8

Я использую DB PostgreSQL и применяю его функциональность LISTEN/NOTIFY. Таким образом, мой слушатель находится на моем AS (Application Server), и у меня есть триггеры, настроенные в моей БД, так что когда CRUD-операции выполняются в таблице, запрос отправляется в AS. NOTIFY.LISTEN/NOTIFY pgconnection идет вниз java?

СЛУШАТЕЛЬ класс в 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); 

} 

Так как мое AS вверх, я настроил, что при запуске класс слушателя называется (@Startup annotation), и это начать прослушивание на канале.

Теперь это работает отлично, если, например, скажем, для тестирования. Я вручную редактирую свою таблицу в БД, уведомление генерируется и LISTENER получает его.

Однако, когда я программно отправляю запрос UPDATE в таблицу, UPADTE выполняется успешно, но LISTENER ничего не получает.

Я чувствую, что моя связь с LISTENER снижается, когда я отправляю запрос (он также делает соединение для редактирования объектов), но я не уверен. Я читал о постоянных связях и объединенных связях, но не мог решить, как это сделать.

Я использую pgjdbc (http://impossibl.github.io/pgjdbc-ng/) jar для уведомлений async, поскольку соединение jdbc требует опроса.

EDIT:

Когда я пытаюсь выше слушатель опроса с использованием стандартного JDBC баночки (не 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-компонента, а затем он сработал.

+0

Внутри вашего слушателя переменная 'jsonPayload' не существует. Кроме того, используете ли вы такое же соединение для записи своих обновлений?Понятно, что ваша связь с приставщиком выходит из сферы действия и уничтожается GC. –

+0

Я не использую то же соединение. Но я проверил с помощью 'netstat', что соединения были в установленном состоянии, а старое соединение не было потеряно. 'netstat --numeric-ports | grep 5432 | grep my.ip' дал два соединения (один старый и один новый) и оба в состоянии ESTABLISHED:' tcp 0 0 192.168.5.126:5432 192.168.105.213:46802 ESTABLISHED tcp 0 0 192.168.5.126:5432 192.168.105.213:46805 ESTABLISHED' –

+0

@ LukeA.Leber: Пожалуйста, проверьте изменения на вопрос. –

ответ

5

Слушатели уведомлений внутренне поддерживаются этой библиотекой в ​​качестве слабых ссылок, что означает, что вам нужно провести жесткую ссылку извне, чтобы они не собирались сбрасывать мусор. Проверьте класс 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 улавливает ваш слушатель, называет «получить» на нерабочую ссылку возвратит нуль и не будет срабатывать, как видно из линий 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); 

довольно странное потребительной случай для слабых ссылок на мой взгляд ...

+0

Спасибо, ты спас мой день. Я был очень смущен этим – sanket1729