Anyone want a couple of listen/notify helper classes?

From: Craig Ringer <craig(at)postnewspapers(dot)com(dot)au>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: Anyone want a couple of listen/notify helper classes?
Date: 2009-12-10 04:53:10
Message-ID: 4B207EB6.50602@postnewspapers.com.au
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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.
}

}

Browse pgsql-jdbc by date

  From Date Subject
Next Message Craig Ringer 2009-12-10 13:23:05 Cheapest way to poll for notifications?
Previous Message Kris Jurka 2009-12-09 01:12:08 Re: Bug in metadata.getColumns()/ORDINAL_POSITION