FAQ
In Cayenne Modeler, when I disable Cayenne managed transactions, a message
saying that the external transaction was used instead during a commit.

How am I supposed to tell my external container to handle transaction if
cayenne manages DB objects(Node, ObjectContext...) ?

Do you have any working example that shows how to use cayenne with the same
circumstances?

thx

Search Discussions

  • Andrus Adamchik at Feb 19, 2012 at 12:52 pm
    External transactions allow you to use container-managed DataSource and tie Cayenne in to container-managed JDBC transactions. So essentially if a container does a commit or rollback on a Connection, this will commit/rollback everything that was flushed via Cayenne or other JDBC clients since the start of the transaction.

    DataNode by itself is stateless. It is just a driver on top of JDBC driver if you may. So no problems there.

    ObjectContext state is not tied directly to the transaction. Its commit within an external tx is a flush to DB that will be committed or rolled back at some later point at tx end. You can do multiple ObjectContext commits within the same tx to update data incrementally, etc. ObjectContext rollback is even less related to tx. It just reverts objects in memory back to their previously known committed state. In many cases you probably do not want to reuse the context between external transactions.

    And finally, consider whether you really need those external transactions. 90% of Cayenne apps don't. A common reason to use external tx is when you want atomic behavior across multiple sources of DB modification (say Cayenne and raw JDBC) or mixing Cayenne with other non-JDBC transactional resources (JMS for instance). If you only modify the DB via Cayenne, then you don't need external tx. This is what makes Cayenne unique in the ORM space, and so much easier to use. It was compared to a version control system by other users - you check out a local copy of your objects, you modify them, and then commit. Only the last step involves a transaction and Cayenne can handle starting and ending it internally with no user involvement.

    Cheers,
    Andrus


    On Feb 18, 2012, at 5:48 PM, YK 7 wrote:
    In Cayenne Modeler, when I disable Cayenne managed transactions, a message
    saying that the external transaction was used instead during a commit.

    How am I supposed to tell my external container to handle transaction if
    cayenne manages DB objects(Node, ObjectContext...) ?

    Do you have any working example that shows how to use cayenne with the same
    circumstances?

    thx
  • YK 7 at Feb 20, 2012 at 8:43 pm
    Thanks for this brilliant answer Andrus!

    However, I still have a question.
    Suppose that we have two databases and that we commit to the second one
    only if the commit to the first db succeeds.
    If I well understood, here I have to use external tx because it offers more
    granularity.

    Is it better to have an ObjectContext per DataNode (and not per DataDomain)
    so that we can handle all cases?

    Thanks
    On Sun, Feb 19, 2012 at 1:51 PM, Andrus Adamchik wrote:

    External transactions allow you to use container-managed DataSource and
    tie Cayenne in to container-managed JDBC transactions. So essentially if a
    container does a commit or rollback on a Connection, this will
    commit/rollback everything that was flushed via Cayenne or other JDBC
    clients since the start of the transaction.

    DataNode by itself is stateless. It is just a driver on top of JDBC driver
    if you may. So no problems there.

    ObjectContext state is not tied directly to the transaction. Its commit
    within an external tx is a flush to DB that will be committed or rolled
    back at some later point at tx end. You can do multiple ObjectContext
    commits within the same tx to update data incrementally, etc. ObjectContext
    rollback is even less related to tx. It just reverts objects in memory back
    to their previously known committed state. In many cases you probably do
    not want to reuse the context between external transactions.

    And finally, consider whether you really need those external transactions.
    90% of Cayenne apps don't. A common reason to use external tx is when you
    want atomic behavior across multiple sources of DB modification (say
    Cayenne and raw JDBC) or mixing Cayenne with other non-JDBC transactional
    resources (JMS for instance). If you only modify the DB via Cayenne, then
    you don't need external tx. This is what makes Cayenne unique in the ORM
    space, and so much easier to use. It was compared to a version control
    system by other users - you check out a local copy of your objects, you
    modify them, and then commit. Only the last step involves a transaction and
    Cayenne can handle starting and ending it internally with no user
    involvement.

    Cheers,
    Andrus


    On Feb 18, 2012, at 5:48 PM, YK 7 wrote:
    In Cayenne Modeler, when I disable Cayenne managed transactions, a message
    saying that the external transaction was used instead during a commit.

    How am I supposed to tell my external container to handle transaction if
    cayenne manages DB objects(Node, ObjectContext...) ?

    Do you have any working example that shows how to use cayenne with the same
    circumstances?

    thx
  • Andrus Adamchik at Feb 21, 2012 at 6:41 am
    Yeah, this is probably a good use case, as real distributed transactions are supported by many containers, but Cayenne would simply do a serial commit on all connections until one of them throws an Exception. So only partial rollback is possible.
    Is it better to have an ObjectContext per DataNode (and not per DataDomain)
    so that we can handle all cases?
    If you are ok with partial rollback and would want to keep using Cayenne transactions, this may be the way to go.

    Andrus

    On Feb 20, 2012, at 11:42 PM, YK 7 wrote:

    Thanks for this brilliant answer Andrus!

    However, I still have a question.
    Suppose that we have two databases and that we commit to the second one
    only if the commit to the first db succeeds.
    If I well understood, here I have to use external tx because it offers more
    granularity.

    Is it better to have an ObjectContext per DataNode (and not per DataDomain)
    so that we can handle all cases?

    Thanks
    On Sun, Feb 19, 2012 at 1:51 PM, Andrus Adamchik wrote:

    External transactions allow you to use container-managed DataSource and
    tie Cayenne in to container-managed JDBC transactions. So essentially if a
    container does a commit or rollback on a Connection, this will
    commit/rollback everything that was flushed via Cayenne or other JDBC
    clients since the start of the transaction.

    DataNode by itself is stateless. It is just a driver on top of JDBC driver
    if you may. So no problems there.

    ObjectContext state is not tied directly to the transaction. Its commit
    within an external tx is a flush to DB that will be committed or rolled
    back at some later point at tx end. You can do multiple ObjectContext
    commits within the same tx to update data incrementally, etc. ObjectContext
    rollback is even less related to tx. It just reverts objects in memory back
    to their previously known committed state. In many cases you probably do
    not want to reuse the context between external transactions.

    And finally, consider whether you really need those external transactions.
    90% of Cayenne apps don't. A common reason to use external tx is when you
    want atomic behavior across multiple sources of DB modification (say
    Cayenne and raw JDBC) or mixing Cayenne with other non-JDBC transactional
    resources (JMS for instance). If you only modify the DB via Cayenne, then
    you don't need external tx. This is what makes Cayenne unique in the ORM
    space, and so much easier to use. It was compared to a version control
    system by other users - you check out a local copy of your objects, you
    modify them, and then commit. Only the last step involves a transaction and
    Cayenne can handle starting and ending it internally with no user
    involvement.

    Cheers,
    Andrus


    On Feb 18, 2012, at 5:48 PM, YK 7 wrote:
    In Cayenne Modeler, when I disable Cayenne managed transactions, a message
    saying that the external transaction was used instead during a commit.

    How am I supposed to tell my external container to handle transaction if
    cayenne manages DB objects(Node, ObjectContext...) ?

    Do you have any working example that shows how to use cayenne with the same
    circumstances?

    thx
  • Andrus Adamchik at Feb 21, 2012 at 6:53 am

    On Feb 21, 2012, at 9:41 AM, Andrus Adamchik wrote:


    Is it better to have an ObjectContext per DataNode (and not per DataDomain)
    so that we can handle all cases?
    If you are ok with partial rollback and would want to keep using Cayenne transactions, this may be the way to go.
    To clarify, context per DN won't alter the rollback behavior compared to one context for multiple DNs. But it will make the failures more easy to handle on the app end, as the states of persistent objects in the corresponding contexts after the commit attempt will correctly reflect their DB state.

    Andrus
  • YK 7 at Feb 21, 2012 at 8:28 am
    As usual, great answer. I can see better the picture now. Many Thanks!

    A final question: In order to properly handle trx across multiple DBs, can
    we use as much DataDomains as DBs?

    In this case, each DataDomain defines its DataNode(s) (DNs: same DB +
    different schemas). We can then have several DataContexts
    that we have to handle in the application end.


    Thanks
    On Tue, Feb 21, 2012 at 7:52 AM, Andrus Adamchik wrote:

    On Feb 21, 2012, at 9:41 AM, Andrus Adamchik wrote:


    Is it better to have an ObjectContext per DataNode (and not per
    DataDomain)
    so that we can handle all cases?
    If you are ok with partial rollback and would want to keep using Cayenne
    transactions, this may be the way to go.

    To clarify, context per DN won't alter the rollback behavior compared to
    one context for multiple DNs. But it will make the failures more easy to
    handle on the app end, as the states of persistent objects in the
    corresponding contexts after the commit attempt will correctly reflect
    their DB state.

    Andrus
  • Andrus Adamchik at Feb 21, 2012 at 8:33 am

    On Feb 21, 2012, at 11:28 AM, YK 7 wrote:

    A final question: In order to properly handle trx across multiple DBs, can
    we use as much DataDomains as DBs?

    In this case, each DataDomain defines its DataNode(s) (DNs: same DB +
    different schemas). We can then have several DataContexts
    that we have to handle in the application end.
    Sure. Separating DB's by DataDomain is the best way to ensure there's no cross-DB objects in one context. If you are on 3.0.x, you'd define multiple DataDomains in a single project; if you are on 3.1 (that features single DataDomain per ServerRuntime), you'd need to start multiple ServerRuntimes, one per DataDomain.

    Andrus
  • Durchholz, Joachim at Feb 21, 2012 at 9:34 am
    This just made me wonder...
    A common reason to use external tx is when you want atomic behavior
    across multiple sources of DB modification (say Cayenne and raw JDBC)
    or mixing Cayenne with other non-JDBC transactional resources (JMS
    for instance). If you only modify the DB via Cayenne, then you don't
    need external tx.
    Just a heads-up: That is not the normal case in corporate processing; there are always other sources of database updates: Nightly batch processing, manual intervention through interactive SQL, or third-party software that's interacting with your storage. You'd have to thread it all through the Java service, which isn't always feasible or even desirable.
    Besides, if you don't have multiple sources of DB modification, you usually don't need a DB. Not an SQL-enabled one anyway.
    you check out a local copy of your objects, you modify them, and then
    commit. Only the last step involves a transaction and Cayenne can
    handle starting and ending it internally with no user involvement.
    What happens if a record is written that was modified by some third party?
    Ideally, Cayenne would avoid writing the udpates and instead report back that the application was trying to write stale data.
  • Andrus Adamchik at Feb 21, 2012 at 9:36 am
    Of course there are multiple sources of DB modification. The question is - do they all have to be in the same transaction ;)
    On Feb 21, 2012, at 12:33 PM, Durchholz, Joachim wrote:

    This just made me wonder...
    A common reason to use external tx is when you want atomic behavior
    across multiple sources of DB modification (say Cayenne and raw JDBC)
    or mixing Cayenne with other non-JDBC transactional resources (JMS
    for instance). If you only modify the DB via Cayenne, then you don't
    need external tx.
    Just a heads-up: That is not the normal case in corporate processing; there are always other sources of database updates: Nightly batch processing, manual intervention through interactive SQL, or third-party software that's interacting with your storage. You'd have to thread it all through the Java service, which isn't always feasible or even desirable.
    Besides, if you don't have multiple sources of DB modification, you usually don't need a DB. Not an SQL-enabled one anyway.
    you check out a local copy of your objects, you modify them, and then
    commit. Only the last step involves a transaction and Cayenne can
    handle starting and ending it internally with no user involvement.
    What happens if a record is written that was modified by some third party?
    Ideally, Cayenne would avoid writing the udpates and instead report back that the application was trying to write stale data.
  • Durchholz, Joachim at Feb 21, 2012 at 10:00 am

    Of course there are multiple sources of DB modification.
    The question is - do they all have to be in the same transaction ;)
    Rarely if ever, of course.
    My question was about how Cayenne interacts with transactions
    initiated by third parties:
    What happens if a record is written that was modified by some third
    party?
    Ideally, Cayenne would avoid writing the udpates and instead report
    back that the application was trying to write stale data.
  • Andrus Adamchik at Feb 21, 2012 at 10:13 am
    Your question is not about transactions. Your's is a valid, but a separate and more or less unrelated topic. Brief answer - Cayenne supports optimistic locking, how to apply it (or any other locking technique) is for the user to decide.

    Andrus

    On Feb 21, 2012, at 12:59 PM, Durchholz, Joachim wrote:

    Of course there are multiple sources of DB modification.
    The question is - do they all have to be in the same transaction ;)
    Rarely if ever, of course.
    My question was about how Cayenne interacts with transactions
    initiated by third parties:
    What happens if a record is written that was modified by some third
    party?
    Ideally, Cayenne would avoid writing the udpates and instead report
    back that the application was trying to write stale data.
  • Durchholz, Joachim at Feb 21, 2012 at 10:50 am

    Brief answer - Cayenne supports optimistic locking, how to apply it
    (or any other locking technique) is for the user to decide.
    What's the approach to do optimistic locking in Cayenne?
    I have checked all chapters in the Cayenne 3.1 docs that seemed relevant, but came up empty.
  • Michael Gentry at Feb 21, 2012 at 4:29 pm
    Hi Joachim,

    The short answer is it really depends on your
    application/requirements. For my personal preference, I like to lock
    on all meaningful columns with the exception of blobs unless there is
    a compelling data/business requirement to not do so. You also need to
    be careful of triggers that update things behind the scenes, too. If
    you have a trigger that updates a last-modified column, you wouldn't
    want to optimistically lock on that column because the trigger is
    going to be changing the value behind your back.

    mrg


    On Tue, Feb 21, 2012 at 5:49 AM, Durchholz, Joachim
    wrote:
    Brief answer - Cayenne supports optimistic locking, how to apply it
    (or any other locking technique) is for the user to decide.
    What's the approach to do optimistic locking in Cayenne?
    I have checked all chapters in the Cayenne 3.1 docs that seemed relevant, but came up empty.
  • Durchholz, Joachim at Feb 21, 2012 at 4:51 pm

    The short answer is it really depends on your application/requirements.
    For my personal preference, I like to lock on all meaningful columns
    with the exception of blobs unless there is a compelling data/business
    requirement to not do so. You also need to be careful of triggers that
    update things behind the scenes, too. If you have a trigger that updates
    a last-modified column, you wouldn't want to optimistically lock on that
    column because the trigger is going to be changing the value behind your
    back.
    So my understanding is that Cayenne leaves it to the application to
    implement optimistic locking.

    I'm not sure how to do that well with Cayenne. My approach would be:
    1) lock all relevant rows
    2) load the relevant rows as Cayenne entities
    3) compare for differences with the unmodified state
    4) if all goes well, trigger Cayenne's commit.

    (1) means I need to know all rows that might be affected. Cayenne tells me
    about entities; does it tell me about the rows associated with them? In
    the presence of flattened relationships, too?

    (2) means opening another Cayenne context and loading the data I guess.
    That should work out of the box.

    (3) means a deep traversal of object networks, while avoiding triggering a
    lazy load.
    Not sure which parts of the Cayenne API to inspect for that.
    Also, not sure how to get that done without writing lots of boilerplate
    code.

    (4) should work out of the box.

    So steps (1) and (3) are the ones I don't know how to do.

    -------------

    There's an approach that halves the number of server roundtrips: Use
    UPDATE table SET field = :value
    WHERE pk = :id
    AND field = :old_value
    and check whether that returns an update count of 1 - if field got changed
    by another process in the time between local read and update, the UPDATE
    will find no record that matches the criteria, do nothing, and return a 0.

    Is there a way to do that in Cayenne?

    (This technique is the one that the Hibernate folks use for their
    implementation of optimistic locking.)
  • Michael Gentry at Feb 21, 2012 at 5:07 pm
    Hi Joachim,

    I think you are over-complicating things.

    1) In Cayenne Modeler, select an ObjEntity (the Java class) and under
    the Entity tab, turn Optimistic Locking on. Then under the Attributes
    tab, turn Used for Locking on for each attribute you wish to lock on
    (you can do the same for Relationships if you desire).

    That's it. You don't have to track which rows were loaded or modified
    (Cayenne knows that). When you commitChanges(), it'll do the UPDATE
    statement as you were suggesting (including the original values -- the
    ones you Used for Locking -- as part of the UPDATE). If something
    else has modified the data between the time you read it and committed
    it, then Cayenne throws an OptimisticLockingException during
    commitChanges().

    mrg


    On Tue, Feb 21, 2012 at 11:51 AM, Durchholz, Joachim
    wrote:
    The short answer is it really depends on your application/requirements.
    For my personal preference, I like to lock on all meaningful columns
    with the exception of blobs unless there is a compelling data/business
    requirement to not do so.  You also need to be careful of triggers that
    update things behind the scenes, too. If you have a trigger that updates
    a last-modified column, you wouldn't want to optimistically lock on that
    column because the trigger is going to be changing the value behind your
    back.
    So my understanding is that Cayenne leaves it to the application to
    implement optimistic locking.

    I'm not sure how to do that well with Cayenne. My approach would be:
    1) lock all relevant rows
    2) load the relevant rows as Cayenne entities
    3) compare for differences with the unmodified state
    4) if all goes well, trigger Cayenne's commit.

    (1) means I need to know all rows that might be affected. Cayenne tells me
    about entities; does it tell me about the rows associated with them? In
    the presence of flattened relationships, too?

    (2) means opening another Cayenne context and loading the data I guess.
    That should work out of the box.

    (3) means a deep traversal of object networks, while avoiding triggering a
    lazy load.
    Not sure which parts of the Cayenne API to inspect for that.
    Also, not sure how to get that done without writing lots of boilerplate
    code.

    (4) should work out of the box.

    So steps (1) and (3) are the ones I don't know how to do.

    -------------

    There's an approach that halves the number of server roundtrips: Use
    UPDATE table SET field = :value
    WHERE pk = :id
    AND field = :old_value
    and check whether that returns an update count of 1 - if field got changed
    by another process in the time between local read and update, the UPDATE
    will find no record that matches the criteria, do nothing, and return a 0.

    Is there a way to do that in Cayenne?

    (This technique is the one that the Hibernate folks use for their
    implementation of optimistic locking.)
  • Durchholz, Joachim at Feb 21, 2012 at 5:29 pm

    1) In Cayenne Modeler, select an ObjEntity (the Java class) and
    under the Entity tab, turn Optimistic Locking on. Then under
    the Attributes tab, turn Used for Locking on for each attribute
    you wish to lock on (you can do the same for Relationships if you
    desire).
    Thanks, that's what I missed.

    Oh right, it's in the FAQ, not in the JavaDoc.
    Finally thought of asking Google. D'oh.

    Though the only other page that mentions it is
    https://cwiki.apache.org/CAY/cayenne-in-motion.html . (It's ancient,
    uses Cayenne 1.1 or 1.2. Not sure whether it's still up-to-date. I
    tend to avoid ancient examples, which is why I missed that one in the
    first place.)

    The Javadoc for the commit functions should at least mention that
    they might throw an optimistic locking exception. And what the class
    of that exception is so people can write try...catch clauses.
    And the Cayenne user guide should mention it, as part of the commit
    stuff (here we're back at transactions ;-)). And maybe there should
    be mention how to enable it if one is not using Modeler.

    Sorry for all those nitty-gritty details, and I apologize for the
    inconvenience if I just overlooked it in the docs.
  • Michael Gentry at Feb 21, 2012 at 6:26 pm
    I always ask Google for everything. I don't have a brain anymore.

    The Cayenne in Motion example is old, but still pretty valid (except
    for package names that have changed).

    The JavaDoc could be improved upon, certainly. There are a few
    exceptions that commitChanges() will throw, but you don't have to
    catch them if you don't want -- depends on your use. Of course,
    catching is usually nicer. :-)


    On Tue, Feb 21, 2012 at 12:28 PM, Durchholz, Joachim
    wrote:
    1) In Cayenne Modeler, select an ObjEntity (the Java class) and
    under the Entity tab, turn Optimistic Locking on.  Then under
    the Attributes tab, turn Used for Locking on for each attribute
    you wish to lock on (you can do the same for Relationships if you
    desire).
    Thanks, that's what I missed.

    Oh right, it's in the FAQ, not in the JavaDoc.
    Finally thought of asking Google. D'oh.

    Though the only other page that mentions it is
    https://cwiki.apache.org/CAY/cayenne-in-motion.html . (It's ancient,
    uses Cayenne 1.1 or 1.2. Not sure whether it's still up-to-date. I
    tend to avoid ancient examples, which is why I missed that one in the
    first place.)

    The Javadoc for the commit functions should at least mention that
    they might throw an optimistic locking exception. And what the class
    of that exception is so people can write try...catch clauses.
    And the Cayenne user guide should mention it, as part of the commit
    stuff (here we're back at transactions ;-)). And maybe there should
    be mention how to enable it if one is not using Modeler.

    Sorry for all those nitty-gritty details, and I apologize for the
    inconvenience if I just overlooked it in the docs.
  • Durchholz, Joachim at Feb 22, 2012 at 10:58 am

    The JavaDoc could be improved upon, certainly. There are a few
    exceptions that commitChanges() will throw, but you don't have
    to catch them if you don't want -- depends on your use.
    Of course, catching is usually nicer. :-)
    Sorry, but that's just too handwavy.
    For writing professional code, anyway.

    I'd need to know what exceptions can be thrown.
    Under which circumstances.
    As exactly as possible. ("Exact" from a caller's perspective. I.e.
    in terms of things that the calling code controls.)

    Of course, I can guess what exception will be thrown when.
    I'll probably even be correct - I can read code after all :-)
    But that's not going to cut it. I won't see what aspects of
    Cayenne's behaviour are essential and what are accidental.
    Accidental aspects might be changed at the drop of a hat. It would
    be unwise to rely on them.
    Essential aspects are those that the Cayenne team expects to be
    relied upon by application developer, and that the Cayenne team
    won't change (not without prominent notice and a good reason,
    anyway).
    Actually I don't care much about Javadoc per se, I care about
    having a place to turn to when I need to check what the dev team
    thinks is essential. So, anything will do, even scribbled notes in
    the source, as long as they are reasonably accurate and up-to-date.

    I'm constantly amazed about how many projects fail to document
    that properly.
    If a project wonders why it isn't getting more traction - here's
    one major pitfall.

    </rant>
    Sorry, but this needed to get out.
  • Michael Gentry at Feb 22, 2012 at 2:02 pm
    Hi Joachim,

    It wasn't intended to be handwavy at all. If I'm writing a batch-type
    job using Cayenne, I'm fine with it dying completely on a commit error
    since it probably isn't safe to continue. For the web applications I
    write, I catch Exception (anything) and inform the user that there was
    a problem and their changes weren't saved (I don't give them a stack
    trace or other mumbo-jumbo they won't understand) and then e-mail the
    exception to the developers so they can investigate. I find in
    practice this works better than trying to catch individual exceptions
    because most of my user community wouldn't understand an
    OptimisticLockException or any other kind of Exception and I don't
    need multiple catch blocks just to e-mail the developers the
    exception.

    Of course, your application/environment might have different
    requirements, which is why it depends on your use cases.

    mrg


    On Wed, Feb 22, 2012 at 5:58 AM, Durchholz, Joachim
    wrote:
    The JavaDoc could be improved upon, certainly.  There are a few
    exceptions that commitChanges() will throw, but you don't have
    to catch them if you don't want -- depends on your use.
    Of course, catching is usually nicer.  :-)
    Sorry, but that's just too handwavy.
    For writing professional code, anyway.

    I'd need to know what exceptions can be thrown.
    Under which circumstances.
    As exactly as possible. ("Exact" from a caller's perspective. I.e.
    in terms of things that the calling code controls.)

    Of course, I can guess what exception will be thrown when.
    I'll probably even be correct - I can read code after all :-)
    But that's not going to cut it. I won't see what aspects of
    Cayenne's behaviour are essential and what are accidental.
    Accidental aspects might be changed at the drop of a hat. It would
    be unwise to rely on them.
    Essential aspects are those that the Cayenne team expects to be
    relied upon by application developer, and that the Cayenne team
    won't change (not without prominent notice and a good reason,
    anyway).
    Actually I don't care much about Javadoc per se, I care about
    having a place to turn to when I need to check what the dev team
    thinks is essential. So, anything will do, even scribbled notes in
    the source, as long as they are reasonably accurate and up-to-date.

    I'm constantly amazed about how many projects fail to document
    that properly.
    If a project wonders why it isn't getting more traction - here's
    one major pitfall.

    </rant>
    Sorry, but this needed to get out.
  • Durchholz, Joachim at Feb 23, 2012 at 10:31 am

    It wasn't intended to be handwavy at all. Okay.
    If I'm writing a batch-type job using Cayenne, I'm fine with it
    dying completely on a commit error since it probably isn't safe
    to continue.
    Heh. That's kind of zeroth-order approximation to dependency analysis: Assume everything depends on everything that came before it.
    My code does that, too, and my boss hates that with a passion.
    The only thing that's holding him back from ordering me to fix it is that I'm telling him I can't do reliable dependency analysis. Not getting useful diagnostics from the ORM is one of the factors that come into play here (there are others, such as higher priorities and constrained resources).
    For the web applications I write, I catch Exception (anything)
    and inform the user that there was a problem and their changes
    weren't saved (I don't give them a stack trace or other
    mumbo-jumbo they won't understand) and then e-mail the exception
    to the developers so they can investigate.
    Doing the same here for the moment.
    I find in practice this works better than trying to catch
    individual exceptions because most of my user community wouldn't
    understand an OptimisticLockException or any other kind of
    Exception and I don't need multiple catch blocks just to e-mail
    the developers the exception.
    This *is* a handwavy way to deal with an optimistic locking situation ;-P

    We could do better.
    For example, in the case of optimistic locking, we could tell the user "somebody else changed the data you were trying to update; here's the base where you both started, here's your change, here's the other person's change; do you want to override the other person's change, or do you want to repeat your edits based on their changes?" Plus add something that makes the overridden data available (clipboard, separate dialog window with the data snippets, whatever).

    Well, so much for the wishlist :-)
    Right now, I think Cayenne should document that it will detect optimistic locking failures but handles them like any unspecific problem: there is no special support for handling the situation. (I'm not aware of any ORM that actually does better than that, by the way. Lifting optimistic locking failures to the GUI abstraction level has been my personal elusive Quest Beast for more than a decade now, that's all.)

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupuser @
categoriescayenne
postedFeb 18, '12 at 2:48p
activeFeb 23, '12 at 10:31a
posts20
users4
websitecayenne.apache.org

People

Translate

site design / logo © 2022 Grokbase