LISTEN/NOTIFY pgconnection goes down java?

后端 未结 1 796
南笙
南笙 2021-02-15 08:53

I am using PostgreSQL DB and applying it\'s LISTEN/NOTIFY functionality. So my listener is at my AS (Application Server) and I have triggers configured on my DB suc

相关标签:
1条回答
  • 2021-02-15 09:32

    The notification listeners are internally maintained by that library as weak references meaning that you have to hold a hard reference externally so they won't be garbage collected. Check out the BasicContext class lines 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));
        }
    
    }
    

    If the GC picks up your listener, calls to "get" on the weak reference will return null and will not fire as seen from lines 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);
          }
    
        }
    
    }
    

    To fix this, add your notification listeners as such:

    /// 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);
    

    Quite an odd use-case for weak references in my opinion...

    0 讨论(0)
提交回复
热议问题