I am writing an application using hibernate + JPA as ORM and postgresql 9.3 as a database, and I need to respond with some Java code to some database events.
To be more precise, I want to create a trigger that uses pg_notify () when a new table is inserted into the table.
I read about this, but all the tutorials were related to jdbc direct connection, not sleeping. I (I think) cannot use hibernation events, because the rows are not inserted through hibernation, but by a third-party application.
Is there a way that I can get notifications sent via pg_notify via sleep mode?
- update
Right now I have a classCastException:
java.lang.ClassCastException: com.sun.gjc.spi.jdbc40.ConnectionWrapper40 cannot be cast to org.postgresql.PGConnection at com.xxx.core.impl.dao.PostgresqlLowLevelNotificationDAOImpl$1.execute(PostgresqlLowLevelNotificationDAOImpl.java:36) at com.xxx.core.impl.dao.PostgresqlLowLevelNotificationDAOImpl$1.execute(PostgresqlLowLevelNotificationDAOImpl.java:1)
I should mention that I am using Glassfish 4.0 as an AS. The connection pool is created on a glass fish and is accessible through the application through jndi. Also, the EntityManager is introduced by the container using Spring. Here is my code:
@Named public class PostgresqlLowLevelNotificationDAOImpl implements PostgresqlLowLevelNotificationDAO{ @PersistenceContext(type =PersistenceContextType.TRANSACTION,synchronization=SynchronizationType.SYNCHRONIZED,unitName="CCPU") private EntityManager em; @Override public ArrayList<PGNotification> getNotifications(){ Session session = em.unwrap(Session.class); PGNotification[] notifications = session.doReturningWork(new ReturningWork<PGNotification[]>() { @Override public PGNotification[] execute(Connection connection) throws SQLException { PGNotification[] notifications = ((PGConnection) connection).getNotifications(); return notifications; } }); return (ArrayList) Arrays.asList(notifications); }
}
- update
I fixed the class exception:
@Override public ArrayList<PGNotification> getNotifications(){ Session session = em.unwrap(Session.class); PGNotification[] notifications = session.doReturningWork(new ReturningWork<PGNotification[]>() { @Override public PGNotification[] execute(Connection connection) throws SQLException { PGConnection pgc = null; if (connection.isWrapperFor(PGConnection.class)) { pgc = (PGConnection) connection.unwrap(PGConnection.class); } PGNotification[] notifications = pgc.getNotifications(); return notifications; } });
But still it seems that I am not receiving notifications.
update ---
After I implemented the solution suggested by Neil, I have this error in Glassfish logs when I undeploy the application:
2014-06-27T11:03:24.278+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.buffer.PooledByteBufAllocator$1] (value [ io.netty.buffer.PooledByteBufAllocator$1@28ad6479 ]) and a value of type [io.netty.buffer.PoolThreadCache] (value [ io.netty.buffer.PoolThreadCache@f9f58cc ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.279+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@267ec117 ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@4bb6e0bf ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.279+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@535d426e ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@fb46e84 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.280+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.internal.ThreadLocalRandom$2] (value [ io.netty.util.internal.ThreadLocalRandom$2@ec3a42a ]) and a value of type [io.netty.util.internal.ThreadLocalRandom] (value [ io.netty.util.internal.ThreadLocalRandom@4e4ec8f8 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.280+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@166c39f2 ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@1b504a5e ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.281+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@34426f54 ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@759b0e99 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.282+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.concurrent.DefaultPromise$1] (value [ io.netty.util.concurrent.DefaultPromise$1@16db9b21 ]) and a value of type [java.lang.Integer] (value [0]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.282+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@166c39f2 ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@2ba59f40 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.282+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.buffer.PooledByteBufAllocator$1] (value [ io.netty.buffer.PooledByteBufAllocator$1@28ad6479 ]) and a value of type [io.netty.buffer.PoolThreadCache] (value [ io.netty.buffer.PoolThreadCache@67a3923 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.283+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@166c39f2 ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@423d2c27 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.283+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.util.Recycler$1] (value [ io.netty.util.Recycler$1@535d426e ]) and a value of type [io.netty.util.Recycler.Stack] (value [ io.netty.util.Recycler$Stack@3e1dd66a ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 2014-06-27T11:03:24.283+0300|SEVERE: The web application [/myApp] created a ThreadLocal with key of type [io.netty.buffer.PooledByteBufAllocator$1] (value [ io.netty.buffer.PooledByteBufAllocator$1@28ad6479 ]) and a value of type [io.netty.buffer.PoolThreadCache] (value [ io.netty.buffer.PoolThreadCache@18e7e902 ]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
I should mention that the destroy () method is called when the application is not deployed. And if I spy with visualVM, the thread is still alive after the application has not been deployed.
public void destroy(){ try{ Statement statement = pgConnection.createStatement(); statement.addBatch("UNLISTEN xxxTest"); statement.executeBatch(); statement.close(); }catch(SQLException sqle) { sqle.printStackTrace(); } }