Listen / Notify
Listen and Notify provide a simple form of signal or interprocess communication mechanism for a collection of processes accessing the same PostgreSQL® database. For more information on notifications consult the main server documentation. This section only deals with the JDBC specific aspects of notifications.
Standard LISTEN , NOTIFY , and UNLISTEN commands are issued via the standard Statement interface. To retrieve and process retrieved notifications the Connection must be cast to the PostgreSQL® specific extension interface PGConnection . From there the getNotifications() method can be used to retrieve any outstanding notifications.
NOTE
A key limitation of the JDBC driver is that it cannot receive asynchronous notifications and must poll the backend to check if any notifications were issued. A timeout can be given to the poll function, but then the execution of statements from other threads will block.
Example 9.2. Receiving Notifications
import java.sql.*;
public class NotificationTest {
public static void main(String args[]) throws Exception {
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:5432/test";
// Create two distinct connections, one for the notifier
// and another for the listener to show the communication
// works across connections although this example would
// work fine with just one connection.
Connection lConn = DriverManager.getConnection(url, "test", "");
Connection nConn = DriverManager.getConnection(url, "test", "");
// Create two threads, one to issue notifications and
// the other to receive them.
Listener listener = new Listener(lConn);
Notifier notifier = new Notifier(nConn);
listener.start();
notifier.start();
}
}
class Listener extends Thread {
private Connection conn;
private org.postgresql.PGConnection pgconn;
Listener(Connection conn) throws SQLException {
this.conn = conn;
this.pgconn = conn.unwrap(org.postgresql.PGConnection.class);
Statement stmt = conn.createStatement();
stmt.execute("LISTEN mymessage");
stmt.close();
}
public void run() {
try {
while (true) {
org.postgresql.PGNotification notifications[] = pgconn.getNotifications();
// If this thread is the only one that uses the connection, a timeout can be used to
// receive notifications immediately:
// org.postgresql.PGNotification notifications[] = pgconn.getNotifications(10000);
for (int i = 0; i < notifications.length; i++) {
System.out.println("Got notification: " + notifications[i].getName());
}
// wait a while before checking again for new
// notifications
Thread.sleep(500);
}
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
class Notifier extends Thread {
private Connection conn;
public Notifier(Connection conn) {
this.conn = conn;
}
public void run() {
while (true) {
try {
Statement stmt = conn.createStatement();
stmt.execute("NOTIFY mymessage");
stmt.close();
Thread.sleep(2000);
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
}