I've used a similar solution, but when I get a broker, first I check if
one broker was already taken for this thread (and a usage counter is
incremented).
Then, when I start one operation, I just check if there is not already a
transaction. If there is no transaction, then I open one. Finally, when
I ask to close the broker, a usage counter for current thread is
decremented, and if it's zero, then broker is really closed.
This technique allow:
- Cross object transactions in same thread
- Avoid begin more than one transaction per broker
- Obligate to always open one transaction, what guarantee standard
behaviour independent of developer personal preferences (important for
groups). So, I can reuse a component written by another programmer
because I know if he execute some operation in database, I'll be in same
transaction.
- When no more object is using a broker, the broker is automatically
closed.
Resuming, all my code finish in one class that is responsible to take a
broker, start a transaction (if needed), execute operation, and close
broker (if there is no more objects using it, of course).
When I execute one operation, I delegate to Action method to start
transaction, commit or rollback. So, every action in my code has
following structure:
public void actionPerformed(ActionEvent evt) {
try {
MyPersonBrokerUC.beginTransaction(); // starts a transaction and
increments usage (to 1) for this thread
MyPersonBrokerUC.store(somePerson); // detect if is a insert or an
update (increments usage to 2) and does the job (return broker and
decrements to 1 again). Will use same broker and transaction started above
OtherPersonUC.dealWithNewPersons(somePerson); // will run under same
transaction (increments usage to 2, execute operation, and decrements to
1 again). I don't even need to know if there is a bunch of another calls
inside this method: all will run under same transaction.
MyPersonBrokerUC.commitTransaction(); // commit the transaction and
decrements usage (to 0, so broker is really closed)
} catch(Exception e) {
MyPersonBrokerUC.rollbackTransaction(); // rollback the transaction
and decrements usage (to 0, so broker is really closed)
DebugUtil.handleException(e);
}
}
UC (use cases) classes never begin, commit or rollback: it's a Action
task. Because a task always execute under unique thread, there is not
problems (if you wish to execute async operation, just start transaction
inside new thread). Works for MVC-Web development (a Servlet or a JSP
will be the "action" in this case).
Thanks to try...catch structure, there is no way to forget a broker
open, neither a transaction open.
Only one cons for this: when debugging, don't try to "fix and continue",
because you will get broken brokers and transactions, leading to dead
lock and fatally to stop and restart.
OT: humm, trying to explain just in words this appear to be really
complicated, but in fact, it isn't. May be sometime I get spare time to
create some nice Sequence and Collaboration diagrams to explain this....
Best regards,
Edson Richter
Bruno CROS escreveu:
Hi Armin,
Thanks for the idea to detect broker leak. It will show some bad coded
methods, even they have been checked : commit never reached, broker not
closed... no commit/abort !!! (find one, arghh )
Meanwhile, there was still some "open broker detected". When i look into
code, i found some old methods that were reading objects, with a
dedicated
transaction. I known now that this transaction is not necessary, and I
know
now it's even unwanted ! It seems to burn connections/brokers.
So i add a little check to my "getTransaction()" method. Now, it searches
for a current transaction, and il found, throw a "Already open
transaction". This let us detect the standalone update method
(opening and
closing Transaction), who are called inside an already open
Transaction (as
the old bad reads methods was called by update methods). Everything
gets ok
now.
May be it can be an developpment setup to avoid broker leak due to the
double opening Transaction (with same broker)
Thanks a lot. Again.
Regards
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]