Repository: cayenne
Updated Branches:
  refs/heads/master df5d38f7a -> a639980d2


Split DataChannelFilter into Query and Sync filters


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/7475b4e0
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/7475b4e0
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/7475b4e0

Branch: refs/heads/master
Commit: 7475b4e09159e5fc5af8d9dadc1243bfb84b61aa
Parents: 22c2e78
Author: Nikita Timofeev <stari...@gmail.com>
Authored: Tue May 29 18:36:41 2018 +0300
Committer: Nikita Timofeev <stari...@gmail.com>
Committed: Fri Jun 8 16:18:26 2018 +0300

----------------------------------------------------------------------
 .../invalidation/CacheInvalidationFilter.java   |  44 ++---
 .../invalidation/CacheInvalidationModule.java   |   2 +-
 .../cayenne/commitlog/CommitLogFilter.java      |  22 +--
 .../commitlog/CommitLogModuleExtender.java      |   4 +-
 ...jectIdRelationshipBatchFaultingStrategy.java |   2 +-
 .../ObjectIdRelationshipFilter.java             |  30 +---
 .../ObjectIdRelationshipHandlerTest.java        |  14 +-
 .../org/apache/cayenne/DataChannelFilter.java   |  47 ++++--
 .../apache/cayenne/DataChannelFilterChain.java  |   9 +-
 .../apache/cayenne/DataChannelQueryFilter.java  |  32 ++++
 .../cayenne/DataChannelQueryFilterChain.java    |  31 ++++
 .../apache/cayenne/DataChannelSyncFilter.java   |  35 ++++
 .../org/apache/cayenne/access/DataDomain.java   | 168 +++++++++++++------
 .../apache/cayenne/configuration/Constants.java |   5 +-
 .../server/DataDomainProvider.java              |  28 ++++
 .../configuration/server/ServerModule.java      |  32 +++-
 .../apache/cayenne/tx/TransactionFilter.java    |  36 ++--
 .../apache/cayenne/MockDataChannelFilter.java   |  44 -----
 .../cayenne/access/DataDomainFiltersIT.java     | 143 +++++-----------
 .../server/DataDomainProviderTest.java          |   2 +
 .../unit/di/server/ServerCaseModule.java        |   4 +
 21 files changed, 413 insertions(+), 321 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationFilter.java
 
b/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationFilter.java
index 85063e7..2d7eb15 100644
--- 
a/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationFilter.java
+++ 
b/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationFilter.java
@@ -19,12 +19,10 @@
 
 package org.apache.cayenne.cache.invalidation;
 
-import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.DataChannelFilter;
-import org.apache.cayenne.DataChannelFilterChain;
+import org.apache.cayenne.DataChannelSyncFilter;
+import org.apache.cayenne.DataChannelSyncFilterChain;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.Persistent;
-import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.annotation.PrePersist;
 import org.apache.cayenne.annotation.PreRemove;
 import org.apache.cayenne.annotation.PreUpdate;
@@ -32,7 +30,6 @@ import org.apache.cayenne.cache.QueryCache;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.di.Provider;
 import org.apache.cayenne.graph.GraphDiff;
-import org.apache.cayenne.query.Query;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -45,7 +42,7 @@ import java.util.function.Function;
 
 /**
  * <p>
- * A {@link DataChannelFilter} that invalidates cache groups.
+ * A {@link DataChannelSyncFilter} that invalidates cache groups.
  * Use custom rules for invalidation provided via DI.
  * </p>
  * <p>
@@ -62,7 +59,7 @@ import java.util.function.Function;
  * @see InvalidationHandler
  * @since 4.0 enhanced to support custom handlers.
  */
-public class CacheInvalidationFilter implements DataChannelFilter {
+public class CacheInvalidationFilter implements DataChannelSyncFilter {
 
     private final Provider<QueryCache> cacheProvider;
     private final List<InvalidationHandler> handlers;
@@ -78,16 +75,9 @@ public class CacheInvalidationFilter implements 
DataChannelFilter {
         this.handlers = handlers;
     }
 
-    public void init(DataChannel channel) {
-        // noop
-    }
-
-    public QueryResponse onQuery(ObjectContext originatingContext, Query 
query, DataChannelFilterChain filterChain) {
-        return filterChain.onQuery(originatingContext, query);
-    }
-
+    @Override
     public GraphDiff onSync(ObjectContext originatingContext, GraphDiff 
changes,
-                            int syncType, DataChannelFilterChain filterChain) {
+                            int syncType, DataChannelSyncFilterChain 
filterChain) {
         try {
             GraphDiff result = filterChain.onSync(originatingContext, changes, 
syncType);
             // no exceptions, flush...
@@ -118,18 +108,16 @@ public class CacheInvalidationFilter implements 
DataChannelFilter {
         // TODO: for some reason we can't use Persistent as the argument 
type... (is it fixed in Cayenne 4.0.M4?)
         Persistent p = (Persistent) object;
 
-        Function<Persistent, Collection<CacheGroupDescriptor>> 
invalidationFunction = mappedHandlers.get(p.getClass());
-        if (invalidationFunction == null) {
-            invalidationFunction = skipHandler;
-            for (InvalidationHandler handler : handlers) {
-                Function<Persistent, Collection<CacheGroupDescriptor>> 
function = handler.canHandle(p.getClass());
-                if (function != null) {
-                    invalidationFunction = function;
-                    break;
-                }
-            }
-            mappedHandlers.put(p.getClass(), invalidationFunction);
-        }
+        Function<Persistent, Collection<CacheGroupDescriptor>> 
invalidationFunction = mappedHandlers
+                .computeIfAbsent(p.getClass(), cl -> {
+                    for (InvalidationHandler handler : handlers) {
+                        Function<Persistent, Collection<CacheGroupDescriptor>> 
function = handler.canHandle(cl);
+                        if (function != null) {
+                            return function;
+                        }
+                    }
+                    return skipHandler;
+                });
 
         Collection<CacheGroupDescriptor> objectGroups = 
invalidationFunction.apply(p);
         if (!objectGroups.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationModule.java
----------------------------------------------------------------------
diff --git 
a/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationModule.java
 
b/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationModule.java
index 822dbc6..2460a99 100644
--- 
a/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationModule.java
+++ 
b/cayenne-cache-invalidation/src/main/java/org/apache/cayenne/cache/invalidation/CacheInvalidationModule.java
@@ -52,7 +52,7 @@ public class CacheInvalidationModule implements Module {
         contributeInvalidationHandler(binder).add(CacheGroupsHandler.class);
 
         // want the filter to be INSIDE transaction by default
-        ServerModule.contributeDomainFilters(binder)
+        ServerModule.contributeDomainSyncFilters(binder)
                 .insertBefore(CacheInvalidationFilter.class, 
TransactionFilter.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogFilter.java
 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogFilter.java
index a3c8a30..b383dc2 100644
--- 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogFilter.java
+++ 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogFilter.java
@@ -22,25 +22,23 @@ import java.util.Collection;
 import java.util.List;
 
 import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.DataChannelFilter;
-import org.apache.cayenne.DataChannelFilterChain;
+import org.apache.cayenne.DataChannelSyncFilter;
+import org.apache.cayenne.DataChannelSyncFilterChain;
 import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.graph.GraphChangeHandler;
 import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.commitlog.model.ChangeMap;
 import org.apache.cayenne.commitlog.model.MutableChangeMap;
 import org.apache.cayenne.commitlog.meta.CommitLogEntityFactory;
-import org.apache.cayenne.query.Query;
 
 /**
- * A {@link DataChannelFilter} that captures commit changes, delegating their
+ * A {@link DataChannelSyncFilter} that captures commit changes, delegating 
their
  * processing to an underlying collection of listeners.
  * 
  * @since 4.0
  */
-public class CommitLogFilter implements DataChannelFilter {
+public class CommitLogFilter implements DataChannelSyncFilter {
 
        private CommitLogEntityFactory entityFactory;
        private Collection<CommitLogListener> listeners;
@@ -52,18 +50,8 @@ public class CommitLogFilter implements DataChannelFilter {
        }
 
        @Override
-       public void init(DataChannel channel) {
-               // do nothing...
-       }
-
-       @Override
-       public QueryResponse onQuery(ObjectContext originatingContext, Query 
query, DataChannelFilterChain filterChain) {
-               return filterChain.onQuery(originatingContext, query);
-       }
-
-       @Override
        public GraphDiff onSync(ObjectContext originatingContext, GraphDiff 
beforeDiff, int syncType,
-                       DataChannelFilterChain filterChain) {
+                                                       
DataChannelSyncFilterChain filterChain) {
 
                // process commits only; skip rollback
                if (syncType != DataChannel.FLUSH_CASCADE_SYNC && syncType != 
DataChannel.FLUSH_NOCASCADE_SYNC) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
----------------------------------------------------------------------
diff --git 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
index 558dcba..3c96a48 100644
--- 
a/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
+++ 
b/cayenne-commitlog/src/main/java/org/apache/cayenne/commitlog/CommitLogModuleExtender.java
@@ -115,9 +115,9 @@ public class CommitLogModuleExtender {
             }
 
             if (excludeFromTransaction) {
-                
ServerModule.contributeDomainFilters(binder).addAfter(CommitLogFilter.class, 
TransactionFilter.class);
+                
ServerModule.contributeDomainSyncFilters(binder).addAfter(CommitLogFilter.class,
 TransactionFilter.class);
             } else {
-                
ServerModule.contributeDomainFilters(binder).insertBefore(CommitLogFilter.class,
 TransactionFilter.class);
+                
ServerModule.contributeDomainSyncFilters(binder).insertBefore(CommitLogFilter.class,
 TransactionFilter.class);
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipBatchFaultingStrategy.java
----------------------------------------------------------------------
diff --git 
a/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipBatchFaultingStrategy.java
 
b/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipBatchFaultingStrategy.java
index 4499880..506fbcd 100644
--- 
a/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipBatchFaultingStrategy.java
+++ 
b/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipBatchFaultingStrategy.java
@@ -35,7 +35,7 @@ public class ObjectIdRelationshipBatchFaultingStrategy 
implements
     private ThreadLocal<List<ObjectIdBatchSourceItem>> batchSources;
 
     public ObjectIdRelationshipBatchFaultingStrategy() {
-        this.batchSources = new ThreadLocal<List<ObjectIdBatchSourceItem>>();
+        this.batchSources = new ThreadLocal<>();
     }
 
     public void afterObjectLoaded(DataObject object) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipFilter.java
 
b/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipFilter.java
index 957c093..bf7bb88 100644
--- 
a/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipFilter.java
+++ 
b/cayenne-lifecycle/src/main/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipFilter.java
@@ -18,28 +18,26 @@
  ****************************************************************/
 package org.apache.cayenne.lifecycle.relationship;
 
-import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.DataChannelFilter;
-import org.apache.cayenne.DataChannelFilterChain;
+import org.apache.cayenne.DataChannelQueryFilter;
+import org.apache.cayenne.DataChannelQueryFilterChain;
 import org.apache.cayenne.DataObject;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.annotation.PostLoad;
 import org.apache.cayenne.annotation.PostPersist;
 import org.apache.cayenne.annotation.PostUpdate;
-import org.apache.cayenne.graph.GraphDiff;
 import org.apache.cayenne.query.Query;
 
 /**
- * A {@link DataChannelFilter} that implements ObjectId relationships read 
functionality.
+ * A {@link DataChannelQueryFilter} that implements ObjectId relationships 
read functionality.
  * 
  * @since 3.1
  */
-public class ObjectIdRelationshipFilter implements DataChannelFilter {
+public class ObjectIdRelationshipFilter implements DataChannelQueryFilter {
 
     private ObjectIdRelationshipFaultingStrategy faultingStrategy;
 
-    public void init(DataChannel channel) {
+    public ObjectIdRelationshipFilter() {
         this.faultingStrategy = createFaultingStrategy();
     }
 
@@ -47,24 +45,10 @@ public class ObjectIdRelationshipFilter implements 
DataChannelFilter {
         return new ObjectIdRelationshipBatchFaultingStrategy();
     }
 
-    public GraphDiff onSync(
-            ObjectContext context,
-            GraphDiff diff,
-            int syncType,
-            DataChannelFilterChain chain) {
-        // noop ... all work is done via listeners...
-        return chain.onSync(context, diff, syncType);
-    }
-
-    public QueryResponse onQuery(
-            ObjectContext context,
-            Query query,
-            DataChannelFilterChain chain) {
-
+    public QueryResponse onQuery(ObjectContext context, Query query, 
DataChannelQueryFilterChain chain) {
         try {
             return chain.onQuery(context, query);
-        }
-        finally {
+        } finally {
             faultingStrategy.afterQuery();
         }
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipHandlerTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipHandlerTest.java
 
b/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipHandlerTest.java
index 8cbcdb7..4c21d74 100644
--- 
a/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipHandlerTest.java
+++ 
b/cayenne-lifecycle/src/test/java/org/apache/cayenne/lifecycle/relationship/ObjectIdRelationshipHandlerTest.java
@@ -32,7 +32,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertSame;
 
 public class ObjectIdRelationshipHandlerTest {
@@ -48,9 +48,8 @@ public class ObjectIdRelationshipHandlerTest {
 
         // a filter is required to invalidate root objects after commit
         ObjectIdRelationshipFilter filter = new ObjectIdRelationshipFilter();
-        runtime.getDataDomain().addFilter(filter);
-        
runtime.getDataDomain().getEntityResolver().getCallbackRegistry().addListener(
-                filter);
+        runtime.getDataDomain().addQueryFilter(filter);
+        
runtime.getDataDomain().getEntityResolver().getCallbackRegistry().addListener(filter);
 
         DBHelper dbHelper = new DBHelper(runtime.getDataSource(null));
 
@@ -62,7 +61,7 @@ public class ObjectIdRelationshipHandlerTest {
     }
 
     @After
-    public void tearDown() throws Exception {
+    public void tearDown() {
         runtime.shutdown();
     }
 
@@ -76,8 +75,7 @@ public class ObjectIdRelationshipHandlerTest {
 
         UuidRoot1 r1 = context.newObject(UuidRoot1.class);
 
-        IdCoder refHandler = new IdCoder(context
-                .getEntityResolver());
+        IdCoder refHandler = new IdCoder(context.getEntityResolver());
         ObjectIdRelationshipHandler handler = new 
ObjectIdRelationshipHandler(refHandler);
         handler.relate(r1, e1);
 
@@ -137,7 +135,7 @@ public class ObjectIdRelationshipHandlerTest {
         context.commitChanges();
 
         int id = Cayenne.intPKForObject(e1);
-        assertFalse(1 == id);
+        assertNotEquals(1, id);
 
         Object[] r1x = rootTable.select();
         assertEquals("E1:" + id, r1x[1]);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilter.java 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilter.java
index 585d01b..24d625c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilter.java
@@ -28,19 +28,44 @@ import org.apache.cayenne.query.Query;
  * etc.
  * 
  * @since 3.1
+ * @deprecated since 4.1 use {@link DataChannelQueryFilter} and {@link 
DataChannelSyncFilter}
  */
-public interface DataChannelFilter {
-    
+@Deprecated
+public interface DataChannelFilter extends DataChannelSyncFilter, 
DataChannelQueryFilter {
+
     void init(DataChannel channel);
 
-    QueryResponse onQuery(
-            ObjectContext originatingContext,
-            Query query,
-            DataChannelFilterChain filterChain);
+    QueryResponse onQuery(ObjectContext originatingContext, Query query,
+                          DataChannelFilterChain filterChain);
+
+    GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int 
syncType,
+                     DataChannelFilterChain filterChain);
+
+    /**
+     * Adapter method that allows to use old DataChannelFilter as new query 
filter
+     */
+    @Override
+    default QueryResponse onQuery(ObjectContext originatingContext, Query 
query,
+                                  DataChannelQueryFilterChain filterChain) {
+        return onQuery(originatingContext, query, new DataChannelFilterChain(){
+            @Override
+            public QueryResponse onQuery(ObjectContext originatingContext, 
Query query) {
+                return filterChain.onQuery(originatingContext, query);
+            }
+        });
+    }
 
-    GraphDiff onSync(
-            ObjectContext originatingContext,
-            GraphDiff changes,
-            int syncType,
-            DataChannelFilterChain filterChain);
+    /**
+     * Adapter method that allows to use old DataChannelFilter as new sync 
filter
+     */
+    @Override
+    default GraphDiff onSync(ObjectContext originatingContext, GraphDiff 
changes, int syncType,
+                             DataChannelSyncFilterChain filterChain) {
+        return onSync(originatingContext, changes, syncType, new 
DataChannelFilterChain(){
+            @Override
+            public GraphDiff onSync(ObjectContext originatingContext, 
GraphDiff changes, int syncType) {
+                return filterChain.onSync(originatingContext, changes, 
syncType);
+            }
+        });
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilterChain.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilterChain.java 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilterChain.java
index 594c3a7..20d554d 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilterChain.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelFilterChain.java
@@ -26,10 +26,15 @@ import org.apache.cayenne.query.Query;
  * the underlying DataChannel for the last chain filter.
  * 
  * @since 3.1
+ * @deprecated since 4.1 in favor of {@link DataChannelSyncFilterChain} and 
{@link DataChannelQueryFilterChain}
  */
 public interface DataChannelFilterChain {
 
-    QueryResponse onQuery(ObjectContext originatingContext, Query query);
+    default QueryResponse onQuery(ObjectContext originatingContext, Query 
query) {
+        throw new UnsupportedOperationException();
+    }
 
-    GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int 
syncType);
+    default GraphDiff onSync(ObjectContext originatingContext, GraphDiff 
changes, int syncType) {
+        throw new UnsupportedOperationException();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilter.java 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilter.java
new file mode 100644
index 0000000..04f0ef1
--- /dev/null
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilter.java
@@ -0,0 +1,32 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne;
+
+import org.apache.cayenne.query.Query;
+
+/**
+ * @since 4.1
+ */
+@FunctionalInterface
+public interface DataChannelQueryFilter {
+
+    QueryResponse onQuery(ObjectContext originatingContext, Query query, 
DataChannelQueryFilterChain filterChain);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilterChain.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilterChain.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilterChain.java
new file mode 100644
index 0000000..322d9d2
--- /dev/null
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelQueryFilterChain.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne;
+
+import org.apache.cayenne.query.Query;
+
+/**
+ * @since 4.1
+ */
+public interface DataChannelQueryFilterChain {
+
+    QueryResponse onQuery(ObjectContext originatingContext, Query query);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncFilter.java 
b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncFilter.java
new file mode 100644
index 0000000..96f1cdd
--- /dev/null
+++ b/cayenne-server/src/main/java/org/apache/cayenne/DataChannelSyncFilter.java
@@ -0,0 +1,35 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+package org.apache.cayenne;
+
+import org.apache.cayenne.graph.GraphDiff;
+
+/**
+ * @since 4.1
+ */
+public interface DataChannelSyncFilter {
+
+    GraphDiff onSync(
+            ObjectContext originatingContext,
+            GraphDiff changes,
+            int syncType,
+            DataChannelSyncFilterChain filterChain);
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomain.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomain.java 
b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomain.java
index bb68fdb..ecd0938 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomain.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomain.java
@@ -22,7 +22,10 @@ package org.apache.cayenne.access;
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.DataChannelFilter;
-import org.apache.cayenne.DataChannelFilterChain;
+import org.apache.cayenne.DataChannelQueryFilter;
+import org.apache.cayenne.DataChannelQueryFilterChain;
+import org.apache.cayenne.DataChannelSyncFilter;
+import org.apache.cayenne.DataChannelSyncFilterChain;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.cache.QueryCache;
@@ -91,9 +94,21 @@ public class DataDomain implements QueryEngine, DataChannel {
 
        /**
         * @since 3.1
+        * @deprecated since 4.1 this field is unused
         */
+       @Deprecated
        protected List<DataChannelFilter> filters;
 
+       /**
+        * @since 4.1
+        */
+       protected List<DataChannelQueryFilter> queryFilters;
+
+       /**
+        * @since 4.1
+        */
+       protected List<DataChannelSyncFilter> syncFilters;
+
        protected Map<String, DataNode> nodes;
        protected Map<String, DataNode> nodesByDataMapName;
        protected DataNode defaultNode;
@@ -146,7 +161,8 @@ public class DataDomain implements QueryEngine, DataChannel 
{
 
        private void init(String name) {
 
-               this.filters = new CopyOnWriteArrayList<>();
+               this.queryFilters = new CopyOnWriteArrayList<>();
+               this.syncFilters = new CopyOnWriteArrayList<>();
                this.nodesByDataMapName = new ConcurrentHashMap<>();
                this.nodes = new ConcurrentHashMap<>();
 
@@ -388,15 +404,8 @@ public class DataDomain implements QueryEngine, 
DataChannel {
        public void removeDataNode(String nodeName) {
                DataNode removed = nodes.remove(nodeName);
                if (removed != null) {
-
                        removed.setEntityResolver(null);
-
-                       Iterator<DataNode> it = 
nodesByDataMapName.values().iterator();
-                       while (it.hasNext()) {
-                               if (it.next() == removed) {
-                                       it.remove();
-                               }
-                       }
+                       nodesByDataMapName.values().removeIf(dataNode -> 
dataNode == removed);
                }
        }
 
@@ -520,13 +529,9 @@ public class DataDomain implements QueryEngine, 
DataChannel {
         * Routes queries to appropriate DataNodes for execution.
         */
        public void performQueries(final Collection<? extends Query> queries, 
final OperationObserver callback) {
-
-               transactionManager.performInTransaction(new 
TransactionalOperation<Object>() {
-                       @Override
-                       public Object perform() {
-                               new 
DataDomainLegacyQueryAction(DataDomain.this, new QueryChain(queries), 
callback).execute();
-                               return null;
-                       }
+               transactionManager.performInTransaction(() -> {
+                       new DataDomainLegacyQueryAction(DataDomain.this, new 
QueryChain(queries), callback).execute();
+                       return null;
                });
        }
 
@@ -667,16 +672,40 @@ public class DataDomain implements QueryEngine, 
DataChannel {
        }
 
        /**
-        * Returns an unmodifiable list of filters registered with this 
DataDomain.
+        * Since 4.1 returns empty list.
+        *
+        * @since 3.1
+        * @deprecated since 4.1 use {@link #getQueryFilters()} and {@link 
#getSyncFilters()}
+        */
+       @Deprecated
+       public List<DataChannelFilter> getFilters() {
+               return Collections.emptyList();
+       }
+
+       /**
+        * Returns an unmodifiable list of query filters registered with this 
DataDomain.
         * <p>
         * Filter ordering note: filters are applied in reverse order of their
         * occurrence in the filter list. I.e. the last filter in the list 
called
         * first in the chain.
         *
-        * @since 3.1
+        * @since 4.1
         */
-       public List<DataChannelFilter> getFilters() {
-               return Collections.unmodifiableList(filters);
+       public List<DataChannelQueryFilter> getQueryFilters() {
+               return Collections.unmodifiableList(queryFilters);
+       }
+
+       /**
+        * Returns an unmodifiable list of sync filters registered with this 
DataDomain.
+        * <p>
+        * Filter ordering note: filters are applied in reverse order of their
+        * occurrence in the filter list. I.e. the last filter in the list 
called
+        * first in the chain.
+        *
+        * @since 4.1
+        */
+       public List<DataChannelSyncFilter> getSyncFilters() {
+               return Collections.unmodifiableList(syncFilters);
        }
 
        /**
@@ -685,20 +714,66 @@ public class DataDomain implements QueryEngine, 
DataChannel {
         * methods have event annotations.
         *
         * @since 3.1
+        * @deprecated since 4.1 use {@link 
#addQueryFilter(DataChannelQueryFilter)} and {@link 
#addSyncFilter(DataChannelSyncFilter)} instead
         */
+       @Deprecated
        public void addFilter(DataChannelFilter filter) {
                filter.init(this);
-               getEntityResolver().getCallbackRegistry().addListener(filter);
-               filters.add(filter);
+               addListener(filter);
+               queryFilters.add(filter);
+               syncFilters.add(filter);
+       }
+
+       /**
+        * Adds a new query filter.
+        * Also registers passed filter as an event listener, if any of its 
methods have event annotations.
+        *
+        * @since 4.1
+        */
+       public void addQueryFilter(DataChannelQueryFilter filter) {
+               addListener(filter);
+               queryFilters.add(filter);
+       }
+
+       /**
+        * Adds a new sync filter.
+        * Also registers passed filter as an event listener, if any of its 
methods have event annotations.
+        *
+        * @since 4.1
+        */
+       public void addSyncFilter(DataChannelSyncFilter filter) {
+               addListener(filter);
+               syncFilters.add(filter);
        }
 
        /**
         * Removes a filter from the filter chain.
         *
         * @since 3.1
+        * @deprecated since 4.1 use {@link 
#removeQueryFilter(DataChannelQueryFilter)} and {@link 
#removeSyncFilter(DataChannelSyncFilter)} instead
         */
+       @Deprecated
        public void removeFilter(DataChannelFilter filter) {
-               filters.remove(filter);
+               removeQueryFilter(filter);
+               removeSyncFilter(filter);
+       }
+
+       /**
+        * Removes a query filter from the filter chain.
+        *
+        * @since 4.1
+        */
+       public void removeQueryFilter(DataChannelQueryFilter filter) {
+               queryFilters.remove(filter);
+       }
+
+       /**
+        * Removes a sync filter from the filter chain.
+        *
+        * @since 4.1
+        */
+       public void removeSyncFilter(DataChannelSyncFilter filter) {
+               syncFilters.remove(filter);
        }
 
        /**
@@ -712,50 +787,35 @@ public class DataDomain implements QueryEngine, 
DataChannel {
                getEntityResolver().getCallbackRegistry().addListener(listener);
        }
 
-       abstract class DataDomainFilterChain implements DataChannelFilterChain {
+       final class DataDomainQueryFilterChain implements 
DataChannelQueryFilterChain {
 
-               private int i;
-
-               DataDomainFilterChain() {
-                       i = filters != null ? filters.size() : 0;
-               }
+               private int idx;
 
-               DataChannelFilter nextFilter() {
-                       // filters are ordered innermost to outermost
-                       i--;
-                       return i >= 0 ? filters.get(i) : null;
+               DataDomainQueryFilterChain() {
+                       idx = queryFilters.size();
                }
-       }
-
-       final class DataDomainQueryFilterChain extends DataDomainFilterChain {
 
                @Override
                public QueryResponse onQuery(ObjectContext originatingContext, 
Query query) {
-
-                       DataChannelFilter filter = nextFilter();
-                       return (filter != null) ? 
filter.onQuery(originatingContext, query, this) : onQueryNoFilters(
-                                       originatingContext, query);
-               }
-
-               @Override
-               public GraphDiff onSync(ObjectContext originatingContext, 
GraphDiff changes, int syncType) {
-                       throw new UnsupportedOperationException("It is illegal 
to call 'onSync' inside 'onQuery' chain");
+                       return --idx >= 0
+                                       ? 
queryFilters.get(idx).onQuery(originatingContext, query, this)
+                                       : onQueryNoFilters(originatingContext, 
query);
                }
        }
 
-       final class DataDomainSyncFilterChain extends DataDomainFilterChain {
+       final class DataDomainSyncFilterChain implements 
DataChannelSyncFilterChain {
 
-               @Override
-               public GraphDiff onSync(final ObjectContext originatingContext, 
final GraphDiff changes, int syncType) {
+               private int idx;
 
-                       DataChannelFilter filter = nextFilter();
-                       return (filter != null) ? 
filter.onSync(originatingContext, changes, syncType, this) : onSyncNoFilters(
-                                       originatingContext, changes, syncType);
+               DataDomainSyncFilterChain() {
+                       idx = syncFilters.size();
                }
 
                @Override
-               public QueryResponse onQuery(ObjectContext originatingContext, 
Query query) {
-                       throw new UnsupportedOperationException("It is illegal 
to call 'onQuery' inside 'onSync' chain");
+               public GraphDiff onSync(ObjectContext originatingContext, final 
GraphDiff changes, int syncType) {
+                       return --idx >= 0
+                                       ? 
syncFilters.get(idx).onSync(originatingContext, changes, syncType, this)
+                                       : onSyncNoFilters(originatingContext, 
changes, syncType);
                }
        }
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java 
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
index 2704ae4..7eb45dc 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/Constants.java
@@ -48,8 +48,11 @@ public interface Constants {
      * A DI container key for the List&lt;DataChannelFilter&gt; storing
      * DataDomain filters.
      *
-     * @see 
org.apache.cayenne.configuration.server.ServerModule#contributeDomainFilters(Binder).
+     * @see 
org.apache.cayenne.configuration.server.ServerModule#contributeDomainQueryFilters(Binder)
+     * @see 
org.apache.cayenne.configuration.server.ServerModule#contributeDomainSyncFilters(Binder)
+     * @deprecated since 4.1 domain filters replaced with query and sync 
filters
      */
+    @Deprecated
     String SERVER_DOMAIN_FILTERS_LIST = "cayenne.server.domain_filters";
 
     /**

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
index f0d3402..26573d1 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/DataDomainProvider.java
@@ -21,6 +21,8 @@ package org.apache.cayenne.configuration.server;
 import org.apache.cayenne.ConfigurationException;
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.DataChannelFilter;
+import org.apache.cayenne.DataChannelQueryFilter;
+import org.apache.cayenne.DataChannelSyncFilter;
 import org.apache.cayenne.access.DataDomain;
 import org.apache.cayenne.access.DataNode;
 import org.apache.cayenne.access.DataRowStoreFactory;
@@ -68,9 +70,25 @@ public class DataDomainProvider implements 
Provider<DataDomain> {
        @Inject
        protected DataChannelDescriptorLoader loader;
 
+       /**
+        * @deprecated since 4.1, use query and sync filters instead
+        */
+       @Deprecated
        @Inject(Constants.SERVER_DOMAIN_FILTERS_LIST)
        protected List<DataChannelFilter> filters;
 
+       /**
+        * @since 4.1
+        */
+       @Inject
+       protected List<DataChannelQueryFilter> queryFilters;
+
+       /**
+        * @since 4.1
+        */
+       @Inject
+       protected List<DataChannelSyncFilter> syncFilters;
+
        @Inject(Constants.SERVER_DOMAIN_LISTENERS_LIST)
        protected List<Object> listeners;
 
@@ -110,6 +128,7 @@ public class DataDomainProvider implements 
Provider<DataDomain> {
                return new DataDomain(name);
        }
 
+       @SuppressWarnings("deprecation")
        protected DataDomain createAndInitDataDomain() throws Exception {
 
                DataChannelDescriptor descriptor = loadDescriptor();
@@ -156,10 +175,19 @@ public class DataDomainProvider implements 
Provider<DataDomain> {
                        dataDomain.setDefaultNode(defaultNode);
                }
 
+               // filters are deprecated, used here for backward compatibility
                for (DataChannelFilter filter : filters) {
                        dataDomain.addFilter(filter);
                }
 
+               for (DataChannelQueryFilter filter : queryFilters) {
+                       dataDomain.addQueryFilter(filter);
+               }
+
+               for (DataChannelSyncFilter filter : syncFilters) {
+                       dataDomain.addSyncFilter(filter);
+               }
+
                for (Object listener : listeners) {
                        dataDomain.addListener(listener);
                }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
index 39e8c14..3a1987d 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/configuration/server/ServerModule.java
@@ -20,6 +20,8 @@ package org.apache.cayenne.configuration.server;
 
 import org.apache.cayenne.DataChannel;
 import org.apache.cayenne.DataChannelFilter;
+import org.apache.cayenne.DataChannelQueryFilter;
+import org.apache.cayenne.DataChannelSyncFilter;
 import org.apache.cayenne.access.DataDomain;
 import org.apache.cayenne.access.DataRowStoreFactory;
 import org.apache.cayenne.access.DefaultDataRowStoreFactory;
@@ -202,12 +204,38 @@ public class ServerModule implements Module {
      * @param binder DI binder passed to the module during injector startup.
      * @return ListBuilder for DataChannelFilter.
      * @since 4.0
+     * @deprecated since 4.1 use {@link #contributeDomainQueryFilters(Binder)} 
and {@link #contributeDomainSyncFilters(Binder)}
      */
+    @Deprecated
     public static ListBuilder<DataChannelFilter> 
contributeDomainFilters(Binder binder) {
         return binder.bindList(DataChannelFilter.class, 
Constants.SERVER_DOMAIN_FILTERS_LIST);
     }
 
     /**
+     * Provides access to a DI collection builder for {@link 
DataChannelQueryFilter}'s that allows downstream modules to
+     * "contribute" their own DataDomain query filters
+     *
+     * @param binder DI binder passed to the module during injector startup.
+     * @return ListBuilder for DataChannelQueryFilter.
+     * @since 4.1
+     */
+    public static ListBuilder<DataChannelQueryFilter> 
contributeDomainQueryFilters(Binder binder) {
+        return binder.bindList(DataChannelQueryFilter.class);
+    }
+
+    /**
+     * Provides access to a DI collection builder for {@link 
DataChannelSyncFilter}'s that allows downstream modules to
+     * "contribute" their own DataDomain sync filters
+     *
+     * @param binder DI binder passed to the module during injector startup.
+     * @return ListBuilder for DataChannelSyncFilter.
+     * @since 4.1
+     */
+    public static ListBuilder<DataChannelSyncFilter> 
contributeDomainSyncFilters(Binder binder) {
+        return binder.bindList(DataChannelSyncFilter.class);
+    }
+
+    /**
      * Provides access to a DI collection builder for lifecycle events 
listeners.
      *
      * @param binder DI binder passed to the module during injector startup.
@@ -358,7 +386,9 @@ public class ServerModule implements Module {
                 .put(SybaseAdapter.class.getName(), SybasePkGenerator.class);
 
         // configure a filter chain with only one TransactionFilter as default
-        contributeDomainFilters(binder).add(TransactionFilter.class);
+        contributeDomainFilters(binder);
+        contributeDomainQueryFilters(binder);
+        contributeDomainSyncFilters(binder).add(TransactionFilter.class);
 
         // init listener list
         contributeDomainListeners(binder);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/main/java/org/apache/cayenne/tx/TransactionFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/tx/TransactionFilter.java 
b/cayenne-server/src/main/java/org/apache/cayenne/tx/TransactionFilter.java
index 622f132..25b23a1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/tx/TransactionFilter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/tx/TransactionFilter.java
@@ -21,60 +21,46 @@ package org.apache.cayenne.tx;
 
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.DataChannelFilter;
-import org.apache.cayenne.DataChannelFilterChain;
 import org.apache.cayenne.DataChannelSyncCallbackAction;
+import org.apache.cayenne.DataChannelSyncFilter;
+import org.apache.cayenne.DataChannelSyncFilterChain;
 import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.graph.GraphDiff;
-import org.apache.cayenne.query.Query;
 
 /**
- * A {@link DataChannelFilter} that provides transactions.
+ * A {@link DataChannelSyncFilter} that provides transactions.
  *
  * @since 4.0
  */
-public class TransactionFilter implements DataChannelFilter {
+public class TransactionFilter implements DataChannelSyncFilter {
 
     @Inject
     protected TransactionManager transactionManager;
 
     @Override
-    public void init(DataChannel channel) {
-    }
-
-    @Override
-    public QueryResponse onQuery(ObjectContext originatingContext, Query 
query, DataChannelFilterChain filterChain) {
-        return filterChain.onQuery(originatingContext, query);
-    }
-
-    @Override
-    public GraphDiff onSync(final ObjectContext originatingContext, final 
GraphDiff changes, final int syncType, final DataChannelFilterChain 
filterChain) {
+    public GraphDiff onSync(ObjectContext originatingContext, GraphDiff 
changes, int syncType, DataChannelSyncFilterChain filterChain) {
         DataChannelSyncCallbackAction callbackAction = 
DataChannelSyncCallbackAction.getCallbackAction(
                 
originatingContext.getChannel().getEntityResolver().getCallbackRegistry(),
                 originatingContext.getGraphManager(),
-                changes, syncType);
+                changes,
+                syncType
+        );
 
         callbackAction.applyPreCommit();
 
         GraphDiff result;
         switch (syncType) {
             case DataChannel.ROLLBACK_CASCADE_SYNC:
-                result = filterChain.onSync(originatingContext, changes, 
syncType);;
+                result = filterChain.onSync(originatingContext, changes, 
syncType);
                 break;
 
             // including transaction handling logic
             case DataChannel.FLUSH_NOCASCADE_SYNC:
             case DataChannel.FLUSH_CASCADE_SYNC:
-                result = transactionManager.performInTransaction(new 
TransactionalOperation<GraphDiff>() {
-                    @Override
-                    public GraphDiff perform() {
-                        return filterChain.onSync(originatingContext, changes, 
syncType);
-                    }
-                });
-
+                result = transactionManager.performInTransaction(() -> 
filterChain.onSync(originatingContext, changes, syncType));
                 break;
+
             default:
                 throw new CayenneRuntimeException("Invalid synchronization 
type: %d", syncType);
         }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/test/java/org/apache/cayenne/MockDataChannelFilter.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/MockDataChannelFilter.java 
b/cayenne-server/src/test/java/org/apache/cayenne/MockDataChannelFilter.java
deleted file mode 100644
index 85145be..0000000
--- a/cayenne-server/src/test/java/org/apache/cayenne/MockDataChannelFilter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*****************************************************************
- *   Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- ****************************************************************/
-package org.apache.cayenne;
-
-import org.apache.cayenne.graph.GraphDiff;
-import org.apache.cayenne.query.Query;
-
-public class MockDataChannelFilter implements DataChannelFilter {
-
-    public void init(DataChannel channel) {
-    }
-
-    public QueryResponse onQuery(
-            ObjectContext originatingContext,
-            Query query,
-            DataChannelFilterChain filterChain) {
-        return null;
-    }
-
-    public GraphDiff onSync(
-            ObjectContext originatingContext,
-            GraphDiff changes,
-            int syncType,
-            DataChannelFilterChain filterChain) {
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
index 8e84fd0..c63e13e 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/access/DataDomainFiltersIT.java
@@ -18,15 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.access;
 
-import org.apache.cayenne.DataChannelFilter;
-import org.apache.cayenne.DataChannelFilterChain;
-import org.apache.cayenne.MockDataChannelFilter;
+import org.apache.cayenne.DataChannelQueryFilter;
+import org.apache.cayenne.DataChannelSyncFilter;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.QueryResponse;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.di.Inject;
 import org.apache.cayenne.graph.GraphDiff;
-import org.apache.cayenne.query.Query;
 import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.testdo.testmap.Artist;
 import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -53,53 +51,36 @@ public class DataDomainFiltersIT extends ServerCase {
 
     @Test
     public void testDefaultFilters() {
-
         // There is a default TransactionFilter
         DataDomain domain = runtime.getDataDomain();
-        assertEquals(1, domain.filters.size());
+        assertEquals(0, domain.queryFilters.size());
+        assertEquals(1, domain.syncFilters.size());
     }
 
     @Test
     public void testOnQuery_FilterOrdering() {
 
         DataDomain domain = runtime.getDataDomain();
+        List<String> results = new ArrayList<>();
 
-        final List<String> results = new ArrayList<String>();
-
-        DataChannelFilter f1 = new MockDataChannelFilter() {
-
-            @Override
-            public QueryResponse onQuery(
-                    ObjectContext originatingContext,
-                    Query query,
-                    DataChannelFilterChain filterChain) {
-
-                results.add("f1start");
-                QueryResponse response = 
filterChain.onQuery(originatingContext, query);
-                results.add("f1end");
-                return response;
-            }
+        DataChannelQueryFilter f1 = (originatingContext, query, filterChain) 
-> {
+            results.add("f1start");
+            QueryResponse response = filterChain.onQuery(originatingContext, 
query);
+            results.add("f1end");
+            return response;
         };
 
-        DataChannelFilter f2 = new MockDataChannelFilter() {
-
-            @Override
-            public QueryResponse onQuery(
-                    ObjectContext originatingContext,
-                    Query query,
-                    DataChannelFilterChain filterChain) {
-
-                results.add("f2start");
-                QueryResponse response = 
filterChain.onQuery(originatingContext, query);
-                results.add("f2end");
-                return response;
-            }
+        DataChannelQueryFilter f2 = (originatingContext, query, filterChain) 
-> {
+            results.add("f2start");
+            QueryResponse response = filterChain.onQuery(originatingContext, 
query);
+            results.add("f2end");
+            return response;
         };
 
-        domain.filters.add(f1);
-        domain.filters.add(f2);
+        domain.queryFilters.add(f1);
+        domain.queryFilters.add(f2);
 
-        SelectQuery query = new SelectQuery(Artist.class);
+        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
         QueryResponse response = domain.onQuery(context, query);
         assertNotNull(response);
         assertEquals(4, results.size());
@@ -113,55 +94,31 @@ public class DataDomainFiltersIT extends ServerCase {
     public void testOnSync_FilterOrdering() {
 
         DataDomain domain = runtime.getDataDomain();
+        List<String> results = new ArrayList<>();
 
-        final List<String> results = new ArrayList<String>();
-
-        DataChannelFilter f1 = new MockDataChannelFilter() {
-
-            @Override
-            public GraphDiff onSync(
-                    ObjectContext originatingContext,
-                    GraphDiff changes,
-                    int syncType,
-                    DataChannelFilterChain filterChain) {
-
-                results.add("f1start");
-                GraphDiff response = filterChain.onSync(
-                        originatingContext,
-                        changes,
-                        syncType);
-                results.add("f1end");
-                return response;
-            }
+        DataChannelSyncFilter f1 = (originatingContext, changes, syncType, 
filterChain) -> {
+            results.add("f1start");
+            GraphDiff response = filterChain.onSync(originatingContext, 
changes, syncType);
+            results.add("f1end");
+            return response;
         };
 
-        DataChannelFilter f2 = new MockDataChannelFilter() {
-
-            @Override
-            public GraphDiff onSync(
-                    ObjectContext originatingContext,
-                    GraphDiff changes,
-                    int syncType,
-                    DataChannelFilterChain filterChain) {
-
-                results.add("f2start");
-                GraphDiff response = filterChain.onSync(
-                        originatingContext,
-                        changes,
-                        syncType);
-                results.add("f2end");
-                return response;
-            }
+        DataChannelSyncFilter f2 = (originatingContext, changes, syncType, 
filterChain) -> {
+            results.add("f2start");
+            GraphDiff response = filterChain.onSync(originatingContext, 
changes, syncType);
+            results.add("f2end");
+            return response;
         };
 
-        domain.filters.add(f1);
-        domain.filters.add(f2);
+        domain.syncFilters.add(f1);
+        domain.syncFilters.add(f2);
 
         Artist a = context.newObject(Artist.class);
         a.setArtistName("AAA");
 
         // testing domain.onSync indirectly
         context.commitChanges();
+
         assertEquals(4, results.size());
         assertEquals("f2start", results.get(0));
         assertEquals("f1start", results.get(1));
@@ -174,38 +131,18 @@ public class DataDomainFiltersIT extends ServerCase {
 
         DataDomain domain = runtime.getDataDomain();
 
-        final QueryResponse r1 = new ListResponse();
-        final QueryResponse r2 = new ListResponse();
+        QueryResponse r1 = new ListResponse();
+        QueryResponse r2 = new ListResponse();
 
-        DataChannelFilter f1 = new MockDataChannelFilter() {
+        DataChannelQueryFilter f1 = (originatingContext, query, filterChain) 
-> r1;
+        DataChannelQueryFilter f2 = (originatingContext, query, filterChain) 
-> r2;
 
-            @Override
-            public QueryResponse onQuery(
-                    ObjectContext originatingContext,
-                    Query query,
-                    DataChannelFilterChain filterChain) {
+        domain.queryFilters.add(f1);
+        domain.queryFilters.add(f2);
 
-                return r1;
-            }
-        };
-
-        DataChannelFilter f2 = new MockDataChannelFilter() {
-
-            @Override
-            public QueryResponse onQuery(
-                    ObjectContext originatingContext,
-                    Query query,
-                    DataChannelFilterChain filterChain) {
-
-                return r2;
-            }
-        };
-
-        domain.filters.add(f1);
-        domain.filters.add(f2);
-
-        SelectQuery query = new SelectQuery(Artist.class);
+        SelectQuery<Artist> query = new SelectQuery<>(Artist.class);
         QueryResponse response = domain.onQuery(context, query);
+
         assertSame(r2, response);
     }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
index aa63213..90446c9 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/configuration/server/DataDomainProviderTest.java
@@ -177,6 +177,8 @@ public class DataDomainProviderTest {
                     
.add(SybaseSniffer.class).add(DerbySniffer.class).add(SQLServerSniffer.class)
                     
.add(OracleSniffer.class).add(PostgresSniffer.class).add(MySQLSniffer.class);
             ServerModule.contributeDomainFilters(binder);
+            ServerModule.contributeDomainQueryFilters(binder);
+            ServerModule.contributeDomainSyncFilters(binder);
             ServerModule.contributeDomainListeners(binder).add(mockListener);
             
ServerModule.contributeProjectLocations(binder).add(testConfigName);
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7475b4e0/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
----------------------------------------------------------------------
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
index 14cf472..7969f55 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseModule.java
@@ -170,6 +170,10 @@ public class ServerCaseModule implements Module {
                 // Should remove problems with random-failing tests (those 
that are GC-sensitive).
                 .put(Constants.SERVER_OBJECT_RETAIN_STRATEGY_PROPERTY, "soft");
 
+        ServerModule.contributeDomainFilters(binder);
+        ServerModule.contributeDomainSyncFilters(binder);
+        ServerModule.contributeDomainQueryFilters(binder);
+
         
binder.bind(PkGeneratorFactoryProvider.class).to(PkGeneratorFactoryProvider.class);
         binder.bind(PkGenerator.class).to(JdbcPkGenerator.class);
         ServerModule.contributePkGenerators(binder)

Reply via email to