【发布时间】:2016-10-21 08:28:22
【问题描述】:
我正在使用 PostgreSQL DB 并应用它的 LISTEN/NOTIFY 功能。因此,我的侦听器位于我的 AS(应用程序服务器)上,并且我在我的数据库上配置了触发器,以便在对表执行 CRUD 操作时在 AS 上发送 NOTIFY 请求。
LISTENER类在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 进行异步通知,因为 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 类的成员变量中,然后它就可以工作了。
【问题讨论】:
-
在您的监听器中,变量 'jsonPayload' 不存在。另外,您是否使用相同的连接来编写更新?您与附加的侦听器的连接超出范围并被 GC 销毁是可行的。
-
我没有使用相同的连接。但我使用
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 -
@LukeA.Leber:请检查问题的编辑。
-
@LukeA.Leber:由于我的连接没有关闭,我感觉我注册的
pgConnection.addNotificationListener(new PGNotificationListener() {})的监听器退出了会话。有cmets吗? -
通知监听器由该库作为弱引用在内部维护,这意味着您必须在外部持有硬引用,这样它们就不会被垃圾收集。查看 BasicContext 类: synchronized (notificationListeners) { notificationListeners.put(key, new WeakReference
(listener));如果 GC 拾取您的侦听器,对弱引用的“get”调用将返回 null 并且不会触发。
标签: java postgresql database-connection connection-pooling pg-jdbc