Re: Cayenne callback listener in single transaction

Andrus Adamchik <[email protected]>
Newsgroups gmane.comp.java.cayenne.devel
Message-ID <[email protected]>

> On Dec 21, 2019, at 7:55 AM, Aristedes Maniatis <[email protected]> wrote:
> 
> On 19/12/19 1:18am, Artem Kravchenko wrote:
>> So the problem which I faced with: the commits (main one and subsequent from listener) are two different jdbs transaction, which is reasonable in fact. But in such case the data consistency is not guaranteed - second commit might be failed. It is really important for me.
> 
> 
> At first glance, I cannot understand why wrapping them in a single transaction would not be the default behaviour here. Adding records in @PostPersist is likely something like:
> 
> * audit records to track changes
> 
> * financial transactional data (eg writing to a general ledger when invoice is created)
> 
> * updating denormalised data (eg. contact.owing) which might be done for search or performance reasons.
> 
> 
> In each case I can think of, rolling back the whole transaction would be a more appropriate behaviour in case of failure.
> 
> 
> Cheers
> 
> Ari

IIRC the original thinking was that many "post" operations are not DB-specific (e.g. sending an email, writing to a file, etc). So they are allowed to fail without rolling back the transaction, and may also be slow and needlessly holding the connection. An ideal solution should support both transactional and non-transactional callbacks to allow the user to chose. I guess an extra transaction property on all @Post* annotations may solve this as the expense of a more complicated event dispatch. Open to discussion on this.

Also there is an alternative mechanism that has this control already - DataChannelFilter, or its special audit-centric implementation CommitLogFilter [1]. Here is how to register a filter inside or outside a transaction [2]:

if (excludeFromTransaction) {
    ServerModule.contributeDomainSyncFilters(binder)
       .addAfter(MyFilter.class, TransactionFilter.class);
} else {
   ServerModule.contributeDomainSyncFilters(binder)
       .insertBefore(MyFilter.class, TransactionFilter.class);
}

So I hope this solves the immediate problem.

Andrus


[1] https://cayenne.apache.org/docs/4.1/cayenne-guide/#ext-commit-log
[2] https://github.com/apache/cayenne/blob/STABLE-4.1/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java#L117
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.