LISTEN / NOTIFY pgconnection down java? [英] LISTEN/NOTIFY pgconnection goes down java?

查看:615
本文介绍了LISTEN / NOTIFY pgconnection down java?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用PostgreSQL数据库并应用它的 LISTEN / NOTIFY 功能。所以我的监听器在我的AS(应用程序服务器),我有触发器配置在我的DB上,使得当对表执行CRUD操作时,在AS上发送一个 NOTIFY 请求。

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 such that when CRUD operations are performed on a table a NOTIFY request is sent on AS.

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注释),它开始在频道上侦听。

So as my AS is up, I have configured that at startup the listener class is called (@Startup annotation) and it's start listening on the channel.

现在这个工作正常,如果像测试我手动编辑数据库中的表,通知生成和LISTENER收到它。

Now this works fine if like say for testing I edit my table in DB manually, the notification is generated and the LISTENER receives it.

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

However, when I programmatically send a UPDATE request on the table, the UPADTE is performed successfully but LISTENER is not receiving anything.

我觉得我的LISTENER连接一个请求(它也使一个连接编辑实体),但我不知道。我读了关于永久连接和池连接,但不能决定如何追求。

I feel my connection of the LISTENER goes down when I send a request (it also makes a connection to edit entities), but I am not sure. I read about permanent connections and pooled connections, but not able to decide how to pursue that.

我使用pgjdbc( http://impossibl.github.io/pgjdbc-ng/ )jar作为jdbc连接需要轮询的异步通知。

I am using pgjdbc (http://impossibl.github.io/pgjdbc-ng/) jar for async notifications as jdbc connection requires polling.

EDIT:

当我尝试上述侦听器并使用标准的jdbc jar(不是pgjdbc),我得到通知。

When I try the above listener with polling by using the standard jdbc jar (not pgjdbc), I get the notifications.

我做
PGNotification notif [] = con.getNotifications

I do PGNotification notif[] = con.getNotifications() and I get notifications, however doing it asynchronously like below I don't get notifications.

    pgConnection.addNotificationListener(new PGNotificationListener() {

         @Override
         public void notification(int processId, String channelName, String payload){

            System.out.println("*********INSIDE NOTIFICATION*************");
         }

已解决:

我的监听器

My listener was going out of scope after the function execution was completed as my listener had the function scope. So kept it into a member variable of my startup bean class and then it worked.

推荐答案

通知监听器在内部由弱引用维护,意味着你必须在外部保存一个硬引用,这样它们不会被垃圾回收。检查BasicContext类行642 - 655:

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

}

如果GC拾取您的监听器,对弱引用的get调用将返回null并且不会从690 - 710行中看到。

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...

这篇关于LISTEN / NOTIFY pgconnection down java?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆