Dec 22nd, 2008, 08:53 AM
Spring, EJB3 and OpenSessionInView
I used Spring+JSF+JPA before and now I'm using JSF+EJB3. I read the reference documentation about using Spring with EJB but found no answers for my questions. So I'd like to post them here:
- If I use Spring's OpenSessionInView filter, then can I say that I will not get the LazyInitializationException anymore (EJBs are the ones that access the database, not some Spring POJO DAOs)?
- At this time, I have only one above question
Thanks for any of your comments.
Dec 22nd, 2008, 09:27 AM
You won't get LazyInitializationExceptions if you use Spring's OpenEntityManagerInViewFilter (not Session). However, if you are using JSF I recommend not using OpenEntityManagerInViewFilter and instead use a JSF PhaseListener. Often times it is good to have a new EntityManager for the VIEW phase.
Dec 22nd, 2008, 10:01 AM
Thanks for a very quick reply. I have some questions though:
Originally Posted by adambrod
- Is there any documentation about open a new entityManager in a jsf phase listener?
- I found only 1 example of open a new entityManager in a jsf phase listener here: http://jira.springframework.org/browse/SPR-3179. I will check to see if it works, but do you use the same thing or something else?
- Why is it better to have a new entityManager for the view phase?
Dec 22nd, 2008, 11:09 AM
I haven't used JSF for a couple years, but Seam has a PhaseListener that does the trick.
The reason you want two EntityManagers for each JSF request is because if you have any errors saving data (in the update phases), you don't want the exceptions to be thrown while you are rendering the next view. You want to update your data, save to the DB (and generate any errors, if there are any), then the view can have its own EM where there won't be any DB-related errors.
Feb 5th, 2009, 02:54 PM
Feb 5th, 2009, 03:14 PM
Are you using Container-managed transactions? I'm assuming you are not using extended persistence contexts. If so, then each time you create a new Transaction you will be creating a new EntityManager. Each EntityManager is independent and doesn't know about any entity that was loaded in another EM. So if any entities are loaded during the Invoke Application phase, they will need to be reloaded during the render phase.
If you are managing transactions yourself, you could create one EntityManager for the entire request. You could start a Txn at the beginning and commit it after Invoke Applicaiton. Finally, you could close the EM after the render response phase (without persisting any changes to the DB).
If you are using Container Managed transactions, I would recommend not starting a transaction at all during the Render Response. There is some overhead in the appserver and the DB if you create a transaction. If there is no transaction, then there is nothing to rollback. Of course, you *might* want a transaction if you want to guarantee read-consistency - that depends on your application, but it is much more expensive.
Feb 5th, 2009, 05:50 PM
Thanks for your answers, it confirms a few of my thoughts.
The SPR-3179 phase listener uses Spring's PlatformTransactionManager so it has full control over transactions, although the underlying implementation may delegate to container transactions. This will be our case since we'll be using WebLogic. What I'm especially wondering is when the EntityManagers it creates will be closed - as far I can see, there are no explicit calls to close them, but maybe the Spring classes do close them? I'll have to investigate that.
Reusing the same EntityManager seems essential to me. If entities are loaded by the invoke application phase but not completely, I want them to be usable in the render response phase. From what I gather this wouldn't be possible using a 2nd EntityManager.
As for the render response transaction, one would be opened anyway by the database for every read operation, so in the end it might less expensive to create one and roll it back than letting the database possibly create many of them. This is Seam's approach as far as I know.
This listener seems awfully simple compared to JpaTransactionManager, I can't help but think that lots of issues haven't been addressed. For now, a solution combining the OpenEntityManagerInViewFilter with a @Transactional invoke application method seems a lot more stable.
Last edited by spiff; Feb 5th, 2009 at 05:55 PM.
Feb 5th, 2009, 06:52 PM
I'm wondering if you might be missing out on some useful feedback because this is in the wrong area; it should be in the Data Access forum.
Feb 5th, 2009, 07:49 PM
You're absolutely right. I moved the discussion over here.