users@glassfish.java.net

Application clients and EnitityManager scope.

From: Ryan J <subs_at_jpts.net>
Date: Wed, 09 Apr 2008 19:53:06 -0600

Hi,

I'm wondering if anyone can suggest any strategies or reading with
regards to using an EntityManager in an application client.

I've worked with it enough to have the basics down. I inject an
EntityManagerFactory (using the ACC) and use that to obtain an
EntityManager when I need it.

The thing I'm having a bit of trouble working out is what scope the
EntityMangager should have (ie: application scope, class scope, method
scope).

I'm assuming that a single, application wide EntityManager that exists
for the entire lifecycle of the application client is a bad idea.

I've also tried the other end of things and scoped the EntityManager at
the method level. Every time I wanted to save some data, I'd get a new
EntityManager and call persist or merge.

This approach didn't seem to work to well in conjunction with my data
binding system. Since the EntityManager would return a new instance of
my data, it created a lot of extra state management for me.

As an example, assume I have two object types:

Author
Book

An Author contains a collection of books using FetchType.EAGER and
CascadeType.ALL. Assume an Author and all of its Book(s) have been
loaded and connected to a UI via data binding. Assume the Author
consists of a couple simple strings / text fields and the Book(s) are in
a simple JList (on the same screen).

If I add a book, the @Id will initially be -1, indicating it is new. If
I get an EntityManager and call merge() on the author, the entity
manager will return a copy of the author (and Books) and the @Id of the
new Book will have been set in that copy of the data. The new copy of
the Author is returned because the Author initially passed to the
EntityManager would have been in an unmanaged state. The Author that is
returned by the EntityManager would be in a managed state.

In this example, I would have to save the selection state of my JList
(of books), switch the old Author object for the new one returned by the
EntityManager and restore the selection state of the JList.

Simply ignoring the updated Author object returned by the EntityManager
isn't an option. If the @Id of the newly created book isn't updated,
the next merge() call will create another new Book with the same
information.

Managing portions of the UI state by hand would be ok for a trivial
example like the one I've given, but it gets tedious very quickly as an
application grows.


The other option, as I see it, is to use a class level scope for the
EntityManager. Using the same example above, I would do the following:

I would use an object (ie: AuthorController) to manage resources for a
single author object (ie: 3 authors would mean 3 AuthorControllers).

When a user opens an Author I would create an AuthorController, get an
EntityManager and set it as the EntityManager for that controller and
load the requested data.

Then as the user makes changes, creates and saves data, I can treat the
Author (and its Collection of Books) like a normal managed entity. When
the user closes an Author, the associated AuthorController (and
EntityManager) would also be closed. I have a few questions though.

1. Is this a reasonable way to use an EntityManager?
2. What if a user loads an Author and leaves it open for 2 hours? Is it
ok to have an EntityManager instance around for an extended period of time?
3. Is it ok to have dozens of EntityManager instances around if they're
all managing different sub-sets of data?

Any suggestions or criticisms are welcome. I'm just trying to get a
feel for how to do things properly, so I don't run into problems later.

Ryan