Hibernate 4 upgrade, COMMIT not being issued - java

I am attempting to upgrade our code base from Hibernate 3.6 to 4.0 (just as a first step into getting us more up to date). I am hitting an issue where a COMMIT is not being issued even though we are calling the commit() after making sure the transaction is isActive().
When running some queries successfully against the Postgres database, I see this in the Postgres logs:
2014-12-30 20:09:39 CST LOG: execute <unnamed>: SET extra_float_digits=3
2014-12-30 20:09:39 CST LOG: execute S_1: BEGIN
2014-12-30 20:09:39 CST LOG: execute <unnamed>: -- This script........
Notice the BEGIN there, and then here's an example of the simple commit call:
if (sf.getCurrentSession().getTransaction().isActive()) {
sf.getCurrentSession().getTransaction().commit();
}
I have debugged down into AbstractTransactionImpl and am looking at a Jdbc4Connection commit() method, and see that the actual COMMIT call is being skipped.....but I don't know why. Here's the if statement that this is failing on (it is in AbstractJdbc2Connection).
if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
executeTransactionCommand(commitQuery);
So, apparently our transactionstate is == ProtocolConnection.TRANSACTION_IDLE. However, I'm not entirely sure what that entails, and why are we getting this issue when the transaction says it isActive()?
NOTE: this same exact code worked for us on Hibernate 3.6.
Thanks.
UPDATE: I debugged further, and it looks like there are many ProtocoalConnectionImpl objects being constructed, does that indicate a problem on our software side that is doing something it shouldn't? Like does that indicate that we're opening connections that are just hanging around? Thanks for any more insight.

So it turns out I was doing something incorrect (surprise). There's a good reason that the TransactionState was showing as TRANSACTION_IDLE and not issuing a commit.
I had seen in multiple places on the internetz where people were getting access to a JDBC connection in the new Hibernate 4.x land by getting access to the underlying ConnectionProvider (sort of like this: https://stackoverflow.com/a/21271019/115694).
However, the problem with doing that is that you are getting a BRAND NEW connection....instead of the connection associated with the current session. This is a pretty big no-no, or at least for us it was.
You do have to in fact do what the person says in this answer:
https://stackoverflow.com/a/3526626/115694
Basically, you MUST use the Work API.

Related

Best way to solve conflict between EclipseLink #Version Timestamp-Field and DB2

In the current project I'm working on, we are using EclipseLink as JPA-Provider. In the background is a DB2-database.
We want to introduce "Optimistic Locking" with the restriction only using Timestamp-fields. Furthermore, these timestamp fields are CURRENT TIMESTAMP fields, so when updating an entity, the CURRENT TIMESTAMP field updates the value itself. This is necessary to guarantee the reliability of the whole system.
When annotating the attribute of an entity with #Version, I get the following error message:
Internal Exception: com.ibm.websphere.ce.cm.StaleConnectionException: THE SQL STATEMENT IS NOT SUPPORTED. SQLCODE=-142, SQLSTATE=42612, DRIVER=4.22.29
Error Code: -142
Call: VALUES CURRENT TIMESTAMP
Query: ValueReadQuery(sql="VALUES CURRENT TIMESTAMP")
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:767)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:275)
[…]
Note: I only get this error message when using the mentioned annotation.
My research resulted in the following:
Internal Exception: com.ibm.websphere.ce.cm.StaleConnectionException:
--> A StaleConnectionException is an exception that is generated by the WebSphere Application Server database connection code when a JDBC driver returns a fatal error from a connection request or operation. In WebSphere Application Server, the StaleConnectionException is issued when the database vendor issues an exception indicating that a connection currently in the connection pool is no longer valid. ( https://developer.ibm.com/answers/questions/205910/how-to-resolve-the-staleconnectionexception-in-web/ )
THE SQL STATEMENT IS NOT SUPPORTED. SQLCODE=-142,
--> An SQL statement was detected that is not supported by the database. The statement might be valid for other IBM® relational database products or it might be valid in another context. For example, statements such as VALUES and SIGNAL or RESIGNAL SQLSTATE can be used only in certain contexts, such as in a trigger body or in an SQL Procedure. ( https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/codes/src/tpc/n142.html )
SQLSTATE=42612,
--> Seems to be internal, nothing for my relevance
After getting more into the topic, I came across the following link, which appears as the most encouraging so far:
https://www.idug.org/p/fo/et/thread=36380
In summary, the suggested way is to extend org.eclipse.persistence.platform.database.DB2MainframePlatform and manipulate the generated SQL-statement.
My expectation is, that there should be a better way, since this should be a standard-case for the framework. If not, is there an more proper/better way to solve this problem?

Grizzly maxPendingBytes property ignored

I'm developing a project using Grizzly 2.3.22 with its Websocket support. Everything was OK until OOM happened. Looking through the dump I found that all the memory was eaten up by a single org.glassfish.grizzly.nio.transport.TCPNIOConnection holding a huge (1,5GB) write queue. I guess one of the client developers was debugging their connected application and stopped on a breakpoint for a long time. Anyway, this can easily happen if a client has a very slow connection - my server should be ready for that.
In the Grizzly documentation I found the maxPendingBytes property, which seem like a solution, at least for now. But I cannot get it to work at all. I set log level to ALL for AbstractNIOAsyncQueueWriter, connect with the client, put it on hold and observe how the server's queue grows like this:
TRACE 2016-07-05 21:02:26.330 [nioEventLoopGroup-2-1] o.g.g.n.AbstractNIOAsyncQueueWriter - AsyncQueueWriter.write connection=TCPNIOConnection{localSocketAddress={/127.0.0.1:8445}, peerSocketAddress={/127.0.0.1:56185}}, record=org.glassfish.grizzly.asyncqueue.AsyncWriteQueueRecord#1e35bafb, directWrite=false, size=165, isUncountable=false, bytesToReserve=165, pendingBytes=16170
TRACE 2016-07-05 21:02:26.368 [nioEventLoopGroup-2-1] o.g.g.n.AbstractNIOAsyncQueueWriter - AsyncQueueWriter.write connection=TCPNIOConnection{localSocketAddress={/127.0.0.1:8445}, peerSocketAddress={/127.0.0.1:56185}}, record=org.glassfish.grizzly.asyncqueue.AsyncWriteQueueRecord#3d6e05dd, directWrite=false, size=165, isUncountable=false, bytesToReserve=165, pendingBytes=16335
...
When I set maxPendingBytes=10000 I expect an exception thrown when the pendingBytes from the log above becomes larger than 10000, but it doesn't happen.
Moreover, I tried debugging the server with the Grizzly's source code, and found that while the property's value does get assigned to the NIOConnection.maxAsyncWriteQueueSize field, the AbstractNIOAsyncQueueWriter.canWrite(...) method - the only place where the field seems to be used - is never called.
I'm at a loss. Am I missing something here?

"Destroying connection that could not be successfully matched"

I have an application that seems to work fine, but if I browse the log files I see a lot of these kind of errors:
2015-06-04 08:23:55,656 WARN [org.jboss.resource.connectionmanager.InternalManagedConnectionPool] [DA366C7824A976BA8D1121A6E9A4F1C1.Node23] Destroying connection that could not be successfully matched: org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener#5d115719[state=NORMAL mc=org.apache.jackrabbit.jca.JCAManagedConnection#3aed875b handles=0 lastUse=1433398630770 permit=false trackByTx=false mcp=org.jboss.resource.connectionmanager.JBossManagedConnectionPool$OnePool#45ccbfb9 context=org.jboss.resource.connectionmanager.InternalManagedConnectionPool#53f2e7c xaResource=org.apache.jackrabbit.jca.TransactionBoundXAResource#40518596 txSync=null]
I am very curious what the error "Destroying connection that could not be successfully matched" exactly means. Google doesn't seem to help me too much on this one.
We work with JBoss 4.0.5.GA and JackRabbit 1.4 (I know it's old, but that's the way it is).
Just Googled and got the below link of 4.2 brancode
Based on code, while retrieving connection from pool, first it checks
1. Does it has managed Connection
1a. if that has Managed Connection, it checks it is in good shape to return by doing matching algorithm.
1b. if it found it is not in valid state ( not matched ) . it is destroy the Managed connection and create new connection ( or retrieve another Managed connection ) and return it.
2. if it doesnt found any managed connection, create new connection and return it
And this is Warning message from thier source code
//Match did not succeed but no exception was thrown.
//Either we have the matching strategy wrong or the
//connection died while being checked. We need to
//distinguish these cases, but for now we always
//destroy the connection.
log.warn("Destroying connection that could not be successfully matched: " + cl);
At any case , have you overridden GWConnectionRequestInfo equals method ?
Your application may work fine, but it is not effectively using connection pool, since it is destroying lot of managed connection due to different reason. i would analysis more and find reason behind why it is not matching
Ad per thier comment , you connection may already closed / matching not working due to different reason.

How to stop ongoing java.sql.statement.executeQuery()?

I'm using latest derby10.11.1.1.
Doing something like this:
DriverManager.registerDriver(new org.apache.derby.jdbc.EmbeddedDriver())
java.sql.Connection connection = DriverManager.getConnection("jdbc:derby:filePath", ...)
Statement stmt = connection.createStatement();
stmt.setQueryTimeout(2); // shall stop query after 2 seconds but id does nothing
stmt.executeQuery(strSql);
stmt.cancel(); // this in fact would run in other thread
I get exception "java.sql.SQLFeatureNotSupportedException: Caused by: ERROR 0A000: Feature not implemented: cancel"
Do you know if there is way how to make it work? Or is it really not implemented in Derby and I would need to use different embedded database? Any tip for some free DB, which I can use instead of derby and which would support SQL timeout?
As i got in java docs
void cancel() throws SQLException
Cancels this Statement object if both the DBMS and driver support aborting an SQL statement. This method can be used by one thread to cancel a statement that is being executed by another thread.
and it will throws
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
you can go with mysql.
there are so many embedded database available you can go through
embedded database
If you get Feature not implemented: cancel then that is definite, cancel is not supported.
From this post by H2's author it looks like H2 supports two ways to timeout your queries, both through the JDBC API and through a setting on the JDBC URL.
Actually I found that there is deadlock timeout in derby as well only set to 60 seconds by default and I never have patience to reach it :).
So the correct answer would be:
stmt.setQueryTimeout(2); truly seems not working
stmt.cancel(); truly seems not implemented
But luckily timeout in database manager exists. And it is set to 60 seconds. See derby dead-locks.
Time can be changed using command:
statement.executeUpdate("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY(" +
"'derby.locks.waitTimeout', '5')");
And it works :)

Postgres JDBC: Especific error code of PSQLException?

When writing java code that uses an Oracle database, one can always catch SQLException an read an specific Oracle error with e.getErrorCode(). For example, error 28001 means expired password, 28000 is blocked account, 1017 is wrong user/passsword, etc.
That way I can manage different errors the appropiate way.
But with PostgreSQL databases e.getErrorCode() always returns 0, even when catching Postgres-specific PSQLException.
The Question
Is there a way that I don't know of to get an specific error code for a Postgres database exception in Java other than trying to parse the error message (which by the way could be in any localized language)?
Have you tried looking at getSqlState() instead? See also: http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html

Categories

Resources