Results 1 to 9 of 9

Thread: Spring, EJB3 and OpenSessionInView

  1. #1

    Question Spring, EJB3 and OpenSessionInView

    Hi,

    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.

  2. #2

    Default

    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.

  3. #3

    Question

    Quote Originally Posted by adambrod View Post
    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.
    Thanks for a very quick reply. I have some questions though:

    - 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?

  4. #4

    Default

    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.

  5. #5
    Join Date
    Apr 2006
    Location
    Montreal, Canada
    Posts
    178

    Default

    Quote Originally Posted by adambrod View Post
    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.
    I'm going through the same process of creating a phase listener to manage transactions and entity managers - basically reimplementing what Seam already offers

    While I do agree that you don't want your "render response" phase to introduce errors in your database, I thought the best way to do this would be to reuse the same EntityManager but bind it to a new, read-only transaction that would be rolled back at the end of the phase. I could be mistaken, but wouldn't a second EntityManager prevent entities loaded in the first EM to access their lazy loaded associations?

    The SPR-3179 phase listener actually does both:
    • before the "restore view" phase, it creates a new EntityManager and binds it to a newly begun read-write transaction
    • after the "invoke application" phase, it commits the transaction, but I don't see whether the EntityManager is closed or not
    • before the "render response" phase, it creates a new EntityManager and binds it to a newly begun read-only transaction
    • after the "render response" phase, it rolls back the transaction, but again I don't see whether the EntityManager is closed or not

    What do you think?

  6. #6

    Default

    Hey Spiff-

    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.

    HTH,
    Adam

  7. #7
    Join Date
    Apr 2006
    Location
    Montreal, Canada
    Posts
    178

    Default

    Hi Adam,

    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.

    Cheers,
    GB
    Last edited by spiff; Feb 5th, 2009 at 05:55 PM.

  8. #8
    Join Date
    May 2005
    Location
    California, US
    Posts
    735

    Default

    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.

  9. #9
    Join Date
    Apr 2006
    Location
    Montreal, Canada
    Posts
    178

    Default

    You're absolutely right. I moved the discussion over here.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •