Hello, all!
I have a set of JPA classes - all working normally on both JBoss and Glassfish, with one exception. First, for reference, have a look at this code snippet:
@Override
public Hub findByEmail(String email) {
assert (email != null);
Query q = this.entityManager.createNamedQuery("hub.findByEmail");
q.setParameter("email", email);
Hub h = Hub.class.cast(q.getSingleResult());
entityManager.refresh(h); // <----- NOTE THIS LINE
return h;
}
Ok...having laid the groundwork, let me explain the actual scenario. I have a test class (EJB 3.0) which I use to run different tests manually (for now, JUnit test suite to come later). Each test is run as a response to a JSP request (i.e. I have a form through which I indicate which test I'd like to run). The first test persists some entities, the second persists a different set of entities into the db, the third runs queries/fetches on those, etc.
The above code is, precisely, used in the "fetch" tests. Now comes the fun part. In this scenario:
1) create an empty db
2) run population test 1
3) run population test 2
4) run fetch test 1 (which calls the snippet above)
Important: fetch test 1 (test #4) includes traversal of a lazily-loaded one-to-many mapping from Hub to another mapped class.
Also important: on both platforms (JBoss and Glassfish), after test #3 is run, the DB is fully populated correctly (verified via a separate process accessing the same DB).
Now, on JBoss test 4 returns the expected result. The lazily-loaded mapping is traversed normally, and the expected entities are retrieved from it. Thus, the test is successful.
On Glassfish however the behavior is wrong - nothing is fetched, because when an attempt is made to traverse the lazy mapping, it is returned empty. This can be resolved in two ways (that I've found at this point):
- Take down the appserver and bring it back up, shortcutting to test 4 (i.e. skip the first 3 tests).
- Add the line with the refresh() call (noted above in the code snippet). With this line in place, everything works as expected in Glassfish.
However, you'll notice that the code snippet involves a query. Shouldn't the object have already been refreshed (if necessary) by being obtained from a query? I.e. shouldn't the refresh() call be wholly unnecessary given the context?
Again - this seems to me to be a stale object issue in a cache somewhere (at least, it's what it smells like). This is because it works fine when the appserver is restarted from scratch (no cache yet), or a cache flush of the object (via the refresh() call) is executed.
Thoughts? Suggestions?
Cheers.
[Message sent by forum member 'drivera']
http://forums.java.net/jive/thread.jspa?messageID=478450