You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by YK 7 <yk...@gmail.com> on 2012/03/19 15:10:03 UTC

Transaction Management Question

Andrus,

I'm new to Cayenne and I'm testing the Cayenne's transaction management
using the following scenario:

I have a simple web application that uses Spring to create
singletons(Services, DAOs...) and make the dependencies injection.
My example is using two different Databases (MySQL and Oracle) and thus, I
have defined two Cayenne Server Runtimes:
One for Oracle and one for MySQL. Those two ServerRuntimes are instantiated
once in a singleton.

I'm trying to use Cayenne Transactions using :
Transaction tx = serverRuntime.getDataDomain().createTransaction().
....
tx.commit(); //or tx.rollback() depending on the situation

The problem here is that if I do so, it means that if a user(or HTTP
session) changes are committed, all other users(or HTTP sessions) changes
will also be committed.
This is because serverRuntime is a singleton and the transaction is created
against it (and not against the objectContext which is bound to the HTTP
session).

I also took a look at the ServerRuntime source code and noticed that it
defines two instance properties (injector and modules which are in the
parent class: CayenneRuntime).

If I'm not mistaken, this means that ServerRuntime is not a good candidate
to be defined as a singleton (one instance per application).

Maybe I'm not correctly using Cayenne to manage transaction when we have
more than one server runtime. If so, what's the best way to achieve that
please?


Thanks

Re: Transaction Management Question

Posted by Andrus Adamchik <an...@objectstyle.org>.
> What I understand here is that the transaction is created against the
> DataDomain AND IS NOT AWARE of the current user session.

Yes, and it doesn't really care.

> Now, if I bound it to the current thread then if I call
> transaction.commit(), will this commit all the changes of all the active
> sessions (users)?

It will commit everything that was flushed in this same thread between transaction start and finish, meaning all your calls to context.commitChanges() in this thread. Java web requests are single threaded. So thread transaction model works perfectly with webapps.

> Hope my problem is clear now!

Well, there is no problem IMO.

Andrus

On Mar 20, 2012, at 12:31 AM, YK 7 wrote:

> Sorry, forget the two ServerRuntimes please.
> 
> Suppose that we have only one server runtime which is instantiated once
> during all web application life cycle.
> 
> I took a look at the Cayenne's source code and found that Calling
> serverRuntime.getDataDomain().createTransaction(), in my example, will
> create an internal transaction: new InternalTransaction(delegate).
> 
> What I understand here is that the transaction is created against the
> DataDomain AND IS NOT AWARE of the current user session.
> 
> Now, if I bound it to the current thread then if I call
> transaction.commit(), will this commit all the changes of all the active
> sessions (users)?
> 
> This is not of course the expected behavior, since I's like to commit only
> the changes of a single user.
> What I don't understand here is how Cayenne transaction will commit
> independently the changes of a each user or HTTP session.
> 
> Hope my problem is clear now!
> 
> 
> 
> On Mon, Mar 19, 2012 at 3:37 PM, Andrus Adamchik <an...@objectstyle.org>wrote:
> 
>> Oh and if you are committing to 2 DBs in separate transactions, just
>> forget all these XA transactions, and just use Cayenne as normal, using
>> ObjectContext instances from an appropriate runtime.
>> 
>> Oh, just remember that a Cayenne TX is bound to the current execution
>> thread. So while ServerRuntime being a singleton is red herring, make sure
>> there's no TX overlap within a request thread, either because you have
>> manual transactions, or e.g. you have listeners that commit to another DB
>> within the first DB commit.
>> 
>> Andrus
>> 
>> On Mar 19, 2012, at 5:30 PM, Andrus Adamchik wrote:
>> 
>>> Hi there,
>>> 
>>> This seems to be a duplicate of the earlier message. John gave a
>> completely correct answer about ServerRuntime and ObjectContext scoping.
>>> 
>>>> Maybe I'm not correctly using Cayenne to manage transaction when we have
>>>> more than one server runtime. If so, what's the best way to achieve that
>>>> please?
>>> 
>>> If you have 2 runtimes accessing 2 independent databases, and want to
>> commit 2 contexts to those together, you can either commit them
>> independently (c1.commitChanges(); c2.commitChanges(); - they won't be a
>> part of the same transaction with all the consequences), or find a solution
>> for distributed transaction management (so called XA transactions). In the
>> later case you can check "External Transactions" in Cayenne, and let the
>> JEE container handle those.
>>> 
>>> I'd much prefer the former solution and the app dealing with
>> consequences, to much heavier XA transactions. But Cayenne would allow you
>> to use the later by absolving itself of TX handling responsibility and
>> letting you or your appserver to handle all that two-phase commit fun stuff.
>>> 
>>> Andrus
>>> 
>>> 
>>> On Mar 19, 2012, at 5:10 PM, YK 7 wrote:
>>>> Andrus,
>>>> 
>>>> I'm new to Cayenne and I'm testing the Cayenne's transaction management
>>>> using the following scenario:
>>>> 
>>>> I have a simple web application that uses Spring to create
>>>> singletons(Services, DAOs...) and make the dependencies injection.
>>>> My example is using two different Databases (MySQL and Oracle) and
>> thus, I
>>>> have defined two Cayenne Server Runtimes:
>>>> One for Oracle and one for MySQL. Those two ServerRuntimes are
>> instantiated
>>>> once in a singleton.
>>>> 
>>>> I'm trying to use Cayenne Transactions using :
>>>> Transaction tx = serverRuntime.getDataDomain().createTransaction().
>>>> ....
>>>> tx.commit(); //or tx.rollback() depending on the situation
>>>> 
>>>> The problem here is that if I do so, it means that if a user(or HTTP
>>>> session) changes are committed, all other users(or HTTP sessions)
>> changes
>>>> will also be committed.
>>>> This is because serverRuntime is a singleton and the transaction is
>> created
>>>> against it (and not against the objectContext which is bound to the HTTP
>>>> session).
>>>> 
>>>> I also took a look at the ServerRuntime source code and noticed that it
>>>> defines two instance properties (injector and modules which are in the
>>>> parent class: CayenneRuntime).
>>>> 
>>>> If I'm not mistaken, this means that ServerRuntime is not a good
>> candidate
>>>> to be defined as a singleton (one instance per application).
>>>> 
>>>> Maybe I'm not correctly using Cayenne to manage transaction when we have
>>>> more than one server runtime. If so, what's the best way to achieve that
>>>> please?
>>>> 
>>>> 
>>>> Thanks
>>> 
>>> 
>> 
>> 


Re: Transaction Management Question

Posted by YK 7 <yk...@gmail.com>.
Sorry, forget the two ServerRuntimes please.

Suppose that we have only one server runtime which is instantiated once
during all web application life cycle.

I took a look at the Cayenne's source code and found that Calling
serverRuntime.getDataDomain().createTransaction(), in my example, will
create an internal transaction: new InternalTransaction(delegate).

What I understand here is that the transaction is created against the
DataDomain AND IS NOT AWARE of the current user session.

Now, if I bound it to the current thread then if I call
transaction.commit(), will this commit all the changes of all the active
sessions (users)?

This is not of course the expected behavior, since I's like to commit only
the changes of a single user.
What I don't understand here is how Cayenne transaction will commit
independently the changes of a each user or HTTP session.

Hope my problem is clear now!



On Mon, Mar 19, 2012 at 3:37 PM, Andrus Adamchik <an...@objectstyle.org>wrote:

> Oh and if you are committing to 2 DBs in separate transactions, just
> forget all these XA transactions, and just use Cayenne as normal, using
> ObjectContext instances from an appropriate runtime.
>
> Oh, just remember that a Cayenne TX is bound to the current execution
> thread. So while ServerRuntime being a singleton is red herring, make sure
> there's no TX overlap within a request thread, either because you have
> manual transactions, or e.g. you have listeners that commit to another DB
> within the first DB commit.
>
> Andrus
>
> On Mar 19, 2012, at 5:30 PM, Andrus Adamchik wrote:
>
> > Hi there,
> >
> > This seems to be a duplicate of the earlier message. John gave a
> completely correct answer about ServerRuntime and ObjectContext scoping.
> >
> >> Maybe I'm not correctly using Cayenne to manage transaction when we have
> >> more than one server runtime. If so, what's the best way to achieve that
> >> please?
> >
> > If you have 2 runtimes accessing 2 independent databases, and want to
> commit 2 contexts to those together, you can either commit them
> independently (c1.commitChanges(); c2.commitChanges(); - they won't be a
> part of the same transaction with all the consequences), or find a solution
> for distributed transaction management (so called XA transactions). In the
> later case you can check "External Transactions" in Cayenne, and let the
> JEE container handle those.
> >
> > I'd much prefer the former solution and the app dealing with
> consequences, to much heavier XA transactions. But Cayenne would allow you
> to use the later by absolving itself of TX handling responsibility and
> letting you or your appserver to handle all that two-phase commit fun stuff.
> >
> > Andrus
> >
> >
> > On Mar 19, 2012, at 5:10 PM, YK 7 wrote:
> >> Andrus,
> >>
> >> I'm new to Cayenne and I'm testing the Cayenne's transaction management
> >> using the following scenario:
> >>
> >> I have a simple web application that uses Spring to create
> >> singletons(Services, DAOs...) and make the dependencies injection.
> >> My example is using two different Databases (MySQL and Oracle) and
> thus, I
> >> have defined two Cayenne Server Runtimes:
> >> One for Oracle and one for MySQL. Those two ServerRuntimes are
> instantiated
> >> once in a singleton.
> >>
> >> I'm trying to use Cayenne Transactions using :
> >> Transaction tx = serverRuntime.getDataDomain().createTransaction().
> >> ....
> >> tx.commit(); //or tx.rollback() depending on the situation
> >>
> >> The problem here is that if I do so, it means that if a user(or HTTP
> >> session) changes are committed, all other users(or HTTP sessions)
> changes
> >> will also be committed.
> >> This is because serverRuntime is a singleton and the transaction is
> created
> >> against it (and not against the objectContext which is bound to the HTTP
> >> session).
> >>
> >> I also took a look at the ServerRuntime source code and noticed that it
> >> defines two instance properties (injector and modules which are in the
> >> parent class: CayenneRuntime).
> >>
> >> If I'm not mistaken, this means that ServerRuntime is not a good
> candidate
> >> to be defined as a singleton (one instance per application).
> >>
> >> Maybe I'm not correctly using Cayenne to manage transaction when we have
> >> more than one server runtime. If so, what's the best way to achieve that
> >> please?
> >>
> >>
> >> Thanks
> >
> >
>
>

Re: Transaction Management Question

Posted by Andrus Adamchik <an...@objectstyle.org>.
Oh and if you are committing to 2 DBs in separate transactions, just forget all these XA transactions, and just use Cayenne as normal, using ObjectContext instances from an appropriate runtime. 

Oh, just remember that a Cayenne TX is bound to the current execution thread. So while ServerRuntime being a singleton is red herring, make sure there's no TX overlap within a request thread, either because you have manual transactions, or e.g. you have listeners that commit to another DB within the first DB commit.

Andrus

On Mar 19, 2012, at 5:30 PM, Andrus Adamchik wrote:

> Hi there,
> 
> This seems to be a duplicate of the earlier message. John gave a completely correct answer about ServerRuntime and ObjectContext scoping. 
> 
>> Maybe I'm not correctly using Cayenne to manage transaction when we have
>> more than one server runtime. If so, what's the best way to achieve that
>> please?
> 
> If you have 2 runtimes accessing 2 independent databases, and want to commit 2 contexts to those together, you can either commit them independently (c1.commitChanges(); c2.commitChanges(); - they won't be a part of the same transaction with all the consequences), or find a solution for distributed transaction management (so called XA transactions). In the later case you can check "External Transactions" in Cayenne, and let the JEE container handle those.
> 
> I'd much prefer the former solution and the app dealing with consequences, to much heavier XA transactions. But Cayenne would allow you to use the later by absolving itself of TX handling responsibility and letting you or your appserver to handle all that two-phase commit fun stuff.
> 
> Andrus
> 
> 
> On Mar 19, 2012, at 5:10 PM, YK 7 wrote:
>> Andrus,
>> 
>> I'm new to Cayenne and I'm testing the Cayenne's transaction management
>> using the following scenario:
>> 
>> I have a simple web application that uses Spring to create
>> singletons(Services, DAOs...) and make the dependencies injection.
>> My example is using two different Databases (MySQL and Oracle) and thus, I
>> have defined two Cayenne Server Runtimes:
>> One for Oracle and one for MySQL. Those two ServerRuntimes are instantiated
>> once in a singleton.
>> 
>> I'm trying to use Cayenne Transactions using :
>> Transaction tx = serverRuntime.getDataDomain().createTransaction().
>> ....
>> tx.commit(); //or tx.rollback() depending on the situation
>> 
>> The problem here is that if I do so, it means that if a user(or HTTP
>> session) changes are committed, all other users(or HTTP sessions) changes
>> will also be committed.
>> This is because serverRuntime is a singleton and the transaction is created
>> against it (and not against the objectContext which is bound to the HTTP
>> session).
>> 
>> I also took a look at the ServerRuntime source code and noticed that it
>> defines two instance properties (injector and modules which are in the
>> parent class: CayenneRuntime).
>> 
>> If I'm not mistaken, this means that ServerRuntime is not a good candidate
>> to be defined as a singleton (one instance per application).
>> 
>> Maybe I'm not correctly using Cayenne to manage transaction when we have
>> more than one server runtime. If so, what's the best way to achieve that
>> please?
>> 
>> 
>> Thanks
> 
> 


Re: Transaction Management Question

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi there,

This seems to be a duplicate of the earlier message. John gave a completely correct answer about ServerRuntime and ObjectContext scoping. 

> Maybe I'm not correctly using Cayenne to manage transaction when we have
> more than one server runtime. If so, what's the best way to achieve that
> please?

If you have 2 runtimes accessing 2 independent databases, and want to commit 2 contexts to those together, you can either commit them independently (c1.commitChanges(); c2.commitChanges(); - they won't be a part of the same transaction with all the consequences), or find a solution for distributed transaction management (so called XA transactions). In the later case you can check "External Transactions" in Cayenne, and let the JEE container handle those.

I'd much prefer the former solution and the app dealing with consequences, to much heavier XA transactions. But Cayenne would allow you to use the later by absolving itself of TX handling responsibility and letting you or your appserver to handle all that two-phase commit fun stuff.

Andrus


On Mar 19, 2012, at 5:10 PM, YK 7 wrote:
> Andrus,
> 
> I'm new to Cayenne and I'm testing the Cayenne's transaction management
> using the following scenario:
> 
> I have a simple web application that uses Spring to create
> singletons(Services, DAOs...) and make the dependencies injection.
> My example is using two different Databases (MySQL and Oracle) and thus, I
> have defined two Cayenne Server Runtimes:
> One for Oracle and one for MySQL. Those two ServerRuntimes are instantiated
> once in a singleton.
> 
> I'm trying to use Cayenne Transactions using :
> Transaction tx = serverRuntime.getDataDomain().createTransaction().
> ....
> tx.commit(); //or tx.rollback() depending on the situation
> 
> The problem here is that if I do so, it means that if a user(or HTTP
> session) changes are committed, all other users(or HTTP sessions) changes
> will also be committed.
> This is because serverRuntime is a singleton and the transaction is created
> against it (and not against the objectContext which is bound to the HTTP
> session).
> 
> I also took a look at the ServerRuntime source code and noticed that it
> defines two instance properties (injector and modules which are in the
> parent class: CayenneRuntime).
> 
> If I'm not mistaken, this means that ServerRuntime is not a good candidate
> to be defined as a singleton (one instance per application).
> 
> Maybe I'm not correctly using Cayenne to manage transaction when we have
> more than one server runtime. If so, what's the best way to achieve that
> please?
> 
> 
> Thanks