我正在使用postgresql db并应用其LISTEN/NOTIFY
功能。因此,我的侦听器在我的AS(应用程序服务器)上,并且我在DB上配置了触发器,因此当在表上执行CRUD操作时,请发送NOTIFY
请求。
侦听器 java中的类:
@Singleton
@Startup
NotificationListenerInterface.class)
public class NotificationListener extends Thread implements NotificationListenerInterface {
@Resource(mappedName="java:/RESOURCES")
private DataSource ds;
@PersistenceContext(unitName = "one")
EntityManager em;
Logger logger = Logger.getLogger(NotificationListener.class);
private Connection Conn;
private PGConnection pgConnection = null;
private NotifyRequest notifyRequest = null;
@PostConstruct
public void notificationListener() throws Throwable {
System.out.println("Notification****************");
try
{
Class.forName("com.impossibl.postgres.jdbc.PGDriver");
String url = "jdbc:pgsql://192.xx.xx.126:5432/postgres";
Conn = DriverManager.getConnection(url,"postgres","password");
this.pgConnection = (PGConnection) Conn;
System.out.println("PG CONNECTON: "+ pgConnection);
Statement listenStatement = Conn.createStatement();
listenStatement.execute("LISTEN notify_channel");
listenStatement.close();
pgConnection.addNotificationListener(new PGNotificationListener() {
@Override
public void notification(int processId, String channelName, String payload){
System.out.println("*********INSIDE NOTIFICATION*************");
System.out.println("Payload: " + jsonPayload);
}
因此,我已经配置了在启动时调用侦听器类(@Startup annotation
),并且在频道上开始侦听。
现在可以很好地工作,如果可以进行测试,我会在DB中手动编辑我的表格,并生成通知并收到它。
但是,当我在表上编程发送更新请求时,Upadte已成功执行,但听众没有收到任何内容。
我觉得当我发送请求时,听众的联系会降低(这也与编辑实体建立了连接),但我不确定。我阅读了有关永久连接和汇总连接的信息,但无法决定如何追求。
我正在使用pgjdbc(http://impossibl.github.io/pgjdbc-ng/)jar用于异步通知,因为JDBC连接需要进行轮询。
编辑:
当我使用标准JDBC JAR(而非PGJDBC)尝试上述侦听器时,我会收到通知。
我愿意 PGNotification notif[] = con.getNotifications()
我收到通知,但是这样做不同步,就像下面没有通知。
pgConnection.addNotificationListener(new PGNotificationListener() {
@Override
public void notification(int processId, String channelName, String payload){
System.out.println("*********INSIDE NOTIFICATION*************");
}
已解决:
我的侦听器在执行函数执行后,由于我的侦听器具有函数范围, 。因此,将其放入我的启动bean类的成员变量,然后起作用。
通知听众内部维护该库作为弱参考,这意味着您必须在外部持有硬参考,以免收集垃圾。查看BasicContext类行642-655:
public void addNotificationListener(String name, String channelNameFilter, NotificationListener listener) {
name = nullToEmpty(name);
channelNameFilter = channelNameFilter != null ? channelNameFilter : ".*";
Pattern channelNameFilterPattern = Pattern.compile(channelNameFilter);
NotificationKey key = new NotificationKey(name, channelNameFilterPattern);
synchronized (notificationListeners) {
notificationListeners.put(key, new WeakReference<NotificationListener>(listener));
}
}
如果GC接您的听众,请打电话给" get"弱参考将返回null,并且不会从第690-710行中看到的发射。
@Override
public synchronized void reportNotification(int processId, String channelName, String payload) {
Iterator<Map.Entry<NotificationKey, WeakReference<NotificationListener>>> iter = notificationListeners.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<NotificationKey, WeakReference<NotificationListener>> entry = iter.next();
NotificationListener listener = entry.getValue().get();
if (listener == null) {
iter.remove();
}
else if (entry.getKey().channelNameFilter.matcher(channelName).matches()) {
listener.notification(processId, channelName, payload);
}
}
}
要解决此问题,请添加您的通知听众:
/// Do not let this reference go out of scope!
PGNotificationListener listener = new PGNotificationListener() {
@Override
public void notification(int processId, String channelName, String payload) {
// interesting code
};
};
pgConnection.addNotificationListener(listener);
我认为弱参考的一个奇怪用例...