You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by jo...@apache.org on 2018/05/04 18:33:25 UTC

[1/3] cayenne git commit: Added getQueryCache to the ObjectContext interface since this is already implemented by BaseContext anyway and makes accessing the cache much easier.

Repository: cayenne
Updated Branches:
  refs/heads/querycache [created] 0a62b2be5


Added getQueryCache to the ObjectContext interface since this is already implemented by BaseContext anyway and makes accessing the cache much easier.

Revised signature for QueryCache.remove(String) to be remove(QueryMetadata) to increase understandability. It was never clear how to use this method before.

Added QueryCache.clearLocalCache method. This is now called automatically at the end of the request-response loop in StatelessContextRequestHandler and by BaseContext.finalize. This will prevent memory leaking from locally cached data in cases where the cache is not configured to expire entries based on time.

Added QueryCache.debugListCacheKeys method to list all keys (prefixed by cache group) in the cache for debugging purposes.


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

Branch: refs/heads/querycache
Commit: be51331499f8dbdb9c897db90602f491a711715f
Parents: 15b7f69
Author: John Huss <jo...@gmail.com>
Authored: Tue May 1 17:02:56 2018 -0500
Committer: John Huss <jo...@apache.org>
Committed: Wed May 2 10:27:37 2018 -0500

----------------------------------------------------------------------
 .../apache/cayenne/jcache/JCacheQueryCache.java | 68 ++++++++++++++++----
 .../java/org/apache/cayenne/BaseContext.java    | 10 +++
 .../java/org/apache/cayenne/ObjectContext.java  |  3 +
 .../cayenne/access/DataContextQueryAction.java  |  6 +-
 .../cayenne/access/DataDomainQueryAction.java   |  2 +-
 .../org/apache/cayenne/cache/MapQueryCache.java | 44 +++++++++++--
 .../apache/cayenne/cache/NestedQueryCache.java  | 21 ++++--
 .../org/apache/cayenne/cache/QueryCache.java    | 21 ++++--
 .../apache/cayenne/cache/MockQueryCache.java    | 16 ++++-
 .../web/StatelessContextRequestHandler.java     |  6 ++
 10 files changed, 164 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java
----------------------------------------------------------------------
diff --git a/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java b/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java
index a6d0e17..c7dcfe3 100644
--- a/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java
+++ b/cayenne-jcache/src/main/java/org/apache/cayenne/jcache/JCacheQueryCache.java
@@ -19,21 +19,26 @@
 
 package org.apache.cayenne.jcache;
 
-import org.apache.cayenne.cache.QueryCache;
-import org.apache.cayenne.cache.QueryCacheEntryFactory;
-import org.apache.cayenne.di.BeforeScopeEnd;
-import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.query.QueryMetadata;
-
-import javax.cache.Cache;
-import javax.cache.CacheException;
-import javax.cache.CacheManager;
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import javax.cache.Cache;
+import javax.cache.Cache.Entry;
+import javax.cache.CacheException;
+import javax.cache.CacheManager;
+
+import org.apache.cayenne.cache.QueryCache;
+import org.apache.cayenne.cache.QueryCacheEntryFactory;
+import org.apache.cayenne.di.BeforeScopeEnd;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.QueryMetadata;
+
 /**
  * @since 4.0
  */
@@ -75,14 +80,16 @@ public class JCacheQueryCache implements QueryCache {
     }
 
     @Override
-    public void remove(String key) {
-        if (key != null) {
-            for (String cache : cacheManager.getCacheNames()) {
-                getCache(cache).remove(key);
+    public void remove(QueryMetadata metadata) {
+        if (metadata != null) {
+            Cache<String, List> cache = getCache(metadata.getCacheGroup());
+            if (cache != null) {
+            	String key = metadata.getCacheKey();
+            	cache.remove(key);
             }
         }
     }
-
+    
     @Override
     public void removeGroup(String groupKey) {
         Cache<String, List> cache = getCache(groupKey);
@@ -156,4 +163,37 @@ public class JCacheQueryCache implements QueryCache {
     public void shutdown() {
         cacheManager.close();
     }
+    
+    @Override
+    public void clearLocalCache(Optional<String> namespace) {
+    	if (!namespace.isPresent()) {
+    		return;
+    	}
+
+    	for (String name : cacheManager.getCacheNames()) {
+    		Cache<String, List> cache = getCache(name);
+    		Iterator<Entry<String, List>> it = cache.iterator();
+    		while (it.hasNext()) {
+    			Entry<String, List> entry = (Entry<String, List>) it.next();
+    			if (entry.getKey().startsWith(namespace.get())) {
+    				it.remove();
+    			}
+    		}
+    	}
+    }
+
+	@Override
+	public List<String> debugListCacheKeys() {
+		List<String> result = new ArrayList<>();
+		for (String name : cacheManager.getCacheNames()) {
+            Cache<String, List> cache = getCache(name);
+            Iterator<Entry<String, List>> it = cache.iterator();
+            while (it.hasNext()) {
+            	Entry<String, List> entry = (Entry<String, List>) it.next();
+				result.add(name + "." + entry.getKey());
+			}
+		}
+		return result;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java b/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
index ac9cc7a..d38cce0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/BaseContext.java
@@ -48,6 +48,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -120,6 +121,14 @@ public abstract class BaseContext implements ObjectContext {
 		graphAction = new ObjectContextGraphAction(this);
 	}
 
+	@Override
+	protected void finalize() throws Throwable {
+		if (queryCache != null) {
+			queryCache.clearLocalCache(Optional.empty());
+		}
+		super.finalize();
+	}
+	
 	/**
 	 * Checks whether this context is attached to Cayenne runtime stack and if
 	 * not, attempts to attach itself to the runtime using Injector returned
@@ -469,6 +478,7 @@ public abstract class BaseContext implements ObjectContext {
 	@Override
 	public abstract Collection<?> uncommittedObjects();
 
+	@Override
 	public QueryCache getQueryCache() {
 		attachToRuntimeIfNeeded();
 		return queryCache;

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
index dc535f8..d4ee643 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/ObjectContext.java
@@ -19,6 +19,7 @@
 
 package org.apache.cayenne;
 
+import org.apache.cayenne.cache.QueryCache;
 import org.apache.cayenne.graph.GraphManager;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.query.Query;
@@ -261,6 +262,8 @@ public interface ObjectContext extends DataChannel, Serializable {
      */
     DataChannel getChannel();
 
+    QueryCache getQueryCache();
+    
     /**
      * Returns <code>true</code> if there are any modified, deleted or new
      * objects registered with this ObjectContext, <code>false</code> otherwise.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
index 87a7b80..1f53c9c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataContextQueryAction.java
@@ -31,6 +31,7 @@ import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.query.EntityResultSegment;
 import org.apache.cayenne.query.ObjectIdQuery;
 import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.QueryMetadata;
 import org.apache.cayenne.query.RefreshQuery;
 import org.apache.cayenne.util.ListResponse;
 import org.apache.cayenne.util.ObjectContextQueryAction;
@@ -176,9 +177,8 @@ class DataContextQueryAction extends ObjectContextQueryAction {
             Query cachedQuery = refreshQuery.getQuery();
             if (cachedQuery != null) {
 
-                String cacheKey = cachedQuery
-                        .getMetaData(context.getEntityResolver())
-                        .getCacheKey();
+                QueryMetadata cacheKey = cachedQuery
+                        .getMetaData(context.getEntityResolver());
                 context.getQueryCache().remove(cacheKey);
 
                 this.response = context.performGenericQuery(cachedQuery);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
index a87de83..be7f180 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
@@ -344,7 +344,7 @@ class DataDomainQueryAction implements QueryRouter, OperationObserver {
             if (refreshQuery.getQuery() != null) {
                 Query cachedQuery = refreshQuery.getQuery();
 
-                String cacheKey = cachedQuery.getMetaData(context.getEntityResolver()).getCacheKey();
+                QueryMetadata cacheKey = cachedQuery.getMetaData(context.getEntityResolver());
                 context.getQueryCache().remove(cacheKey);
 
                 this.response = domain.onQuery(context, cachedQuery);

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java
index e2fb64d..3f85328 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/MapQueryCache.java
@@ -19,8 +19,12 @@
 package org.apache.cayenne.cache;
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.cayenne.CayenneRuntimeException;
@@ -97,15 +101,15 @@ public class MapQueryCache implements QueryCache, Serializable {
         }
     }
 
-    public void remove(String key) {
+    public void remove(QueryMetadata metadata) {
+        String key = metadata.getCacheKey();
         if (key == null) {
             return;
         }
-
-        for(Map<String, List<?>> map : cacheGroups.values()) {
-            synchronized (map) {
-                map.remove(key);
-            }
+        
+        Map<String, List<?>> map = createIfAbsent(metadata);
+        synchronized (map) {
+            map.remove(key);
         }
     }
 
@@ -172,4 +176,32 @@ public class MapQueryCache implements QueryCache, Serializable {
         // no explicit cache group
         return DEFAULT_CACHE_NAME;
     }
+
+	@Override
+	public void clearLocalCache(Optional<String> namespace) {
+		if (!namespace.isPresent()) {
+    		return;
+    	}
+		
+        for (Entry<String, Map<String, List<?>>> cacheGroup : cacheGroups.entrySet()) {
+        	Set<String> keys = cacheGroup.getValue().keySet();
+        	for (String key : keys) {
+        		if (key.startsWith(namespace.get())) {
+        			keys.remove(key);
+        		}
+        	}
+        }
+	}
+
+	@Override
+	public List<String> debugListCacheKeys() {
+		List<String> result = new ArrayList<>();
+        for (Entry<String, Map<String, List<?>>> cacheGroup : cacheGroups.entrySet()) {
+        	for (String key : cacheGroup.getValue().keySet()) {
+				result.add(cacheGroup.getKey() + "." + key);
+        	}
+        }
+		return result;
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java
index 7f50e5d..7dd3236 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/NestedQueryCache.java
@@ -18,11 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.cache;
 
+import java.util.List;
+import java.util.Optional;
+
 import org.apache.cayenne.query.QueryMetadata;
 import org.apache.cayenne.query.QueryMetadataProxy;
 
-import java.util.List;
-
 /**
  * A {@link QueryCache} wrapper that introduces a key namespace on top of a
  * delegate shared cache. This way multiple cache users can share the same
@@ -97,8 +98,8 @@ public class NestedQueryCache implements QueryCache {
      * Removes an entry for key in the current namespace.
      */
     @Override
-    public void remove(String key) {
-        delegate.remove(qualifiedKey(key));
+    public void remove(QueryMetadata metadata) {
+        delegate.remove(qualifiedMetadata(metadata));
     }
 
     /**
@@ -126,4 +127,16 @@ public class NestedQueryCache implements QueryCache {
             }
         };
     }
+
+	@Override
+	public void clearLocalCache(Optional<String> namespace) {
+		// ignore passed in namespace
+		delegate.clearLocalCache(Optional.of(this.namespace));
+	}
+
+	@Override
+	public List<String> debugListCacheKeys() {
+		return delegate.debugListCacheKeys();
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java b/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java
index de74ea6..8aa242a 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/cache/QueryCache.java
@@ -21,6 +21,7 @@ package org.apache.cayenne.cache;
 import org.apache.cayenne.query.QueryMetadata;
 
 import java.util.List;
+import java.util.Optional;
 
 /**
  * Defines API of a cache that stores query results.
@@ -29,6 +30,7 @@ import java.util.List;
  */
 public interface QueryCache {
 
+	
     /**
      * Returns a cached query result for the given QueryMetadata or null if the result is
      * not cached or is expired.
@@ -51,11 +53,13 @@ public interface QueryCache {
 
     @SuppressWarnings("rawtypes")
     void put(QueryMetadata metadata, List results);
-
+	
     /**
-     * Removes a single entry from cache.
+     * Removes a single query result from the cache that matches the given metadata.
+     * The metadata can be obtained like so: 
+     * <pre>query.getMetaData(context.getEntityResolver())</pre>
      */
-    void remove(String key);
+    void remove(QueryMetadata metadata);
 
     /**
      * Removes a group of entries identified by group key. Note that depending on
@@ -65,7 +69,7 @@ public interface QueryCache {
      * will not change after calling this method.
      */
     void removeGroup(String groupKey);
-
+    
     /**
      * Removes a group of entries identified by group key.
      * Can be used if cache provider supports strictly typed caches.
@@ -82,4 +86,13 @@ public interface QueryCache {
      */
     @Deprecated
     void clear();
+    
+    /**
+     * Clears all entries in the LOCAL cache.
+     * @param namespace this parameter is for internal use only - client should always pass Optional.empty()
+     */
+	void clearLocalCache(Optional<String> namespace);
+	
+	List<String> debugListCacheKeys();
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java b/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java
index 0705a60..7ed263c 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/cache/MockQueryCache.java
@@ -18,8 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.cache;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 
+import org.apache.cayenne.query.QueryCacheStrategy;
 import org.apache.cayenne.query.QueryMetadata;
 
 public class MockQueryCache implements QueryCache {
@@ -38,7 +42,7 @@ public class MockQueryCache implements QueryCache {
     public void put(QueryMetadata metadata, List results) {
     }
 
-    public void remove(String key) {
+    public void remove(QueryMetadata metadata) {
     }
 
     public void removeGroup(String groupKey) {
@@ -51,4 +55,14 @@ public class MockQueryCache implements QueryCache {
     public int size() {
         return 0;
     }
+    
+	@Override
+	public void clearLocalCache(Optional<String> namespace) {
+	}
+
+	@Override
+	public List<String> debugListCacheKeys() {
+		return Collections.emptyList();
+	}
+
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/be513314/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
index 0e7651e..66e8768 100644
--- a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
+++ b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.configuration.web;
 
+import java.util.Optional;
+
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
@@ -67,6 +69,10 @@ public class StatelessContextRequestHandler implements RequestHandler {
 
     public void requestEnd(ServletRequest request, ServletResponse response) {
         CayenneRuntime.bindThreadInjector(null);
+        ObjectContext context = BaseContext.getThreadObjectContext();
+        if (context != null) {
+        	((BaseContext)context).getQueryCache().clearLocalCache(Optional.empty());
+        }
         BaseContext.bindThreadObjectContext(null);
     }
 


[2/3] cayenne git commit: Fix ROP compatibility with QueryCache changes

Posted by jo...@apache.org.
Fix ROP compatibility with QueryCache changes


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

Branch: refs/heads/querycache
Commit: 2ac3c9776c6dd830b071ede26cb6154870c40032
Parents: be51331
Author: John Huss <jo...@apache.org>
Authored: Wed May 2 15:25:17 2018 -0500
Committer: John Huss <jo...@apache.org>
Committed: Wed May 2 15:25:17 2018 -0500

----------------------------------------------------------------------
 .../java/org/apache/cayenne/CayenneContextQueryAction.java   | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/2ac3c977/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextQueryAction.java
----------------------------------------------------------------------
diff --git a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextQueryAction.java b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextQueryAction.java
index e0b693c..ced71d5 100644
--- a/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextQueryAction.java
+++ b/cayenne-rop-server/src/main/java/org/apache/cayenne/CayenneContextQueryAction.java
@@ -26,6 +26,7 @@ import java.util.List;
 import org.apache.cayenne.cache.QueryCacheEntryFactory;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.query.Query;
+import org.apache.cayenne.query.QueryMetadata;
 import org.apache.cayenne.query.RefreshQuery;
 import org.apache.cayenne.reflect.AttributeProperty;
 import org.apache.cayenne.reflect.ClassDescriptor;
@@ -108,10 +109,9 @@ class CayenneContextQueryAction extends ObjectContextQueryAction {
             if (refreshQuery.getQuery() != null) {
                 Query cachedQuery = refreshQuery.getQuery();
 
-                String cacheKey = cachedQuery
-                        .getMetaData(context.getEntityResolver())
-                        .getCacheKey();
-                context.getQueryCache().remove(cacheKey);
+                QueryMetadata metadata = cachedQuery
+                        .getMetaData(context.getEntityResolver());
+                context.getQueryCache().remove(metadata);
 
                 this.response = context.performGenericQuery(cachedQuery);
 


[3/3] cayenne git commit: noop

Posted by jo...@apache.org.
noop


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

Branch: refs/heads/querycache
Commit: 0a62b2be5bb0ecd8047b1f2b6c01b947db7bc7ff
Parents: 2ac3c97
Author: John Huss <jo...@apache.org>
Authored: Fri May 4 13:33:16 2018 -0500
Committer: John Huss <jo...@apache.org>
Committed: Fri May 4 13:33:16 2018 -0500

----------------------------------------------------------------------
 RELEASE-NOTES.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/0a62b2be/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 9d1d3aa..48de012 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -9,7 +9,7 @@ https://issues.apache.org/jira/browse/CAY
 
 ----------------------------------
 Release: 4.1.M2
-Date:
+Date: 
 ----------------------------------
 Changes/New Features:
 
@@ -514,4 +514,4 @@ CAY-1804 Serialisation of long[] type was not working correctly.
 CAY-1806 Error importing eomodel
 CAY-1817 NPE during Validate Project
 CAY-1827 EhCache region corresponding to a cache group loses its settings after 'removeGroup'
-CAY-1832 Exception when modifying objects in postLoad callback
\ No newline at end of file
+CAY-1832 Exception when modifying objects in postLoad callback