Anyone want a couple of listen/notify helper classes? - Mailing list pgsql-jdbc

From Craig Ringer
Subject Anyone want a couple of listen/notify helper classes?
Date
Msg-id 4B207EB6.50602@postnewspapers.com.au
Whole thread Raw
List pgsql-jdbc
Hi folks

I've just put together a couple of helper classes for the use of
listen/notify in Java, and was wondering if anybody might be interested
in using them. If so, I'll tidy them up a bit and pop them on the wiki
for general use.

The two classes are:



* PgNotificationHelper

   A fairly simple manager of listen/notify events on a connection.
   Provides `observer'-style listener interface and list of listeners
   so that Java objects may easily receive NOTIFY events without having
   to care about the SQL guts. Also provides helpers for managing the
   list of events listened to in the database, so that you can easily
   call "helper.listen(name)" etc to add/remove listeners. Tracks the
   list of listened-to names its self, and can re-listen to them if
   passed a new connection after a connection break. Plays well with
   others - can be used without problems on a connection you're using
   for other things.

   PgNotificationHelper doesn't do periodic polling, you need to do that.
   It also expects you to handle any exceptions it reports while
   working with the conennection you supplied to it.

   PgNotificationHelper is well suited to apps that use the JDBC
   APIs quite directly.



* PgNotificationPoller

   Uses PgNotificationHelper behind the scenes to provide a
   listen/notify interface that does its own periodic polling.
   To do this it uses a dedicated JDBC connection it creates and
   manages its self using user-supplied credentials. The
   connection will be re-created (with appropriate failure backoff)
   if it drops. A daemon thread is used to do the database work.

   PgNotificationPoller is completely thread-safe and no public methods
   ever block to wait for database work. All public methods may be
   called safely from any thread. All communication between the
   PgNotificationPoller and the worker thread is by asynchronous
   messaging.

   PgNotificationHelper is well suited to apps that use connection
   pooling and some kind of ORM layer, where low-level connection
   management is done behind the scenes. However, it doesn't depend
   on any interfaces from any connection pools or ORMs, and works fine
   in their absence. Unlike PgNotificationHelper, though, it does
   cost you an extra JDBC connection to the database.

   All listeners' methods are always sent on the EDT, for ease of
   use in Swing apps. (This could be easily changed if required).

   Currently the user has absolutely no access to the
   PgNotificationPoller's connection. I may extend the class to allow a
   user to "borrow" the connection from the poller to do work on it,
   though, if there's interest in that. Extensions may also be made
   to allow the PgNotificationPoller to manage advisory locks.



I haven't attached the current code, as it needs some JavaDoc love and I
need to fill out the test cases a bit. I thought this might be a common
enough task to tackle, though, that people might be interested in
nicer-to-use interfaces for working with these database features.

After all, something like this is a *wee* bit nicer to use than direct
listen/notify via JDBC:



class MyClass implements PgNotificationPoller.PgNotificationListener {

    // In practice you'd usually maintain one poller for the whole
    // app and pass it in as a param, but for the sake of the example:

    private final PgNotificationPoller poller = new PgNotificationPoller(
           "jdbc:postgresql://localhost/dbname", "username", "password");

    public MyClass() {
        poller.addNotificationListener(this);
        // Tell the poller to issue a LISTEN CUSTOMERS_CHANGED, which
        // will be executed next time the poller's connection is idle.
        poller.listen("CUSTOMERS_CHANGED");
    }

    @Override
    public void notified( PgNotificationPoller poller,
           Connection connection,
           PGNotification n )
    {
        System.out.println("Received notification: " + n.getName()
                + " from " + n.getPID()
                + " with param " + n.getParameter());
    }

    @Override
    public void pollerStatusChanged( PgNotificationPoller poller,
           Status oldStatus,
           Status newStatus )
    {
        // Allows you to act on broken connections and reconnects
        // that might mean you have to compensate for lost notifications.
    }

}


pgsql-jdbc by date:

Previous
From: Kris Jurka
Date:
Subject: Re: Bug in metadata.getColumns()/ORDINAL_POSITION
Next
From: John R Pierce
Date:
Subject: Connection.setReadOnly()