You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Mike Kienenberger <mk...@gmail.com> on 2013/09/13 20:32:13 UTC

Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

So I'm finally making the attempt to upgrade my ancient Cayenne
project from 1.1 to 3.x.

The one kind of compile error I still haven't resolved is registering
for a data context commit.

I know I can register individual PrePersist, PreRemove, and PreUpdate
callbacks for individual entity types, but I don't see how I be
notified of with a single DataContext.WILL_COMMIT event once before
each context.commit().


I see three problems with trying to use the individual callbacks:

- Huge performance hit of being notified for each and every entity committed

- Another performance hit of setting up lifecycle notification by
iterating through the runtime metadata to register every existing
entity type for each of the three pre-commit listeners

and

- If nothing gets changed by the commit, then I would still get no notification.

Re: Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

Posted by Mike Kienenberger <mk...@gmail.com>.
Thanks for responding.  I hadn't seen DataChannelFilter as I was still on 3.0.

My use case is forcing a failure during a commit during testing.

Lifecycle callbacks won't work because I need to do something during a
DataContext commit rather than for individual entity changes as the
entities involved are not always easily known.

DataChannelFilter looks like it will give me what I need.   It looks
like I'll need to upgrade to 3.1 in order to use DataChannelFilter.
I need to do a little more debugging and testing under 3.0 before I
upgrade to 3.1, so I will stick with my local modification to generate
a DATACONTEXT_WILL_COMMIT event using EventManager for now, then
upgrade to DataChannelFilter.


On Sun, Sep 15, 2013 at 4:45 AM, Andrus Adamchik <an...@objectstyle.org> wrote:
> Hi Mike,
>
> We've been gradually moving from "event" to "callback" and model for object lifecycle tracking and to "interceptor" model for transaction state tracking. In practical terms this means that events dispatched via EventManager should be considered internal to the framework (there are probably exceptions to this rule, but that's the general direction). User application should instead be using callbacks on objects / listeners to receive per-object events and DataChannelFilter [1] to intercept transactions. The 2 approaches are synergetic and are often combined together [2].
>
> Will that be sufficient for your use cases?
>
> Andrus
>
>
> [1] http://cayenne.apache.org/docs/3.1/api/org/apache/cayenne/DataChannelFilter.html
> [2] http://cayenne.apache.org/docs/3.1/cayenne-guide/lifecycle-events.html#comining-listeners-with-datachannelfilters
>
> On Sep 13, 2013, at 9:32 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>> So I'm finally making the attempt to upgrade my ancient Cayenne
>> project from 1.1 to 3.x.
>>
>> The one kind of compile error I still haven't resolved is registering
>> for a data context commit.
>>
>> I know I can register individual PrePersist, PreRemove, and PreUpdate
>> callbacks for individual entity types, but I don't see how I be
>> notified of with a single DataContext.WILL_COMMIT event once before
>> each context.commit().
>>
>>
>> I see three problems with trying to use the individual callbacks:
>>
>> - Huge performance hit of being notified for each and every entity committed
>>
>> - Another performance hit of setting up lifecycle notification by
>> iterating through the runtime metadata to register every existing
>> entity type for each of the three pre-commit listeners
>>
>> and
>>
>> - If nothing gets changed by the commit, then I would still get no notification.
>>
>

Re: Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi Mike,

We've been gradually moving from "event" to "callback" and model for object lifecycle tracking and to "interceptor" model for transaction state tracking. In practical terms this means that events dispatched via EventManager should be considered internal to the framework (there are probably exceptions to this rule, but that's the general direction). User application should instead be using callbacks on objects / listeners to receive per-object events and DataChannelFilter [1] to intercept transactions. The 2 approaches are synergetic and are often combined together [2].

Will that be sufficient for your use cases? 

Andrus


[1] http://cayenne.apache.org/docs/3.1/api/org/apache/cayenne/DataChannelFilter.html
[2] http://cayenne.apache.org/docs/3.1/cayenne-guide/lifecycle-events.html#comining-listeners-with-datachannelfilters

On Sep 13, 2013, at 9:32 PM, Mike Kienenberger <mk...@gmail.com> wrote:
> So I'm finally making the attempt to upgrade my ancient Cayenne
> project from 1.1 to 3.x.
> 
> The one kind of compile error I still haven't resolved is registering
> for a data context commit.
> 
> I know I can register individual PrePersist, PreRemove, and PreUpdate
> callbacks for individual entity types, but I don't see how I be
> notified of with a single DataContext.WILL_COMMIT event once before
> each context.commit().
> 
> 
> I see three problems with trying to use the individual callbacks:
> 
> - Huge performance hit of being notified for each and every entity committed
> 
> - Another performance hit of setting up lifecycle notification by
> iterating through the runtime metadata to register every existing
> entity type for each of the three pre-commit listeners
> 
> and
> 
> - If nothing gets changed by the commit, then I would still get no notification.
> 


Re: Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

Posted by Mike Kienenberger <mk...@gmail.com>.
GRAPH_WILL_FLUSH turned out to be insufficient where it was placed.
I think it only picks up changes committed to a parent context.

I ended up going with this instead inside the synchronized block of
flushToParent().   And since it wasn't really dealing with graph
flushing at this point, I renamed it to DataContextWillCommit.

### Eclipse Workspace Patch 1.0
#P cayenne-STABLE-3.0
Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
===================================================================
--- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
   (revision 1523007)
+++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
   (working copy)
@@ -1110,6 +1110,9 @@
         synchronized (objectStore) {

             ObjectStoreGraphDiff changes = objectStore.getChanges();
+
+            fireDataContextWillCommit(this, changes);
+
             boolean noop = isValidatingObjectsOnCommit()
                     ? changes.validateAndCheckNoop()
                     : changes.isNoop();

On Sat, Sep 14, 2013 at 10:35 AM, Mike Kienenberger <mk...@gmail.com> wrote:
> As I noted on the user mailing list, I haven't been able to find an
> equivalent of DataContext.WILL_COMMIT in 3.0.2.
>
> This change adds that functionality and all the unit tests continue to
> pass.  Does anyone see a problem with it?   Is there a better approach
> to take?   Another approach I considered was to add a willCommit()
> method to DataContextDelegate.
>
> I haven't looked at 3.1 or 3.2 yet, but I'm going to guess that it
> will also work there.  The performance hit should be minor, especially
> since there will be no default listeners.
>
> Note that the change to DataContext is to fire the event as the first
> action in protected GraphDiff onContextFlush() -- the method name was
> unfortunately truncated in the diff.
>
>
> ### Eclipse Workspace Patch 1.0
> #P cayenne-STABLE-3.0
> Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
> ===================================================================
> --- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
>    (revision 1523007)
> +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
>    (working copy)
> @@ -1069,6 +1069,8 @@
>              GraphDiff changes,
>              boolean cascade) {
>
> +        fireDataChannelWillCommit(originatingContext, changes);
> +
>          boolean childContext = this != originatingContext && changes != null;
>
>          try {
> Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannel.java
> ===================================================================
> --- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannel.java
>    (revision 1523007)
> +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannel.java
>    (working copy)
> @@ -57,6 +57,10 @@
>      public static final EventSubject GRAPH_CHANGED_SUBJECT =
> EventSubject.getSubject(
>              DataChannel.class,
>              "graphChanged");
> +
> +    public static final EventSubject GRAPH_WILL_FLUSH_SUBJECT =
> EventSubject.getSubject(
> +            DataChannel.class,
> +            "graphWillFlush");
>
>      public static final EventSubject GRAPH_FLUSHED_SUBJECT =
> EventSubject.getSubject(
>              DataChannel.class,
> Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
> ===================================================================
> --- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
>    (revision 1523007)
> +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
>    (working copy)
> @@ -315,6 +315,18 @@
>              boolean cascade);
>
>      /**
> +     * @since 3.0.2
> +     */
> +    protected void fireDataChannelWillCommit(Object postedBy,
> GraphDiff changes) {
> +        EventManager manager = getEventManager();
> +
> +        if (manager != null) {
> +            GraphEvent e = new GraphEvent(this, postedBy, changes);
> +            manager.postEvent(e, DataChannel.GRAPH_WILL_FLUSH_SUBJECT);
> +        }
> +    }
> +
> +    /**
>       * @since 1.2
>       */
>      protected void fireDataChannelCommitted(Object postedBy,
> GraphDiff changes) {
>
> On Sat, Sep 14, 2013 at 10:04 AM, Mike Kienenberger <mk...@gmail.com> wrote:
>> Further testing shows that GRAPH_FLUSHED_SUBJECT would be DID_COMMIT
>> not WILL_COMMIT.
>> So I'm still unable to get a single one-time notification before a
>> DataContext will commit a transaction.
>>
>> On Fri, Sep 13, 2013 at 2:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>>> So right after I sent my last message, I realized that while
>>> DataContext.WILL_COMMIT was gone, EventManager was still around.
>>>
>>> I did a quick search to see what kind of events were published, and I
>>> saw this one:
>>>
>>> DataChannel.GRAPH_FLUSHED_SUBJECT
>>>
>>> Is this equivalent to the DataContext.WILL_COMMIT event?
>>>
>>>
>>>
>>> On Fri, Sep 13, 2013 at 2:32 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>>>> So I'm finally making the attempt to upgrade my ancient Cayenne
>>>> project from 1.1 to 3.x.
>>>>
>>>> The one kind of compile error I still haven't resolved is registering
>>>> for a data context commit.
>>>>
>>>> I know I can register individual PrePersist, PreRemove, and PreUpdate
>>>> callbacks for individual entity types, but I don't see how I be
>>>> notified of with a single DataContext.WILL_COMMIT event once before
>>>> each context.commit().
>>>>
>>>>
>>>> I see three problems with trying to use the individual callbacks:
>>>>
>>>> - Huge performance hit of being notified for each and every entity committed
>>>>
>>>> - Another performance hit of setting up lifecycle notification by
>>>> iterating through the runtime metadata to register every existing
>>>> entity type for each of the three pre-commit listeners
>>>>
>>>> and
>>>>
>>>> - If nothing gets changed by the commit, then I would still get no notification.

Re: Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

Posted by Mike Kienenberger <mk...@gmail.com>.
As I noted on the user mailing list, I haven't been able to find an
equivalent of DataContext.WILL_COMMIT in 3.0.2.

This change adds that functionality and all the unit tests continue to
pass.  Does anyone see a problem with it?   Is there a better approach
to take?   Another approach I considered was to add a willCommit()
method to DataContextDelegate.

I haven't looked at 3.1 or 3.2 yet, but I'm going to guess that it
will also work there.  The performance hit should be minor, especially
since there will be no default listeners.

Note that the change to DataContext is to fire the event as the first
action in protected GraphDiff onContextFlush() -- the method name was
unfortunately truncated in the diff.


### Eclipse Workspace Patch 1.0
#P cayenne-STABLE-3.0
Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
===================================================================
--- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
   (revision 1523007)
+++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
   (working copy)
@@ -1069,6 +1069,8 @@
             GraphDiff changes,
             boolean cascade) {

+        fireDataChannelWillCommit(originatingContext, changes);
+
         boolean childContext = this != originatingContext && changes != null;

         try {
Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannel.java
===================================================================
--- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannel.java
   (revision 1523007)
+++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/DataChannel.java
   (working copy)
@@ -57,6 +57,10 @@
     public static final EventSubject GRAPH_CHANGED_SUBJECT =
EventSubject.getSubject(
             DataChannel.class,
             "graphChanged");
+
+    public static final EventSubject GRAPH_WILL_FLUSH_SUBJECT =
EventSubject.getSubject(
+            DataChannel.class,
+            "graphWillFlush");

     public static final EventSubject GRAPH_FLUSHED_SUBJECT =
EventSubject.getSubject(
             DataChannel.class,
Index: framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
===================================================================
--- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
   (revision 1523007)
+++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
   (working copy)
@@ -315,6 +315,18 @@
             boolean cascade);

     /**
+     * @since 3.0.2
+     */
+    protected void fireDataChannelWillCommit(Object postedBy,
GraphDiff changes) {
+        EventManager manager = getEventManager();
+
+        if (manager != null) {
+            GraphEvent e = new GraphEvent(this, postedBy, changes);
+            manager.postEvent(e, DataChannel.GRAPH_WILL_FLUSH_SUBJECT);
+        }
+    }
+
+    /**
      * @since 1.2
      */
     protected void fireDataChannelCommitted(Object postedBy,
GraphDiff changes) {

On Sat, Sep 14, 2013 at 10:04 AM, Mike Kienenberger <mk...@gmail.com> wrote:
> Further testing shows that GRAPH_FLUSHED_SUBJECT would be DID_COMMIT
> not WILL_COMMIT.
> So I'm still unable to get a single one-time notification before a
> DataContext will commit a transaction.
>
> On Fri, Sep 13, 2013 at 2:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>> So right after I sent my last message, I realized that while
>> DataContext.WILL_COMMIT was gone, EventManager was still around.
>>
>> I did a quick search to see what kind of events were published, and I
>> saw this one:
>>
>> DataChannel.GRAPH_FLUSHED_SUBJECT
>>
>> Is this equivalent to the DataContext.WILL_COMMIT event?
>>
>>
>>
>> On Fri, Sep 13, 2013 at 2:32 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>>> So I'm finally making the attempt to upgrade my ancient Cayenne
>>> project from 1.1 to 3.x.
>>>
>>> The one kind of compile error I still haven't resolved is registering
>>> for a data context commit.
>>>
>>> I know I can register individual PrePersist, PreRemove, and PreUpdate
>>> callbacks for individual entity types, but I don't see how I be
>>> notified of with a single DataContext.WILL_COMMIT event once before
>>> each context.commit().
>>>
>>>
>>> I see three problems with trying to use the individual callbacks:
>>>
>>> - Huge performance hit of being notified for each and every entity committed
>>>
>>> - Another performance hit of setting up lifecycle notification by
>>> iterating through the runtime metadata to register every existing
>>> entity type for each of the three pre-commit listeners
>>>
>>> and
>>>
>>> - If nothing gets changed by the commit, then I would still get no notification.

Re: Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

Posted by Mike Kienenberger <mk...@gmail.com>.
Further testing shows that GRAPH_FLUSHED_SUBJECT would be DID_COMMIT
not WILL_COMMIT.
So I'm still unable to get a single one-time notification before a
DataContext will commit a transaction.

On Fri, Sep 13, 2013 at 2:39 PM, Mike Kienenberger <mk...@gmail.com> wrote:
> So right after I sent my last message, I realized that while
> DataContext.WILL_COMMIT was gone, EventManager was still around.
>
> I did a quick search to see what kind of events were published, and I
> saw this one:
>
> DataChannel.GRAPH_FLUSHED_SUBJECT
>
> Is this equivalent to the DataContext.WILL_COMMIT event?
>
>
>
> On Fri, Sep 13, 2013 at 2:32 PM, Mike Kienenberger <mk...@gmail.com> wrote:
>> So I'm finally making the attempt to upgrade my ancient Cayenne
>> project from 1.1 to 3.x.
>>
>> The one kind of compile error I still haven't resolved is registering
>> for a data context commit.
>>
>> I know I can register individual PrePersist, PreRemove, and PreUpdate
>> callbacks for individual entity types, but I don't see how I be
>> notified of with a single DataContext.WILL_COMMIT event once before
>> each context.commit().
>>
>>
>> I see three problems with trying to use the individual callbacks:
>>
>> - Huge performance hit of being notified for each and every entity committed
>>
>> - Another performance hit of setting up lifecycle notification by
>> iterating through the runtime metadata to register every existing
>> entity type for each of the three pre-commit listeners
>>
>> and
>>
>> - If nothing gets changed by the commit, then I would still get no notification.

Re: Upgrading from 1.1/1.2/2.0 DataContext.WILL_COMMIT to 3.x

Posted by Mike Kienenberger <mk...@gmail.com>.
So right after I sent my last message, I realized that while
DataContext.WILL_COMMIT was gone, EventManager was still around.

I did a quick search to see what kind of events were published, and I
saw this one:

DataChannel.GRAPH_FLUSHED_SUBJECT

Is this equivalent to the DataContext.WILL_COMMIT event?



On Fri, Sep 13, 2013 at 2:32 PM, Mike Kienenberger <mk...@gmail.com> wrote:
> So I'm finally making the attempt to upgrade my ancient Cayenne
> project from 1.1 to 3.x.
>
> The one kind of compile error I still haven't resolved is registering
> for a data context commit.
>
> I know I can register individual PrePersist, PreRemove, and PreUpdate
> callbacks for individual entity types, but I don't see how I be
> notified of with a single DataContext.WILL_COMMIT event once before
> each context.commit().
>
>
> I see three problems with trying to use the individual callbacks:
>
> - Huge performance hit of being notified for each and every entity committed
>
> - Another performance hit of setting up lifecycle notification by
> iterating through the runtime metadata to register every existing
> entity type for each of the three pre-commit listeners
>
> and
>
> - If nothing gets changed by the commit, then I would still get no notification.