Re: Singletons in Cayenne and problems. Can I use multiple transactions?

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Tue Dec 01 2009 - 08:56:29 EST

  • Next message: Evgeny Ryabitskiy: "Re: Singletons in Cayenne and problems. Can I use multiple transactions?"

    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 <andru..bjectstyle.org>:
    >> 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 <andru..bjectstyle.org>:
    >>>>
    >>>> 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.
    >>>>>
    >>>>
    >>>>
    >>>
    >>
    >>
    >



    This archive was generated by hypermail 2.0.0 : Tue Dec 01 2009 - 08:57:05 EST