I'm working on a REST webservice that uses hibernate as an OR Mapper. I recently upgraded hibernate from 3.2 to 4.3 and got an error I described here. Basically my transaction got rolled back somewhere and then I got an error when I wanted to use that session again (which is correct hibernate behavior).
I think I figured out why I got that error. It is because when I receive the request a long session is started. This session also opens a transaction that will be open for a longer period of time. Besides this long running session/transaction also some small session/transaction should be opened on the same thread. As far as I found out, all sessions get the same UserTransaction to work with and since the small transactions commit and rollback this transaction I run in the error described in my other post.
Since I'm working with a huge code base it is that easy to change the code so that all that side session run in a different thread (in case that would help) or to refactor the whole service so that only one transaction can be open at any time.
Actual Question starts here
Is there any possibility to start multiple simultaneous sessions/transactions in one Thread? If so, what would I have to do, to tell hibernate to do that? If this is not possible what way of accomplishing a similar behavior would you suggest?
Code snippet I use to create the sessions
Session session = sessionFactory.openSession();
CustomSessionWrapper dpSession = new CustomSessionWrapper(session, this);
if (!session.isClosed() && !session.getTransaction().isActive()) {
session.beginTransaction();
}
The code worked before I upgraded hibernate so the problem should not be in the CustomSessionWrapper or any other custom class.
Thanks a lot in advance!
Related
We recently had a very unexpected issue in PROD which we manage to reproduce but we still don't have a clear explanation of what is causing it and more importantly how to fix it.
Our system is a vendor workflow framework that offers us hooks to add our custom behavior. It is running on WebSphere Application Server and it is a mix of Camel and Spring and EJB. Initially it was pure EJB but a few years ago the vendor added Camel with a view of getting rid of application server.
Now the problem:
The start of processing is a Camel route which is transacted with PROPAGATION_REQUIRED attribute. Part of the processing there is a local call to an EJB method. There is not explicit setting for any of EJB methods exposed apart from being Container managed. This means the EJB call should get the implicit value of REQUIRED. Part of the EJB call there is data change happening. The reference to the EJB is obtained using some code like below:
String repositoryName = MBLLookupUtil.getInstance().getRepositoryName();
RepositoryInstanceFacadeHome facadeHome = MBLLookupUtil.getInstance().getRepositoryInstanceFacadeHome(
repositoryName);
RepositoryInstanceFacade facade = facadeHome.create();
// Here is when the data change happens:
facade.doSomeWork();
The application logs show clearly that the EJB processing is happening in the same thread as the client. After making the call there is more work in the calling client when a Timeout exception happens.
We expect that both data change on client side and that changed as part of the EJB call will be roll backed, however the data changed by EJB call stays committed while the client side (Camel) gets roll backed.
In the spring application context we use WebSphereUowTransactionManager which is the IBM recommended way of configuring transaction manager:
<bean id="txManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
Any hints about what could cause this or how we could further investigate would be great appreciated. Thank you in advance.
UPDATE:
As advised in tomgeraghty3's comment I made a code change to log the value of TransactionSynchronizationManager.isActualTransactionActive() and the result was true
UPDATE 2:
We found out where the issue was by spending hours of analyzing decompiled vendor code. The transaction propagation was configured in an application-context.xml file but it was also overwritten straight in the POJO code with an #Transactional(propagation=REQUIRED_NEW) annotation. We proved that was the problem by removing the POJO class from the vendor jar and adding one with no annotation with the same package in one of ours. Very dirty just to prove our suspicion.
Now our bigger challenge would be to persuade the vendor address the issue. Hope it is just a bug and not an impacting change.
I'm working on a system where things can and will change outside of JPA, so I need a new session for every request, but my JavaEE app deployed into TomEE persists sessions between requests, resulting in entities that are cached when they've since been updated somewhere outside of the app.
I attempted to create a cfg.xml and get the session factory that way, but was just met with exceptions. I also attempted to unwrap the entity manager class to get the factory that way, but got an exception saying the class couldn't be unwrapped. I feel like this may be something to do with how TomEE and Hibernate interact. Are there issues with my current setup. Or am I trying to implement session-per-request wrong,
The problem that you have is not with the session, it is related with the session cache, so what you can do is invalidate your session cache:
session.refresh(entity)
then hibernate will compare database data and entity object data if there are differences then it will execute again an sql query.
session.clear()
will remove everything from the session cache, so you will not get old data.
My project connects to a database using hibernate, getting connections from a connection pool on JBoss. I want to replace some of the reads/writes to tables with publish/consume from queues. I built a working example that uses OracleAQ, however, I am connecting to the DB using:
AQjmsFactory.getQueueConnectionFactory followed by createQueueConnection,
then using createQueueSession to get a (JMS) QueueSession on which I can call createProducer and createConsumer.
So I know how to do what I want using a jms.QueueSession. But using hibernate, I get a hibernate.session, which doesn't have those methods.
I don't want to open a new connection every time I perform an action on a queue - which is what I am doing now in my working example. Is there a way to perform queue operations from a hibernate.session? Only with SQL queries?
I think you're confusing a JMS (message queue) session with a Hibernate (database) session. The Hibernate framework doesn't have any overlap with JMS, so it can't be used to do both things.
You'll need 2 different sessions for this to work:
A Hibernate Session (org.hibernate.Session) for DB work
A JMS Session (javax.jms.Session) to to JMS/queue work
Depending on your use case, you may also want an XA transaction manager to do a proper two-phase commit across both sessions and maintain transactional integrity.
I was also looking for some "sane" way how to use JMS connection to manipulate database data. There is not any. Dean is right, you have to use two different connections to the same data and have distributed XA transaction between them.
This solution opens a world of various problems never seen before. In real life distributed transactions can really be non-trivial. Surprisingly in some situations Oracle can detect that two connections are pointing into the same database and then two-phase commit can be bypassed - even when using XA.
I am working on a project that has Spring based Web Services and Spring Jdbc based persistence.
I have configured a DataSourceTransactionManager to manage the transactions and applied this to the service layer using a Pointcut.
Transaction propagation level is set REQUIRED.
The queries are issued through Spring provided JdbcTemplate.
The problem is that in case of multiple concurrent request to a service i get a MySQLTransactionRollbackException("Deadlock found when trying to get lock; try restarting transaction").
Apparently one of the transactions has obtained a lock which makes the second one fail.
My question is - How should configure Spring to delay the execution of the service until a lock is obtainable, instead of just giving up and throwing an exception?
I can't even catch the exception and try to re-execute the query because I've applied transaction on service layer as an advice keeping my DAOs clean.
I'm hoping to get a declarative solution only (since I am an AOP fanatic & crusader against boilerplate code :-) ). But even programmatic solutions are welcome.
Thanks for your suggestions.
Update -
#ninjalj Yes it was actually a real deadlock. Turns out I was writing my test case incorrectly. Silly me :-(
If I'm not mistaken, that indicates a real deadlock, so you should really retry the transaction. IIRC, a timeout waiting for a lock has "timeout" in the exception message.
I have a Tomcat servlet that incorporates hibernate. It works fine normally. When the servlet starts I initialize hibernate and create a session factory. I then use this session factory to generate sessions when performing various database transactions. So far so good. My problem comes after a long period of inactivity on the servlet (say when the users go home for the night and then try to log in the next morning). Suddenly, I am unable to communicate with the databse. In the logs I see
org.hibernate.exception.JDBCConectionException: Could not execute query.
If I stop and restart Tomcat, reinitializing my servlet and rebuilding my session factory, everything works fine. It is almost like the session factory itself is timing out?
Any ideas?
Thanks,
Elliott
If I stop and restart Tomcat, reinitializing my servlet and rebuilding my session factory, everything works fine. It is almost like the session factory itself is timing out?
It's not the session factory but the connections used by the session factory (e.g. MySQL is well known to timeout connections after 8 hours of inactivity by default). Either:
use a connection pool that is able to validate connections on borrow and to renew them ~or~
increase the idle timeout on the database side
OK. Suppose I use a c3P0 connection pool. How do I specify in the hibernate.cfg.xml file that I want to "validate connections on borrow" or does it do this by default?
The various options when using C3P0 are documented in Configuring Connection Testing. My advice would be to use the idleConnectionTestPeriod parameter:
The most reliable time to test
Connections is on check-out. But this
is also the most costly choice from a
client-performance perspective. Most
applications should work quite
reliably using a combination of
idleConnectionTestPeriod and
testConnectionsOnCheckIn. Both the
idle test and the check-in test are
performed asynchronously, which leads
to better performance, both perceived
and actual.
Note that for many applications, high
performance is more important than the
risk of an occasional database
exception. In its default
configuration, c3p0 does no Connection
testing at all. Setting a fairly long
idleConnectionTestPeriod, and not
testing on checkout and check-in at
all is an excellent, high-performance
approach.
To configure C3P0 with Hibernate, be sure to read the relevant instructions (and to use the appropriate properties, and the appropriate files).