PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

LISTEN/NOTIFY pgconnection fällt aus Java?

Die Benachrichtigungs-Listener werden von dieser Bibliothek intern als schwache Referenzen verwaltet, was bedeutet, dass Sie eine harte Referenz extern halten müssen, damit sie nicht von der Garbage Collection erfasst werden. Schauen Sie sich die BasicContext-Klassenzeilen 642 - 655 an:

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

}

Wenn der GC Ihren Listener abholt, geben Aufrufe zum "Get" auf der schwachen Referenz null zurück und werden nicht ausgelöst, wie aus den Zeilen 690 - 710 zu sehen ist

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

    }

}

Um dies zu beheben, fügen Sie Ihre Benachrichtigungs-Listener wie folgt hinzu:

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

Meiner Meinung nach ein ziemlich seltsamer Anwendungsfall für schwache Referenzen ...