Hello everybody!
I hope you can help me to get a better understanding of how Persistence Contexts get propagated... I spent a lot of time with this problem but am still not sure of what happens behind the scenes..
Here follows a short description of what I have done..
I am using
EJB 3.1 together with JPA2 (eclipseLink) and have the following Entities (simplified):
They model the fact that a Testsuite groups several Tests which fall under a specific name (e.g.: "Standard testsuite"). Every time a Testsuite is executed on a Server, a file is produced that looks something like this:
Testsuite: Standard testsuite
Executed on: Server1
Started at: 2011-10-10 10:11:24
TEST-1024 "Test with name X": Success
TEST-1025 "Test whit another name": Failure
...
At this point, other Entities come into play:
The idea is that an output File as the one above describes a TestsuiteRun, which has an association to the TestSuite that got executed (its name is Unique) together with a collection of TestRuns, each corresponding to a
Test. For brevity, in the pseudo-code above I've omitted to specify that most of the associations are bidirectional, i.e. a Test knows all of its TestRuns (and viceversa); a Machine knows all of the TestsuiteRuns which got executed on it; a TestRun knows the TestsuiteRun it belongs to, and so on..
Now, my application parses a file at a time with the twofold aim of:
inserting (if they have not been already stored) new Testsuites/Tests/Server into the DB creating a TestsuiteRun object together with all the related TestRuns.
For better performances at point 1), I use a cache object, which gets initialized with pre-existing data from the DB and is responsible for adding new records when it is the case. Here is a reduced version of it:
All of the DAOs use a Transaction-scoped EntityManager:
As you can see, I use an extended PersistenceContext and every time I read or write to the DB I use em.merge() in order to keep the entities managed. I have read in the book "Pro JPA 2" that in situations like this the PC gets propagated (in my case from Cache to TestDAO): this should mean that doing testDao.persist(t) within retrieveTestCreateIfNotPresent() should be enough to make sure t remains managed (hence the em.merge() in this case could be omitted)?
The situation is more unclear when the file parser comes into play. The code which does the job is something like:
Being the TestsuiteRunBuilder declared as follows:
Also this class uses an Extended PC and such a bean should live only in the time span which goes from the beginning of the file parsing to the insertion into the DB (build is annotated with Remove). Of course the associations of TestsuiteRun are instructed to propagate merge..
You can see that I've marked Cache as Singleton, as I'd like to let the cache remain in memory also for the next file..
The application seems to work, but I am not really sure why.. What happens for example when I parse the second file? In what relation is the PersistenceContext of the new (the 2nd) TestsuiteRunBuilder object with that of Cache (which should be still "alive")?
I am really, really confused... What shall I change in this design? Isn't there a way to make things easier?
Thanks a lot for your help!
Bye!