-
1. Re: After entityManager.find(), no session or session was closed
smarlow Dec 2, 2011 12:19 PM (in response to bohl)Thanks for reporting this important issue and posting the above information. It appears that AS6 has a bug, in that the entities are not detached until the business method completes, instead of when the entity manager invocation completes.
I also rejected AS7-2781 after further discussion and verifying that the entities should be detached when the entity manager (transaction scoped persistence context used with no active jta transaction) returns. I would like to explore improving this (in a future JPA specification, which IMO would be a good improvement). No promises on the JPA specification changing, there may be good reasons for the current behaviour that cannot be addressed. I think that you can follow the JPA 2.1 expert group discussion here, if your interested.
I think that Seam 2 might do some special tricks, to avoid this problem. I'm not sure how they do that but I think they hook into the persistence provider at a lower level to do the magic.
I assume you don't want to EAGER fetch the collection, otherwise you would of made that change. EAGER fetch would be one way of fixing this.
I think that you want to make the business method transactional like a session bean would of been (if you used one). Look for @Transactional here. Or look at this example of using @Stateful.
Write back if that helps or doesn't.
Scott
-
2. Re: After entityManager.find(), no session or session was closed
bohl Dec 4, 2011 4:36 PM (in response to smarlow)Hi Scott, thanks for all these insights. I realized that the kitchensink example you mentioned and the "jboss-javaee6-webapp" maven template I used are pretty much the same application. Now imho there's something wrong with it, since all I did to produce the "no session" exception, was add one lazy-loaded property to the "Member" class in the "kitchensink"-model, and then try to access in MemberListProducer#retrieveAllMembersOrderedByName.
If the kitchensink example is intended to be used as a starting point for new apps (why publish it as a maven template otherwise?), then there should imho at least be a comment indicating that the entities retrieved in MemberListProducer#retrieveAllMembersOrderedByName will get auto-detached. Alternatively, the code could demonstrate how to fetch them "the right way" so that they won't get auto-detached. Because detached entities are usually not what developers expect or want.
-
3. Re: After entityManager.find(), no session or session was closed
smarlow Dec 4, 2011 8:17 PM (in response to bohl)In KitchenSink, MemberListProducer is not using @Stateful, sorry about the incomplete information. It looks like MemberRegistration is using @Stateful.
Rather than reproducing the bug, with KitchenSink, instead just verify that JTA transactions are started MemberListProducer member functions are invoked (you could enable TRACE logging in as7/standalone/configuration/standalone.xml if its not obvious).
I like your idea for a change to the KitchenSink example. Maybe that could get added to the section below the code:
Line Number
32 - 34 The observer method is notified whenever a member is created, removed, or updated. This allows us to refresh the list of members whenever they are needed. This is a good approach as it allows us to cache the list of members, but keep it up to date at the same time.
Advanced: Entities loaded without an active JTA transaction, are detached as soon as the EntityManager method returns. This can cause problems if FetchType.LAZY is used as the lazy fetch will not occur in time.
What happens if you add @Transactional to MemberListProducer#retrieveAllMembersOrderedByName? Does that succeed in making the member function transactional and your added code in that method succeed in reading the lazy data?
Keep in mind, that enties are detached after the JTA transaction completes, so you probably want to also make the caller to MemberListProducer#retrieveAllMembersOrderedByName @Tranactional (if the test succeeds). That way the JTA transaction will start at a higher level (given you more time to read the lazy parts before the entities are detached).