Calling Cayenne transactions "singletons" is not really accurate, as they are thread-local and scoped, and you can control that scope if you have to. So here is how you can address your problem - unbind outer transaction from the thread when the nested transaction is started, and then rebind it back after inner commit/rollback:

Transaction outer = Transaction.getThreadTransaction();
try {
   Transaction inner = ... // create
   Transaction.bindThreadTransaction(inner);

   ... // do work
}
finally {
   Transaction.bindThreadTransaction(outer);
}

I am undecided on whether DataDomain-scoped transactions is a good idea going forward. This goes against most J2EE users expectations about transactions, and while addressing one use case it breaks others (i.e. other users may need a single commit point across multiple DataDomains).

Andrus


On Dec 1, 2009, at 3:41 PM, Evgeny Ryabitskiy wrote:

Manual? I create them manually by calling domain1.createTransaction()
and domain2.createTransaction().

How it happen: One method from Module 1 do some queries (first domain)
then call method from Module 2 that is also doing some queries (second
domain), after method from module 2 finished: method from module 1 is
doing more queries.

So it's like an "nested" transaction (from mod 2) but is performed on
another DataDomain (it's another DB server) and absolutely isolated
from huge "outer" transaction (mod 1).
But I want to control both! and separately...

Evgeny.



2009/12/1 Andrus Adamchik <[email protected]>:
Are those manual transactions? (I.e. how does it happen that transaction
scopes overlap between two queries?)

Also you can reuse the current thread transaction between multiple domains. As I said, connections are scoped by DataNode name, so the same transaction will return 2 separate connections for 2 queries run against 2 different
nodes.

Andrus

On Dec 1, 2009, at 3:27 PM, Evgeny Ryabitskiy wrote:

Problem in multiple Domains.
When I am creating transaction I am creating it's for specific
DataDomain (like a DataContext).
When I have 2 Modules with dedicated DataDomains (so it will be 2
DataDomains) I can create 2 Transactions
(domain.createTransaction()).

But to thread I can bind only one. Then when I start performing queries I
got:
1)First Domain Transaction is binded and handled normally
2)Second Domain Transaction is override by first DataDomain. So when I
perform query for second: ThreadLocals return Transaction for firs
Domain.

Evgeny



2009/12/1 Andrus Adamchik <[email protected]>:

Singletons are bad in a general purpose framework, like Cayenne. No
question
about that. Per your description even thread-local singletons can be a
problem, which is less obvious to me, but I guess real in some
circumstances. So let's see what those are.

2)DataContext.getThreadLocal()
Solved by own ThreadLocal for each module. (modules can work in one
thread)
//also spend some time

This is just a convenience in Cayenne. Nobody's forced to use it. I will
go
as far as to suggest to remove it from Cayenne 3.1 as a built-in feature, and just document it as a possible design pattern in a user application.

3)Transaction.getThreadTransaction()
this is killing one!!!
using of own ThreadLocal doesn't help.
It's hard-coded in performing Query to use this singleton
Transaction.getThreadTransaction()
And that is really huge problem for me.

J2EE pattern of tying a transaction to an execution thread, even if
multiple
data sources are involved, makes sense as it allows to commit/ rollback multiple things at once. Cayenne Transaction sort of follows that. JDBC connections within the transaction are scoped by DataNode name. So what
exactly is the problem?

Andrus



On Dec 1, 2009, at 2:44 PM, Evgeny Ryabitskiy wrote:

Hello 2 everyone!

Today I one more time thinking about singleton pattern and it's hard
usssage in Cayenne.

So.. I have several modules, each has own DomainConfig file and
connection to it's DataBase. Sometimes there can be used different DB servers and even different DB types (usually it's Oracle and MS SQL,
sometimes Sybase).

Singletons:
1) Configuration.getSharedConfiguration()
This problem is solved:
DefaultConfiguration conf = new
DefaultConfiguration("module1-cayenne.xml");
conf .initialize;
conf.getDomain();
//spend some time to find solution... everywhere examples with
SharedConfiguration

2)DataContext.getThreadLocal()
Solved by own ThreadLocal for each module. (modules can work in one
thread)
//also spend some time

3)Transaction.getThreadTransaction()
this is killing one!!!
using of own ThreadLocal doesn't help.
It's hard-coded in performing Query to use this singleton
Transaction.getThreadTransaction()
And that is really huge problem for me.

So me suggestion is to move this ThreadLocal to DataDomain. Still can
use singleton API for standalone applications.
Also we can move DataContext to DataDomain.

Evgeny.








Reply via email to