LISTEN / NOTIFY pgconnection关闭java?

我正在使用PostgreSQL DB并应用它的LISTEN/NOTIFYfunction。 所以我的监听器在我的AS(应用服务器)上,并且我在我的数据库上配置了触发器,这样当在表上执行CRUD操作时,在AS上发送NOTIFY请求。

java中的LISTENER类:

  @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); } 

因此,当我的AS启动时,我已经配置了在启动时调用监听器类( @Startup annotation )并且它开始在通道上监听。

现在这个工作正常,如果说测试我手动编辑DB中的表,生成通知并且LISTENER接收它。

但是,当我以编程方式在表上发送UPDATE请求时,UPADTE成功执行但LISTENER没有收到任何内容。

当我发送请求时,我觉得我的LISTENER连接断开了(它也建立了与编辑实体的连接),但我不确定。 我读到了永久连接和汇集连接,但无法决定如何实现这一点。

我正在使用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(listener)); } } 

如果GC选择了你的监听器,那么对弱引用的“get”调用将返回null并且不会触发,如第690-710行所示。

  @Override public synchronized void reportNotification(int processId, String channelName, String payload) { Iterator>> iter = notificationListeners.entrySet().iterator(); while (iter.hasNext()) { Map.Entry> 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); 

在我看来,弱引用的用例相当奇怪……