FAQ
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

Search Discussions

  • Andrus Adamchik at Mar 19, 2012 at 2:31 pm
    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
  • Andrus Adamchik at Mar 19, 2012 at 2:38 pm
    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
  • YK 7 at Mar 19, 2012 at 9:31 pm
    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 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
  • Andrus Adamchik at Mar 20, 2012 at 7:11 am

    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 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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupuser @
categoriescayenne
postedMar 19, '12 at 2:10p
activeMar 20, '12 at 7:11a
posts5
users2
websitecayenne.apache.org

2 users in discussion

Andrus Adamchik: 3 posts YK 7: 2 posts

People

Translate

site design / logo © 2022 Grokbase