You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/08/04 00:09:23 UTC

svn commit: r982048 - in /openjpa/trunk/openjpa-kernel/src/main: java/org/apache/openjpa/kernel/ java/org/apache/openjpa/util/ resources/org/apache/openjpa/kernel/

Author: ppoddar
Date: Tue Aug  3 22:09:22 2010
New Revision: 982048

URL: http://svn.apache.org/viewvc?rev=982048&view=rev
Log:
OPENJPA-1567: Allow reference to sibling managed instances

Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachManager.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
    openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachManager.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachManager.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachManager.java Tue Aug  3 22:09:22 2010
@@ -62,8 +62,8 @@ public class AttachManager {
     private final Collection _visitedNodes = new ArrayList();
 
     // reusable strategies
-    private AttachStrategy _version = null;
-    private AttachStrategy _detach = null;
+    private AttachStrategy _version;
+    private AttachStrategy _detach;
 
     /**
      * Constructor. Supply broker attaching to.

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java Tue Aug  3 22:09:22 2010
@@ -238,7 +238,8 @@ public class BrokerImpl
     private boolean _cachePreparedQuery = true;
     private boolean _cacheFinderQuery = true;
     private boolean _suppressBatchOLELogging = false;
-
+    private boolean _allowReferenceToSiblingContext = false;
+    
     // status
     private int _flags = 0;
 
@@ -4042,7 +4043,7 @@ public class BrokerImpl
      * @param status one of our STATUS constants describing why we're
      * setting the state manager
      */
-    void setStateManager(Object id, StateManagerImpl sm, int status) {
+    protected void setStateManager(Object id, StateManagerImpl sm, int status) {
         lock();
         try {
             switch (status) {
@@ -4490,6 +4491,8 @@ public class BrokerImpl
             return false;
 
         PersistenceCapable pc = ImplHelper.toPersistenceCapable(obj, _conf);
+        if (pc.pcGetStateManager() instanceof DetachedStateManager)
+            return true;
         Boolean detached = pc.pcIsDetached();
         if (detached != null)
             return detached.booleanValue();
@@ -5090,4 +5093,12 @@ public class BrokerImpl
         }
         return _store.isCached(oids, loaded);
     };
+    
+    public boolean getAllowReferenceToSiblingContext() {
+        return _allowReferenceToSiblingContext;
+    }
+    
+    public void setAllowReferenceToSiblingContext(boolean allow) {
+        _allowReferenceToSiblingContext = allow;
+    }
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java Tue Aug  3 22:09:22 2010
@@ -1468,4 +1468,13 @@ public class DelegatingBroker
     public boolean isCached(List<Object> oid) {
         return _broker.isCached(oid);
     }
+    
+    public boolean getAllowReferenceToSiblingContext() {
+        return _broker.getAllowReferenceToSiblingContext();
+    }
+    
+    public void setAllowReferenceToSiblingContext(boolean allow) {
+        _broker.setAllowReferenceToSiblingContext(allow);
+    }
+
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedValueStateManager.java Tue Aug  3 22:09:22 2010
@@ -281,6 +281,9 @@ public class DetachedValueStateManager
         if (sm != null) {
             if (sm instanceof DetachedStateManager)
                 return fetchFromDetachedSM((DetachedStateManager) sm, field);
+            if (_ctx.getAllowReferenceToSiblingContext() && sm instanceof StateManagerImpl) {
+                return ((StateManagerImpl) sm).fetch(field);
+            }
             throw new UnsupportedException(_loc.get("detach-val-badsm", _pc));
         }
         provideField(field);

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java Tue Aug  3 22:09:22 2010
@@ -29,12 +29,14 @@ import java.util.Date;
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.lib.util.Localizer;
 import org.apache.openjpa.meta.FieldMetaData;
 import org.apache.openjpa.meta.JavaTypes;
 import org.apache.openjpa.meta.ValueMetaData;
 import org.apache.openjpa.util.ChangeTracker;
 import org.apache.openjpa.util.Exceptions;
+import org.apache.openjpa.util.ImplHelper;
 import org.apache.openjpa.util.InvalidStateException;
 import org.apache.openjpa.util.MapChangeTracker;
 import org.apache.openjpa.util.ObjectId;
@@ -763,10 +765,18 @@ class SingleFieldManager
                 return; // allow but ignore
 
             sm = _broker.getStateManager(obj);
-            if (sm == null || !sm.isPersistent())
-                throw new InvalidStateException(
-                    _loc.get("cant-cascade-persist", vmd))
+            if (sm == null || !sm.isPersistent()) {
+                if (((StoreContext)_broker).getAllowReferenceToSiblingContext() 
+                 && ImplHelper.isManageable(obj) 
+                 && ((PersistenceCapable)obj).pcGetStateManager() != null) {
+                    return; 
+                } else {
+                    throw new InvalidStateException(_loc.get("cant-cascade-persist", 
+                            vmd.toString(), Exceptions.toString(obj),
+                            sm == null ? " unmanaged" : sm.getPCState().getClass().getSimpleName()))
                     .setFailedObject(obj);
+                }
+            }
         } else {
             if (vmd.getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) {
                 if (!_broker.isDetachedNew() && _broker.isDetached(obj))

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java Tue Aug  3 22:09:22 2010
@@ -500,4 +500,26 @@ public interface StoreContext {
      * @since 2.0.0. 
      */
     public boolean isCached(List<Object> oid);
+    
+    /**
+     * Affirms if this context will allow its managed instances to refer instances 
+     * that are managed by other contexts. 
+     * <B>Note</B>: Some specification (such as JPA) does not warranty predictable
+     * behavior when strict group-like property of a persistent context (where managed 
+     * instances can only refer to instances managed by the <em>same</em> context).
+     * Please be aware of consequences when the flag is set to true.
+     * 
+     * @since 2.1
+     */
+    public void setAllowReferenceToSiblingContext(boolean flag);
+    
+    /**
+     * Affirms if this context will allow its managed instances to refer instances 
+     * that are managed by other contexts. 
+     * 
+     * @return false by default.
+     * 
+     * @since 2.1
+     */
+    public boolean getAllowReferenceToSiblingContext();
 }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java Tue Aug  3 22:09:22 2010
@@ -486,9 +486,9 @@ public class ApplicationIds {
                 // If a value already exists on this field, throw exception.
                 // This is considered an application coding error.
                 if (!sm.isDefaultValue(pks[i].getIndex()))
-                    throw new InvalidStateException(_loc2.get(
-                            "existing-value-override-excep", pks[i]
-                                    .getFullName(false)));
+                    throw new InvalidStateException(_loc2.get("existing-value-override-excep", 
+                            pks[i].getFullName(false), Exceptions.toString(sm.getPersistenceCapable()),
+                            sm.getPCState().getClass().getSimpleName()));
                 // Assign the generated value
                 if (store.assignField(sm, pks[i].getIndex(), preFlush))
                     pks[i].setValueGenerated(true);

Modified: openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties?rev=982048&r1=982047&r2=982048&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties (original)
+++ openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties Tue Aug  3 22:09:22 2010
@@ -214,14 +214,18 @@ nontrans-proxied: You cannot make a prop
 	nontransactional.
 no-field: Field "{0}" is not declared in "{1}", or is not managed.
 no-field-index: "{0}" is not the index of any managed field in "{1}".
-cant-cascade-persist: Encountered unmanaged object in persistent field \
-	"{0}" during flush.  However, this field does not \
-	allow cascade persist. Set the cascade attribute for this field to \
-    CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or \
-    "persist" or "all" (JPA orm.xml), or enable cascade-persist globally, \
-    or manually persist the related field value prior to flushing. \
-	You cannot flush unmanaged objects or graphs that have persistent \
-    associations to unmanaged objects.
+cant-cascade-persist: Encountered unmanaged object "{1}" in life cycle state \
+	{2} while cascading persistence via field "{0}" during flush.  However, \
+	this field does not allow cascade persist. You cannot flush unmanaged objects \
+	or graphs that have persistent associations to unmanaged objects.\r\n \
+	Suggested actions: a) Set the cascade attribute for this field to \
+	CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or \
+    "persist" or "all" (JPA orm.xml), \r\n \
+    b) enable cascade-persist globally, \r\n \
+    c) manually persist the related field value prior to flushing. \r\n \
+    d) if the reference belongs to another context, allow reference to it \
+    by setting StoreContext.setAllowReferenceToSiblingContext().
+	
 cant-cascade-attach: Encountered new object in persistent field \
 	"{0}" during attach.  However, this field does not \
 	allow cascade attach. Set the cascade attribute for this field to \
@@ -384,11 +388,10 @@ null-fg: Attempt to add null/empty fetch
 null-field: Attempt to add null/empty field name to fetch configuration.
 container-projection: Query projections cannot include array, collection, or \
     map fields.  Invalid query: "{0}"
-existing-value-override-excep: The generated value processing detected an \
-existing value assigned to this field: {0}.  This existing value was either \
-provided via an initializer or by calling the setter method.  You either need \
-to remove the @GeneratedValue annotation or modify the code to remove the \
-initializer processing.
+existing-value-override-excep: Primary key field {0} of {1} has non-default value. \
+	The instance life cycle is in {2} state and hence an existing non-default value \
+	for the identity field is not permitted. You either need to remove the @GeneratedValue \
+	annotation or modify the code to remove the initializer processing.
 invalid-tran-status: The transaction was not in a valid state ({0}) to \
 accept the "{1}" method invocation.  Processing will continue.
 multi-threaded-access: Multiple concurrent threads attempted to access a \