JPA DAO in Desktop Applicationhttps://www.eclipse.org/forums/index.php/mv/msg/152546/480317/#msg_480317
I've got one more question and hopefully someone can help me out here, since all
tutorials and pages I've found for JPA dont cover the DAO usage. At least not
for J2SE environments. In a Container I can just put a @EntityManager annotation
on my DAO and everything is fine but I have no clue how I should do this for my RCP.

But maybe I should start by what I already have. EclipseLink is started as
rcp-bundle and I can obtain the EntityManagerFactory for my persistence.xml. I
am also able to create EntityManger but I dont know what is the right/efficient
way for my DAOs.

Do I have to create a EntityManager for each DAO, and does it always has to be a
newly created one? Or can I reuse EntityManager-Instances (Singleton anybody ;) ).

Currently I have a Singleton-Class called JpaManager which creates the
EntityManagerFactory and this one also creates the DAOs and passes a
EntityManager Instance (which is reused). When I run my test I get an exception
regarding multiple entities in one session. I found something about a
SessionBroker but I am cufused if my approach might be totaly wrong at all (so a
SessionBroker will not help me in the end).

Could somebody clarify this a bit for me, and maybe give a best-practise tip?

How you use EL depends on how you want your application to behave; in a web application this is quite simple: you need an EM to process the request and after that you're done. For a swing application you have to decide if you want one EM for the whole application or if you want, for example like me, one EM per window.

The latter is a logical setup; all the changes a user makes are limited to that window, another window the changes are only available as soon as he commits them. The problem is when you introduce a business model; this encapsulated set of classes need to know which EM to use at any given time. It does not know which window it currently is working for, since you have only one BM loaded.

But a stand alone application introduces another problem: when does a transaction start and when does it finish? You cannot start a transaction while the user is editing, because that would cause all kinds of update statements and thus locks and conflict other windows. Like with the submit in a webapplication, you need some kind of save button. When that save button is pressed, a transaction is started, changes are made and written to the database, and a commit or rollback is done. The problem with this is that you need to remember all the changes that were made prior to pressing the save button and applying them when save is pressed. Even worse; if you need to do a rollback some of the entities may already have been persisted and are rolled back by the database, but the in-memory version has its version counter increased. The next persist will throw a already-modifiedd exception.

A lot of joy is going on trying to create a workable environment. I already addressed this with the developers; the spec is very webapp focused.

Anyhow, I have written two extensions on top of JPA / Eclipselink to solve these (and some more) problems.

1. EntityManagerFinder - this is a class used by the business model to find the correct EM. Naturally there is a "singleton" implementation, but also a "Swing" implementation. The Swing implementation examines the component -and from that the window- that currently has the focus. It has a map which binds EM's to windows and thus it can find the correct EM te use. This works automatically 99% of the time. As soon as you start to invoke separate threads for long running tasks, a line of code is required to bind that thread to the correct EM. It's not covering all possible scenario's, but it real life it goes a long way.

2. An extension directly on EntityManager and Transaction which remember all merge, persist and removes when a transaction is not running. When the transaction is started, all these changes are automatically re-applied. Because it does not remember the order in which they happened (I had no need for that), you need to put the database in the suspend-constraint-checking-until-commit mode. Oracle has you create deferred constraints, Informix allows setting this on the connection for all constraints, each database has a different approach.

That is how I have my fat client running. Works fine for over a year now.

Tom]]>Tom Eugelink2009-08-15T05:59:05-00:00Re: JPA DAO in Desktop Applicationhttps://www.eclipse.org/forums/index.php/mv/msg/152546/481136/#msg_481136
In my current setup I am trying to setup a MVP pattern and the only difference
to your window-approach would be that instead of the windows holding a reference
to the EM, the presenter will have and he is also responsible for the business
model.

Your advices regarding multiple EMs at the same time are very usefull, I have to
think more about this before I start coding something. Currently I am trying to
integrate Spring DM in my RCP, at least in the data-bundle/plugin. Lets see what
Spring can do when it comes to the lifecycle of a EM instance, I just know there
is some support for that.

regards
-- Marc

tbee schrieb:
>> Could somebody clarify this a bit for me, and maybe give a
>> best-practise tip?
>
> I can only tell you how I use Eclipselink in my swing application.
>
> How you use EL depends on how you want your application to behave; in a
> web application this is quite simple: you need an EM to process the
> request and after that you're done. For a swing application you have to
> decide if you want one EM for the whole application or if you want, for
> example like me, one EM per window.
>
> The latter is a logical setup; all the changes a user makes are limited
> to that window, another window the changes are only available as soon
> as he commits them. The problem is when you introduce a business model;
> this encapsulated set of classes need to know which EM to use at any
> given time. It does not know which window it currently is working for,
> since you have only one BM loaded.
>
> But a stand alone application introduces another problem: when does a
> transaction start and when does it finish? You cannot start a
> transaction while the user is editing, because that would cause all
> kinds of update statements and thus locks and conflict other windows.
> Like with the submit in a webapplication, you need some kind of save
> button. When that save button is pressed, a transaction is started,
> changes are made and written to the database, and a commit or rollback
> is done. The problem with this is that you need to remember all the
> changes that were made prior to pressing the save button and applying
> them when save is pressed. Even worse; if you need to do a rollback some
> of the entities may already have been persisted and are rolled back by
> the database, but the in-memory version has its version counter
> increased. The next persist will throw a already-modifiedd exception.
>
> A lot of joy is going on trying to create a workable environment. I
> already addressed this with the developers; the spec is very webapp
> focused.
>
> Anyhow, I have written two extensions on top of JPA / Eclipselink to
> solve these (and some more) problems.
>
> 1. EntityManagerFinder - this is a class used by the business model to
> find the correct EM. Naturally there is a "singleton" implementation,
> but also a "Swing" implementation. The Swing implementation examines the
> component -and from that the window- that currently has the focus. It
> has a map which binds EM's to windows and thus it can find the correct
> EM te use. This works automatically 99% of the time. As soon as you
> start to invoke separate threads for long running tasks, a line of code
> is required to bind that thread to the correct EM. It's not covering all
> possible scenario's, but it real life it goes a long way.
>
> 2. An extension directly on EntityManager and Transaction which remember
> all merge, persist and removes when a transaction is not running. When
> the transaction is started, all these changes are automatically
> re-applied. Because it does not remember the order in which they
> happened (I had no need for that), you need to put the database in the
> suspend-constraint-checking-until-commit mode. Oracle has you create
> deferred constraints, Informix allows setting this on the connection for
> all constraints, each database has a different approach.
>
> That is how I have my fat client running. Works fine for over a year now.
>
> Tom]]>Marc Schlegel2009-08-19T17:35:31-00:00Re: JPA DAO in Desktop Applicationhttps://www.eclipse.org/forums/index.php/mv/msg/152546/481212/#msg_481212
> Your advices regarding multiple EMs at the same time are very usefull, I have to
> think more about this before I start coding something. Currently I am trying to
> integrate Spring DM in my RCP, at least in the data-bundle/plugin. Lets see what
> Spring can do when it comes to the lifecycle of a EM instance, I just know there
> is some support for that.

I think Tom is right, it really depends on what you want to do. I also
think that the approach to reuse one singleton instance of the em is not
wrong at all, for example if you have one global save action in your app
(like we have in our project) it is useful to just have one instance of
the em. If this leads to an exception in your case, there may be a
configuration issue.

I would like to give a note about the spring dm thougths. If you use
spring dm to manage the emf and the em, you only have to options (and to
me only one works nice), as the spring-configuration only lets you
decide between singleton and prototype scope of spring beans (there are
more scopes, but there are all only working in the web tier because they
are session related). The latter creates a new instance of a bean every
time which is not really working unless you dont't have long running
transactions. So what I mean to say is, if decide to use spring, the
singleton approach is the easiest way to set things up (I'm not
confident enough to say "the only" unless I feel that way :-))

By the way, we develop a single sourced application that runs both on
desktop an in the web and use the singleton approach (session-singleton
for the web case) and it works like a charm.

As a hint, the use of spring does not necessarily make your life easier,
as the configuration can be tricky, too.