Hibernate IS NOT throwing StaleObjectStateException (DO NOT DO OPTIMISTIC LOCKING) - spring

I am puzzled here. I wanted to implement optimistic locking in my spring hibernate program but the hibernate is not throwing StaleObjectStateException even though I open a data in separate browser and updated it separately.
My Dao looks like this:
public void update(User user) throws StaleObjectStateException{
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
My Pojo look like this:
#Version#Temporal(TemporalType.TIMESTAMP)
#Column(name="timestamp", length=19)
public Timestamp getTimestamp() {
return this.timestamp;
}
Config.xml
<bean name="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<tx:annotation-driven />
<bean name="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
One of my doubt why it is NOT throwing exception is that upon update, the other session timestamp is also updated since the data is persisted? Please help.
Perry

I see that you are using spring transaction manager. So I suppose somewhere you have #Transactional annotation that tracks your transactions. In this case I think that StaleObjectStateExceptionwill be thrown not on execution of update method of you class but when the transaction will be commited. And I also think that spring will wrap hibernate exception into HibernateOptimisticLockingFailureException. So you need to add throws declaration to the method that marked with #Transactional annotation.
If you do not have any transactional annotation than you need to add some or use manual transaction handling in Dao.

Related

Which is the default transaction manager the #Transactional uses?

We have configured multiple transaction managers:
<tx:annotation-driven transaction-manager="transactionManager1" />
<tx:annotation-driven transaction-manager="transactionManager2" />
<tx:annotation-driven transaction-manager="transactionManager3" />
<bean id="transactionManage1"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory1" />
</bean>
<bean id="transactionManager2"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2" />
</bean>
<bean id="transactionManage3"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory3" />
</bean>
However,I don't see a name of transaction manager specified in #Transactional annotation in a service class. I am wondering which transaction manager will be used? The code is working and it looks like it used the first one - "transactionManager1" by default. Do I miss something?
I am wondering which transaction manager will be used?
The behaviour there is probably undefined, but it's most likely to use whichever <tx:annotation-driven> comes first in the context.
There's no reason you should need to do this. If you need fine-grained control over which tx manager to use, then you need to do it programmatically using something like TransactionTemplate. The #Transactional annotation is a convenience, but isn't as flexible as using the underlying API directly.

Two entity managers in Spring

I had done this programmatically at some point - that is creating two entity managers with different data sources and providing them for different services.
However now I am building a webApp using Spring. Thing is that I want to have two entity managers responsible for separate databases. So in my case, half of DAO's would be using emNumber1, and second half would be using emNumber2. Oh and totally different persistence units as I only need to read data from DB1 and then process it and store this data in DB2 in totally different entities.
I am well aware that this problem is and has been going around for sometime now but in different shapes and forms and so I am composing this question only because I could not understand the solutions that were presented withing those googled-up forum threads or they were not applicable to my case. In same cases I could not understand the solution or how to apply it in my case so really sorry for redundant question if it were to be solved by linking a solution from this very own site.
Here is how I find fit to configure a single transaction manager
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/db"
p:username="dbuser"
p:password="dbuser"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="pu1"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"/>
</bean>
Then inside my dao:
public class SimpleDaoImpl implements SimpleDao {
#PersistenceContext
private EntityManager entityManager;
/* methods that use entity manager for transactions and data detcing */
}
So in case of two transaction managers with different data sources how would one specify what entity manager to inject into which DAO or is that impossible in Spring?
Here i have hibernate with two different data sources and i use #Qualifier to specify the session factory like this:
#Autowired
#Qualifier(value="sessionFactoryOne")
private SessionFactory sessionFactoryOne;
#Autowired
#Qualifier(value="sessionFactoryTwo")
private SessionFactory sessionFactoryTwo;
then i get the session from this guys.
In xml config i have two dataSource, sessionFactory and transactionManager, one for each DB.
Works fine ;)
You can do #PersistenceContext(unitName="pu1")

How to apply transactions best practice for read operations in Spring MVC using Hibernate?

As it is mentioned in blogs/books (e.g. Java Transactions Design Strategies by Mark Richards), read operations must have the Propagation.SUPPORTS attribute.
In a simple Spring 3.1 MVC project with Hibernate 4.1 the scenario is:
Declarative transaction management using #Transactional
sessionFactory of org.springframework.orm.hibernate4.LocalSessionFactoryBean
Transaction manager of org.springframework.orm.hibernate4.HibernateTransactionManager
Service class with #Transactional(propagation=Propagation.REQUIRED)
Function of that Service class that only retrieves a resultset (performs read operation) with #Transactional(propagation=Propagation.SUPPORTS)
Function of read operation retieves the resultset using sessionFactory.getCurrentSession().get()
Of course, when a Controller executes the function of read operation, the exception "No Session found for current thread" is raised because a transaction is not started and a session is not obtained.
Based on the above configuration (while it is best e.g. non-invasive, less code etc) the Propagation.SUPPORTS attribute cannot be used unless a transaction is started before with Propagation.REQUIRED or Propagation.REQUIRES_NEW.
How do we use use Propagation.SUPPORTS for read operations without having to start a transaction e.g. with Propagation.REQUIRED before but still taking advantage the benefits of declarative transaction management?
Thank you in advance.
Coder, here is the configuration:
<tx:annotation-driven transaction-manager="txManager"/>
<context:component-scan base-package="com.myapps.service.impl" />
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>.....</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${db.dialect}</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
I disagree with using SUPPORTS for read operations. Use REQUIRED.
A transaction is needed anyway to perform every database operation
Doing several small transactions to read several things at once won't benefit from the first-level cache
There won't be any isolation between all the subsequent reads, meaning that something not visible to the first read might become visible for the second one
you'll get lazy loading exceptions when traversing associations
Transaction is not always required for Propagation.SUPPORTS.
Propagation.SUPPORTS: Support a current transaction, execute non-transactionally if none exists.

No Session found for current thread using JTA TransactionManager

I'm having some trouble migrating to hibernate 4 while using a JTA Transaction Manager.
Maybe you can help, cause I'm all out of ideas.
Software:
Spring: 3.1.1.RELEASE
Hibernate: 4.1.3.Final
Database: Oracle 11g
Application: Ejb 3.0 deployed in Websphere Application Server 7.0 (using #Interceptors(SpringBeanAutowiringInterceptor.class) to initialize the spring context)
Spring configuration:
<context:annotation-config />
<context:component-scan base-package="myServicePackage,myDaoPackage" />
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/MyDataSource" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="myModelPackage" />
<property name="mappingResources" value="queries.xml" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
</bean>
<tx:jta-transaction-manager />
<!-- <bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager" /> -->
<tx:annotation-driven />
Service:
#Service
public class TradeService {
#Autowired
private TradeDao tradeDao;
}
Dao:
#Repository
#Transactional
public class TradeDao {
#Autowired
private SessionFactory sessionFactory;
public Trade getTrade(){
return (Trade) sessionFactory.getCurrentSession().getNamedQuery("get_trade").uniqueResult();
}
Throws:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1041)
at myDaoPackage.TradeDao.getTrade(TradeDao.java:26)
Notes:
I've also tried using #Transactional on the service instead of the
dao. Same result.
Similar config, but using Spring 3.0.5.RELEASE, Hibernate 3.6.5.Final, and TradeDao extending HibernateDaoSupport works.
So, does anyone have any ideas?
I've been trying a lot of things all day today.
My head is spinning and I'm annoyed, so I must be missing something very simple, but at this point I can't really tell :)
I finally got this working.
As I was expecting I was missing just some small configuration :)
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</prop>
</props>
</property>
I found these configuration options earlier while browsing, but for some reason they didn't work when I tried them. Probably I had something else wrong at that time... (see Transaction strategy configuration chapter)
Thank you all for trying to help!
It's probably much like the problem that this person was having: http://forum.springsource.org/showthread.php?121109-Transaction-Propagations-and-Hibernate-4
That is, HibernateDaoSupport (and, presumably, HibernateTemplate) was creating a Session if one wasn't found on the Thread, whereas it sounds like the new approach does not.
EDIT: I just realized that the included link is using a HibernateTransactionManager. I believe that if you use a JtaTransactionManager and do not use a HibernateTemplate, you have to manually apply advice around the target which creates a session.
It might also be something they missed in Spring: https://jira.springsource.org/browse/SPR-9404
By default the #Transactional annotation works on interfaces. Since you're going sans interface, you should add the proxy-target-class="true" attribute to the <tx:annotation-driven /> tag in your configuration.

Spring, Websphere, JMS and Eclipselink Issue

I have an application that runs inside of Websphere, and I am having an issue with persisting JPA entities.
Previously, the application was setup with RESOURCE_LOCAL persistence units, with the Spring JpaTransactionManager, and transactions that were committed explicitly in code.
TransactionStatus transactionStatus = transactionManager.getTransaction( new DefaultTransactionDefinition() );
try {
entityManager.persist( someJpaEntity );
}
catch( Exception exception ) {
transactionManager.rollback( transactionStatus );
throw exception;
}
try {
transactionManager.commit( transactionStatus );
}
catch( TransactionException exception ) {
exception
}
I am working on an enhancement to the application that will allow calls through a Message Driven Pojo linked to a Websphere Queue. I was able to setup a configuration through spring that will allow my application to receive messages through a JMS queue. The spring config looks like:
<jee:jndi-lookup id="jmsConnectionFactory" jndi-name="QueueConnectionFactory"/>
<jee:jndi-lookup id="jmsQueue" jndi-name="DIQueue" />
<!-- A dynamic resolver -->
<bean id="jmsDestResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"/>
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="jmsConnectionFactory"/>
</property>
<property name="destinationResolver">
<ref bean="jmsDestResolver"/>
</property>
</bean>
<bean id="messageListener" class="my.app.FileMessageListener" />
<bean id="exListener" class="my.app.JmsExceptionListener" />
<bean id="msgListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="destination" ref="jmsQueue" />
<property name="messageListener" ref="messageListener" />
<property name="transactionManager" ref="transactionManager" />
<property name="taskExecutor" ref="myTaskExecutor" />
<property name="exceptionListener" ref="exListener" />
</bean>
<bean id="myTaskExecutor" class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
<property name="workManagerName" value="wm/default" />
</bean>
Not sure if there is an issue with my spring setup, but I do receive messages through my Active MQ broker, so that part I seem to be good with.
Now, the issue is, that when I get a message in through JMS, I would call the above code to insert the JPA entity. When the code would run, I would get the message "unable to commit a one phase resource in a two phase transaction", or something similar. What I came to understand is that the Spring JpaTransactionManager does not work with XA or JTA transactions.
So, I worked on moving to the Spring JtaTransactionManager.
I changed everything I Could think of over to use JTA, here is where I declare my transaction manager:
<bean id="transactionManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
Updated my persistence XML:
<persistence-unit name="AppUnit" transaction-type="JTA">
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<jta-data-source>java:APPDS</jta-data-source>
And still, nothing works. My code runs without exception, but nothing gets persisted to the database. The message gets pulled off of the JMS Queue, but no data.
Any suggestions?
I finally got this working, and figured I would post the answer.
There are actually 2 pieces to the puzzle.
First, in Websphere, you need to go to your app server -> TransactionService, and check / enable the "Accept Heuristic Hazard" checkbox. That definitely helped. I am running WAS 7.
The second thing, is you MUST set the property eclipselink.target-server on your persistence unit or your EntityManagerFactory.
That second item definitely did the trick. I tested with the property and without it. Without it, nothing persists. With it, everything works fine.
Here is my EntityManagerFactory, I am using a property placeholder to set the value of the eclipselink.target-server property:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceUnitName" value="MyUnit" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="databasePlatform">
<value>${app.databasePlatform}</value>
</property>
<property name="showSql">
<value>${app.showSql}</value>
</property>
</bean>
</property>
<!-- THIS DID THE TRICK -->
<property name="jpaPropertyMap">
<map>
<entry key="eclipselink.target-server" value="${app.targetServer}"/>
</map>
</property>
</bean>

Resources