You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2011/02/19 21:36:24 UTC
svn commit: r1072435 - in
/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src:
main/java/org/apache/cayenne/ main/java/org/apache/cayenne/access/
test/java/org/apache/cayenne/
Author: aadamchik
Date: Sat Feb 19 20:36:24 2011
New Revision: 1072435
URL: http://svn.apache.org/viewvc?rev=1072435&view=rev
Log:
CAY-1536 Expand deserialization context to provide Injector object instead of just a DataChannel
restoring lazy deserialization mechanism for context, only now it is specified in the superclass
Modified:
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/BaseContextTest.java
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java?rev=1072435&r1=1072434&r2=1072435&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/BaseContext.java Sat Feb 19 20:36:24 2011
@@ -25,6 +25,9 @@ import java.util.List;
import java.util.Map;
import org.apache.cayenne.cache.QueryCache;
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Key;
import org.apache.cayenne.event.EventManager;
import org.apache.cayenne.exp.ValueInjector;
import org.apache.cayenne.graph.CompoundDiff;
@@ -112,6 +115,39 @@ public abstract class BaseContext implem
graphAction = new ObjectContextGraphAction(this);
}
+ /**
+ * Checks whether this context is attached to Cayenne runtime stack and if not,
+ * attempts to attach itself to the runtime using Injector returned from the call to
+ * {@link CayenneRuntime#getThreadInjector()}. If thread Injector is not available and
+ * the context is not attached, throws CayenneRuntimeException.
+ * <p>
+ * This method is called internally by the context before access to transient
+ * variables to allow the context to attach to the stack lazily following
+ * deserialization.
+ *
+ * @return true if the context successfully attached to the thread runtime, false - if
+ * it was already attached.
+ * @since 3.1
+ */
+ protected boolean attachIfNeeded() {
+ if (channel != null) {
+ return false;
+ }
+
+ Injector injector = CayenneRuntime.getThreadInjector();
+ if (injector == null) {
+ throw new CayenneRuntimeException("Can't attach to Cayenne runtime. "
+ + "Null injector returned from CayenneRuntime.getThreadInjector()");
+ }
+
+ setChannel(injector.getInstance(DataChannel.class));
+ setQueryCache(injector.getInstance(Key.get(
+ QueryCache.class,
+ QUERY_CACHE_INJECTION_KEY)));
+
+ return true;
+ }
+
public abstract void commitChanges();
public abstract void commitChangesToParent();
@@ -121,6 +157,13 @@ public abstract class BaseContext implem
public DataChannel getChannel() {
return channel;
}
+
+ /**
+ * @since 3.1
+ */
+ public void setChannel(DataChannel channel) {
+ this.channel = channel;
+ }
public abstract EntityResolver getEntityResolver();
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java?rev=1072435&r1=1072434&r2=1072435&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/CayenneContext.java Sat Feb 19 20:36:24 2011
@@ -86,6 +86,7 @@ public class CayenneContext extends Base
/**
* Sets the context channel, setting up a listener for channel events.
*/
+ @Override
public void setChannel(DataChannel channel) {
if (this.channel != channel) {
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java?rev=1072435&r1=1072434&r2=1072435&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataContext.java Sat Feb 19 20:36:24 2011
@@ -43,10 +43,6 @@ import org.apache.cayenne.Persistent;
import org.apache.cayenne.QueryResponse;
import org.apache.cayenne.access.util.IteratedSelectObserver;
import org.apache.cayenne.cache.NestedQueryCache;
-import org.apache.cayenne.cache.QueryCache;
-import org.apache.cayenne.configuration.CayenneRuntime;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.Key;
import org.apache.cayenne.event.EventManager;
import org.apache.cayenne.graph.ChildDiffLoader;
import org.apache.cayenne.graph.CompoundDiff;
@@ -143,6 +139,7 @@ public class DataContext extends BaseCon
/**
* @since 1.2
*/
+ @Override
public void setChannel(DataChannel channel) {
if (this.channel != channel) {
@@ -1134,44 +1131,33 @@ public class DataContext extends BaseCon
// TODO: most of this should be in the superclass, especially the code connecting
// super transient ivars
- // 1. read non-transient properties
+ // read non-transient properties
in.defaultReadObject();
- // 2. Deserialize local snapshots cache
+ // deserialize local snapshots cache
if (!isUsingSharedSnapshotCache()) {
DataRowStore cache = (DataRowStore) in.readObject();
objectStore.setDataRowCache(cache);
}
- // 3. set parent channel
- // call a channel setter to ensure EntityResolver is extracted from channel
- // call it after DataRowCache is deserialized to avoid incorrect DataRowCache lazy
- // creation
- Injector injector = CayenneRuntime.getThreadInjector();
- if (injector != null) {
- setChannel(injector.getInstance(DataChannel.class));
- setQueryCache(injector.getInstance(Key.get(
- QueryCache.class,
- QUERY_CACHE_INJECTION_KEY)));
- }
- else {
- // throw?
- }
-
- // CayenneDataObjects have a transient datacontext
+ // CayenneDataObjects have a transient DataContext
// because at deserialize time the datacontext may need to be different
// than the one at serialize time (for programmer defined reasons).
- // So, when a dataobject is resurrected because it's datacontext was
- // serialized, it will then set the objects datacontext to the correctone
- // If deserialized "otherwise", it will not have a datacontext (good)
+ // So, when a DataObject is resurrected because it's DataContext was
+ // serialized, it will then set the objects DataContext to the correct one
+ // If deserialized "otherwise", it will not have a DataContext.
synchronized (getObjectStore()) {
- Iterator it = objectStore.getObjectIterator();
+ Iterator<?> it = objectStore.getObjectIterator();
while (it.hasNext()) {
Persistent object = (Persistent) it.next();
object.setObjectContext(this);
}
}
+
+ // ... deferring initialization of transient properties of this context till first
+ // access, so that it can attach to Cayenne runtime using appropriate thread
+ // injector.
}
/**
Modified: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/BaseContextTest.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/BaseContextTest.java?rev=1072435&r1=1072434&r2=1072435&view=diff
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/BaseContextTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/test/java/org/apache/cayenne/BaseContextTest.java Sat Feb 19 20:36:24 2011
@@ -18,10 +18,20 @@
****************************************************************/
package org.apache.cayenne;
+import static org.mockito.Mockito.mock;
+
import java.util.Map;
import junit.framework.TestCase;
+import org.apache.cayenne.cache.QueryCache;
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Key;
+import org.apache.cayenne.di.Module;
+
public class BaseContextTest extends TestCase {
public void testUserPropertiesLazyInit() {
@@ -32,4 +42,58 @@ public class BaseContextTest extends Tes
assertNotNull(properties);
assertSame(properties, context.getUserProperties());
}
+
+ public void testAttachIfNeeded() {
+
+ final DataChannel channel = mock(DataChannel.class);
+ final QueryCache cache = mock(QueryCache.class);
+
+ Module testModule = new Module() {
+
+ public void configure(Binder binder) {
+ binder.bind(DataChannel.class).toInstance(channel);
+ Key<QueryCache> cacheKey = Key.get(
+ QueryCache.class,
+ BaseContext.QUERY_CACHE_INJECTION_KEY);
+ binder.bind(cacheKey).toInstance(cache);
+ }
+ };
+
+ Injector injector = DIBootstrap.createInjector(testModule);
+
+ BaseContext context = new MockBaseContext();
+ assertNull(context.channel);
+ assertNull(context.queryCache);
+
+ Injector oldInjector = CayenneRuntime.getThreadInjector();
+ try {
+
+ CayenneRuntime.bindThreadInjector(injector);
+
+ assertTrue(context.attachIfNeeded());
+ assertSame(channel, context.channel);
+ assertSame(cache, context.queryCache);
+
+ assertFalse(context.attachIfNeeded());
+ assertFalse(context.attachIfNeeded());
+ }
+ finally {
+ CayenneRuntime.bindThreadInjector(oldInjector);
+ }
+ }
+
+ public void testAttachIfNeeded_NoStack() {
+
+ BaseContext context = new MockBaseContext();
+ assertNull(context.channel);
+ assertNull(context.queryCache);
+
+ try {
+ context.attachIfNeeded();
+ fail("No thread stack, must have thrown");
+ }
+ catch (CayenneRuntimeException e) {
+ // expected
+ }
+ }
}