You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Matt Watson <ma...@swarmbox.com> on 2015/09/15 01:50:02 UTC
EventManager example usages
I was curious about what you could accomplish with EventManager listeners.
I have a scenario where I normally use the Cayenne lifecycle callbacks to detect when an Object was updated, and “sync” it to an external system.
class SalesOrder {
void sync() {
// send data to external system
}
@PostUpdate
void didUpdate() {
this.sync();
}
}
But I now want to sync a SalesOrder if it changes or if any of its SalesOrderLines (many relationship) change. But If both objects SalesOrder/SalesOrderLine are part of the same commit, then I don’t want the sync to get invoked more than once.
If I just used the logic below, its possible that the SalesOrder would get synced multiple times for all of its child SalesOrderLines, and possibly again if the SalesOrder itself changes
class SalesOrderLine {
@PostUpdate
void didUpdate() {
this.getSalesOrder().sync();
}
}
Was hoping to find something that I can execute after the commit of all objects is done, but call sync on the SalesOrder once. Can the EventManager help with this?
post-commit listeners?
Thanks,
Matt Watson
Re: EventManager example usages
Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi Matt,
Sorry for delayed reply.
So you have a case that I call "an aggregate" - a root object and its closely-related children. And it has to be processed only once during any given commit, even though multiple objects may have changed. We have a good example of that in Cayenne. Take a look at AuditableFilter [1] located in cayenne-lifecycle module. To define an aggregate for the audit operation it uses 2 annotations on DataObjects - @Auditable and @AuditableChild [2]. AuditableFilter itself defines a number of listener methods that are invoked in the context of a transaction when an annotated entity is modified. Instead of invoking an action immediately, the filter would combine the events together by the root of an aggregate.
You may write a similar filter for your case. You don't have to use @Auditable / @AuditableChild. Instead you would annotate the listener methods with @PostUpdate(SalesOrder.class) and @PostUpdate(SalesOrderLine.class)), etc. But you can use the same general approach.
Hope this helps, and please ask if anything is unclear in the AuditableFilter.
Andrus
[1] https://github.com/apache/cayenne/blob/master/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit/AuditableFilter.java
[2] https://github.com/apache/cayenne/tree/master/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/audit
> On Sep 15, 2015, at 2:50 AM, Matt Watson <ma...@swarmbox.com> wrote:
>
> I was curious about what you could accomplish with EventManager listeners.
>
> I have a scenario where I normally use the Cayenne lifecycle callbacks to detect when an Object was updated, and “sync” it to an external system.
>
> class SalesOrder {
> void sync() {
> // send data to external system
> }
>
> @PostUpdate
> void didUpdate() {
> this.sync();
> }
> }
>
>
> But I now want to sync a SalesOrder if it changes or if any of its SalesOrderLines (many relationship) change. But If both objects SalesOrder/SalesOrderLine are part of the same commit, then I don’t want the sync to get invoked more than once.
>
> If I just used the logic below, its possible that the SalesOrder would get synced multiple times for all of its child SalesOrderLines, and possibly again if the SalesOrder itself changes
>
> class SalesOrderLine {
> @PostUpdate
> void didUpdate() {
> this.getSalesOrder().sync();
> }
> }
>
> Was hoping to find something that I can execute after the commit of all objects is done, but call sync on the SalesOrder once. Can the EventManager help with this?
>
> post-commit listeners?
>
> Thanks,
>
> Matt Watson