You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by dw...@apache.org on 2010/03/27 04:12:07 UTC

svn commit: r928128 - in /openjpa/trunk: openjpa-kernel/src/main/java/org/apache/openjpa/conf/ openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-kernel/src/main/java/org/apache/openjpa/util/ openjpa-persistence-jdbc/src/test/java/org/apac...

Author: dwoods
Date: Sat Mar 27 03:12:07 2010
New Revision: 928128

URL: http://svn.apache.org/viewvc?rev=928128&view=rev
Log:
OPENJPA-1597 Add openjpa.Compatibility option IgnoreDetachedStateFieldForProxySerialization which 2.0 apps can set to true to fall back to 1.0 behavior and defaults 1.0 apps to old behavior of not removing  classes after EM.clear() is called.

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence1.xml   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence2.xml   (with props)
Modified:
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java
    openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxies.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestContainerSpecCompatibilityOptions.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestDetachNoProxy.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/TestDetachMerge.java
    openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/proxy/persistence2.xml
    openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/conf/Compatibility.java Sat Mar 27 03:12:07 2010
@@ -66,6 +66,7 @@ public class Compatibility {
     private boolean _isNonDefaultMappingAllowed = false;
     private boolean _reorderMetaDataResolution = true;
     private boolean _reloadOnDetach = false;
+    private boolean _ignoreDetachedStateFieldForProxySerialization = false;
     
     /**
      * Whether to require exact identity value types when creating object
@@ -296,6 +297,39 @@ public class Compatibility {
     }
 
     /**
+     * Whether OpenJPA should ignore the DetachedStateField value when
+     * determining if our Proxy classes should be removed during serialization.
+     * <P>Starting with version 2.0.0, when the DetachedStateFiled==true, the
+     * build time $proxy classes will not be removed.
+     * <P>Prior to version 2.0.0, the DetachedStateFiled was not used and
+     * the $proxy classes were not being removed during serialization after
+     * the Persistence context was cleared.
+     * 
+     * @param ignoreDSF if true the old Proxy serialization behavior will be used.
+     * 
+     * @since 2.0.0
+     */
+    public void setIgnoreDetachedStateFieldForProxySerialization(boolean ignoreDSF) {
+        _ignoreDetachedStateFieldForProxySerialization = ignoreDSF;
+    }
+    
+    /**
+     * Whether OpenJPA should ignore the DetachedStateField value when
+     * determining if our Proxy classes should be removed during serialization.
+     * <P>Starting with version 2.0.0, when the DetachedStateFiled==true, the
+     * build time $proxy classes will not be removed.
+     * <P>Prior to version 2.0.0, the DetachedStateFiled was not used and
+     * the $proxy classes were not being removed during serialization after
+     * the Persistence context was cleared.
+     * 
+     * @since 2.0.0
+     * @return true if the old Proxy serialization will be used, otherwise false.
+     */
+    public boolean getIgnoreDetachedStateFieldForProxySerialization() {
+        return _ignoreDetachedStateFieldForProxySerialization;
+    }
+
+    /**
      * Whether OpenJPA should flush changes before detaching or serializing an
      * entity. In JPA this is usually false, but other persistence frameworks
      * (ie JDO) may expect it to be true.

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java Sat Mar 27 03:12:07 2010
@@ -25,6 +25,7 @@ import java.util.BitSet;
 import java.util.Collection;
 import java.util.Map;
 
+import org.apache.openjpa.conf.Compatibility;
 import org.apache.openjpa.enhance.PersistenceCapable;
 import org.apache.openjpa.enhance.StateManager;
 import org.apache.openjpa.lib.util.Localizer;
@@ -62,6 +63,7 @@ public class DetachedStateManager
     private final Object _oid;
     private final Object _version;
     private final ReentrantLock _lock;
+    private final boolean _useDSFForUnproxy;   // old releases will default to FALSE, which is the old behavior
 
     /**
      * Constructor.
@@ -89,6 +91,14 @@ public class DetachedStateManager
             _lock = new ReentrantLock();
         else
             _lock = null;
+        if (sm.getContext() != null && sm.getContext().getConfiguration() != null) {
+            Compatibility compat = sm.getContext().getConfiguration().getCompatibilityInstance();
+            if (compat != null && !compat.getIgnoreDetachedStateFieldForProxySerialization())
+                _useDSFForUnproxy = true;      // new 2.0 behavior
+            else
+                _useDSFForUnproxy = false;
+        } else
+            _useDSFForUnproxy = false;
     }
 
     /////////////////////////////////
@@ -731,6 +741,15 @@ public class DetachedStateManager
         return _dirty;
     }
 
+    /**
+     * Should DetachedStateField be used by Proxies to determine when to remove
+     * $proxy wrappers during serialization.
+     * @since 2.0.0
+     */
+    public boolean getUseDSFForUnproxy() {
+        return _useDSFForUnproxy;
+    }
+
     public BitSet getFlushed() {
         throw new UnsupportedOperationException();
     }

Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxies.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxies.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxies.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/Proxies.java Sat Mar 27 03:12:07 2010
@@ -20,6 +20,8 @@ package org.apache.openjpa.util;
 
 import java.security.AccessController;
 
+import org.apache.openjpa.conf.Compatibility;
+import org.apache.openjpa.kernel.DetachedStateManager;
 import org.apache.openjpa.kernel.OpenJPAStateManager;
 import org.apache.openjpa.lib.util.J2DoPrivHelper;
 import org.apache.openjpa.lib.util.Localizer;
@@ -111,19 +113,47 @@ public class Proxies {
         } else if (proxy.getOwner() == null) {
             // no StateManager (DetachedStateField==false), so no $proxy to remove
             return proxy;
-        } else if (proxy.getOwner().isDetached()) {
-            // already detached, so remove any $proxy
-            return proxy.copy(proxy);
         } else {
             // using a StateManager, so determine what DetachedState is being used
-            OpenJPAStateManager sm = proxy.getOwner();  // !null checked for above
-            ClassMetaData meta = sm.getMetaData();      // if null, no proxies?
-            if ((meta != null) && (!Boolean.TRUE.equals(meta.usesDetachedState()))) {
-                // configured to use transient (null) or no (FALSE) StateManger, so remove any $proxy
-                return proxy.copy(proxy);
+            OpenJPAStateManager sm = proxy.getOwner();  // null checked for above
+            ClassMetaData meta = null;          // if null, no proxies?
+            boolean useDSFForUnproxy = false;   // default to false for old 1.0 behavior
+
+            // DetachedStateMnager has no context or metadata, so we can't get configuration settings
+            if (!proxy.getOwner().isDetached()) {
+                Compatibility compat = null;
+                meta = sm.getMetaData();
+                if (meta != null) {
+                    compat = meta.getRepository().getConfiguration().getCompatibilityInstance();
+                } else if (sm.getContext() != null && sm.getContext().getConfiguration() != null) {
+                    compat = sm.getContext().getConfiguration().getCompatibilityInstance();
+                } else {
+                    // no-op - using a StateManager, but no Compatibilty settings available
+                }
+                if (compat != null) {
+                    // new 2.0 behavior of using DetachedStateField to determine unproxy during serialization
+                    useDSFForUnproxy = !compat.getIgnoreDetachedStateFieldForProxySerialization();
+                }
+            } else {
+                // Using a DetachedStateManager, so use the new flag since there is no context or metadata
+                useDSFForUnproxy = ((DetachedStateManager)sm).getUseDSFForUnproxy();
+            }
+            
+            if (useDSFForUnproxy) {
+                // use new 2.0 behavior
+                if ((meta != null) && (Boolean.TRUE.equals(meta.usesDetachedState()))) {
+                    // configured to always use and serialize a StateManger, so keep any $proxy
+                    return proxy;
+                } else {
+                    // already detached or using DetachedStateField==false or transient, so remove any $proxy
+                    return proxy.copy(proxy);
+                }
             } else {
-                // DetachedStateField==true, which means to keep the SM and $proxy in the serialized objects
-                return proxy;
+                // use old 1.0 behavior
+                if (proxy.getOwner().isDetached())
+                    return proxy;
+                else
+                    return proxy.copy(proxy);
             }
         }
     }

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestContainerSpecCompatibilityOptions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestContainerSpecCompatibilityOptions.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestContainerSpecCompatibilityOptions.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestContainerSpecCompatibilityOptions.java Sat Mar 27 03:12:07 2010
@@ -71,6 +71,7 @@ public class TestContainerSpecCompatibil
         Compatibility compat = emf1.getConfiguration().getCompatibilityInstance();
         assertTrue(compat.getFlushBeforeDetach());
         assertTrue(compat.getCopyOnDetach());
+        assertTrue(compat.getIgnoreDetachedStateFieldForProxySerialization());
         assertTrue(compat.getPrivatePersistentProperties());
         assertFalse(compat.isAbstractMappingUniDirectional());
         assertFalse(compat.isNonDefaultMappingAllowed());
@@ -92,6 +93,7 @@ public class TestContainerSpecCompatibil
         Compatibility compat = emf.getConfiguration().getCompatibilityInstance();
         assertFalse(compat.getFlushBeforeDetach());
         assertFalse(compat.getCopyOnDetach());
+        assertFalse(compat.getIgnoreDetachedStateFieldForProxySerialization());
         assertFalse(compat.getPrivatePersistentProperties());
         assertTrue(compat.isAbstractMappingUniDirectional());
         assertTrue(compat.isNonDefaultMappingAllowed());

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/compat/TestSpecCompatibilityOptions.java Sat Mar 27 03:12:07 2010
@@ -57,6 +57,7 @@ extends AbstractCachedEMFTestCase {
         Compatibility compat = emf.getConfiguration().getCompatibilityInstance();
         assertTrue(compat.getFlushBeforeDetach());
         assertTrue(compat.getCopyOnDetach());
+        assertTrue(compat.getIgnoreDetachedStateFieldForProxySerialization());
         assertTrue(compat.getPrivatePersistentProperties());
         String vMode = emf.getConfiguration().getValidationMode();
         assertEquals("NONE", vMode);
@@ -65,7 +66,6 @@ extends AbstractCachedEMFTestCase {
         assertEquals(spec.getVersion(), 1);
         
         emf.close();
-
     }
 
     /*
@@ -82,6 +82,7 @@ extends AbstractCachedEMFTestCase {
         Compatibility compat = emf.getConfiguration().getCompatibilityInstance();
         assertFalse(compat.getFlushBeforeDetach());
         assertFalse(compat.getCopyOnDetach());
+        assertFalse(compat.getIgnoreDetachedStateFieldForProxySerialization());
         assertFalse(compat.getPrivatePersistentProperties());
         String vMode = emf.getConfiguration().getValidationMode();
         assertEquals("AUTO", vMode);

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestDetachNoProxy.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestDetachNoProxy.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestDetachNoProxy.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detach/TestDetachNoProxy.java Sat Mar 27 03:12:07 2010
@@ -28,34 +28,19 @@ import java.util.ArrayList;
 import org.apache.openjpa.conf.Compatibility;
 import org.apache.openjpa.lib.log.Log;
 import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
+import org.apache.openjpa.persistence.OpenJPAPersistence;
 import org.apache.openjpa.persistence.test.SingleEMFTestCase;
 
 public class TestDetachNoProxy extends SingleEMFTestCase {
     
     private static final int numEntities = 3;
     private static final String PROXY = new String("$proxy");
-    private Log log;
+    private Log _log;
     
     public void setUp() {
         setUp(DROP_TABLES, Entity20.class);
-        log = emf.getConfiguration().getLog("test");
-        
-        // check and set Compatibility values to new 2.0 values
-        Compatibility compat = emf.getConfiguration().getCompatibilityInstance();
-        assertNotNull(compat);
-        if (log.isTraceEnabled()) {
-            log.trace("Before set, FlushBeforeDetach=" + compat.getFlushBeforeDetach());
-            log.trace("Before set, CopyOnDetach=" + compat.getCopyOnDetach());
-            log.trace("Before set, CascadeWithDetach=" + compat.getCascadeWithDetach());
-        }
-        compat.setFlushBeforeDetach(false);
-        compat.setCopyOnDetach(false);
-        compat.setCascadeWithDetach(false);
-        if (log.isTraceEnabled()) {
-            log.trace("After set, FlushBeforeDetach=" + compat.getFlushBeforeDetach());
-            log.trace("After set, CopyOnDetach=" + compat.getCopyOnDetach());
-            log.trace("After set, CascadeWithDetach=" + compat.getCascadeWithDetach());
-        }
+        _log = emf.getConfiguration().getLog("test");
         createEntities(numEntities);
     }
     
@@ -74,16 +59,33 @@ public class TestDetachNoProxy extends S
     /* 
      * Verify that an in-place detached entity does not use the proxy classes.
      */
-    public void testDetach() {
-        if (log.isTraceEnabled())
-            log.trace("***** testDetach() *****");
+    public void testDetach20() {
         Integer id = new Integer(0);
-        OpenJPAEntityManager em = emf.createEntityManager();
+        OpenJPAEntityManagerFactorySPI emf2 = 
+            (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
+            "NoProxy2New", "org/apache/openjpa/persistence/detach/persistence2.xml");
+        assertNotNull(emf2);
+
+        Log log = emf2.getConfiguration().getLog("test");
+        if (log.isTraceEnabled())
+            log.trace("***** testDetach20() *****");
         
+        if (log.isTraceEnabled()) {
+            Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
+            assertNotNull(compat);
+            log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
+            log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
+            log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
+        }
+
+        OpenJPAEntityManager em = emf2.createEntityManager();
         em.clear();
+        
         Entity20 e20 = em.find(Entity20.class, id);
         if (log.isTraceEnabled())
-            log.trace("** after find");
+            log.trace("** testDetach20() - after find");
         assertTrue(em.contains(e20));
         assertFalse(em.isDetached(e20));
         verifySerializable(e20, true, false);
@@ -91,28 +93,46 @@ public class TestDetachNoProxy extends S
         // new openjpa-2.0.0 behavior, where detach() doesn't return updated entity, but does it in-place
         em.detach(e20);
         if (log.isTraceEnabled())
-            log.trace("** after detach");
+            log.trace("** testDetach20() - after detach");
         // in-place updated entity should not have any proxy classes and should be detached
         assertFalse(em.contains(e20));
         assertTrue(em.isDetached(e20));
         verifySerializable(e20, false, false);
                
         em.close();
+        emf2.close();
     }
 
     /* 
      * Verify that a detachCopy() returned entity does not contain any proxy classes.
      */
-    public void testDetachCopy() {
-        if (log.isTraceEnabled())
-            log.trace("***** testDetachCopy() *****");
+    public void testDetachCopy20() {
         Integer id = new Integer(0);
-        OpenJPAEntityManager em = emf.createEntityManager();
+        OpenJPAEntityManagerFactorySPI emf2 = 
+            (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
+            "NoProxy2New", "org/apache/openjpa/persistence/detach/persistence2.xml");
+        assertNotNull(emf2);
+
+        Log log = emf2.getConfiguration().getLog("test");
+        if (log.isTraceEnabled())
+            log.trace("***** testDetachCopy20() *****");
+        
+        if (log.isTraceEnabled()) {
+            Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
+            assertNotNull(compat);
+            log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
+            log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
+            log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
+        }
+
+        OpenJPAEntityManager em = emf2.createEntityManager();
         em.clear();
 
         Entity20 e20 = em.find(Entity20.class, id);
         if (log.isTraceEnabled())
-            log.trace("** after find");
+            log.trace("** testDetachCopy20() - after find");
         assertTrue(em.contains(e20));
         assertFalse(em.isDetached(e20));
         verifySerializable(e20, true, false);
@@ -120,7 +140,7 @@ public class TestDetachNoProxy extends S
         // Test new detachCopy() method added in 2.0.0
         Entity20 e20copy = em.detachCopy(e20);
         if (log.isTraceEnabled())
-            log.trace("** after detachCopy");
+            log.trace("** TestDetachCopy20() - after detachCopy");
         // verify e20 is same as above
         assertTrue(em.contains(e20));
         assertFalse(em.isDetached(e20));
@@ -131,15 +151,33 @@ public class TestDetachNoProxy extends S
         verifySerializable(e20copy, false, false);
         
         em.close();
+        emf2.close();
     }
 
     /*
      * Verify that in-place detachAll entities do not use the proxy classes.
      */
-    public void testDetachAll() {
+    public void testDetachAll20() {
+        OpenJPAEntityManagerFactorySPI emf2 = 
+            (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
+            "NoProxy2New", "org/apache/openjpa/persistence/detach/persistence2.xml");
+        assertNotNull(emf2);
+
+        Log log = emf2.getConfiguration().getLog("test");
         if (log.isTraceEnabled())
-            log.trace("***** testDetachAll() *****");
-        OpenJPAEntityManager em = emf.createEntityManager();
+            log.trace("***** testDetachAll20() *****");
+        
+        if (log.isTraceEnabled()) {
+            Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
+            assertNotNull(compat);
+            log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
+            log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
+            log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
+        }
+
+        OpenJPAEntityManager em = emf2.createEntityManager();
         em.clear();
 
         ArrayList<Entity20> e20List = new ArrayList<Entity20>(numEntities);
@@ -147,7 +185,7 @@ public class TestDetachNoProxy extends S
             Entity20 e20 = em.find(Entity20.class, new Integer(i));
             e20List.add(e20);
             if (log.isTraceEnabled())
-                log.trace("** after find Entity20(" + i + ")");
+                log.trace("** testDetachAll20() - after find Entity20(" + i + ")");
             assertTrue(em.contains(e20));
             assertFalse(em.isDetached(e20));
             verifySerializable(e20, true, false);            
@@ -159,7 +197,7 @@ public class TestDetachNoProxy extends S
         em.detachAll(e20List.get(0), e20List.get(1), e20List.get(2));
         for (int i=0; i<numEntities; i++) {
             if (log.isTraceEnabled())
-                log.trace("** after EM.detachAll() verify e20List(" + i + ")");
+                log.trace("** testDetachAll20() - after EM.detachAll() verify e20List(" + i + ")");
             Entity20 e20 = e20List.get(i);
             // entity should not have any proxy classes (in-place updated) and is detached
             assertFalse(em.contains(e20));
@@ -168,15 +206,33 @@ public class TestDetachNoProxy extends S
         }
 
         em.close();
+        emf2.close();
     }
 
     /*
-     * Verify that after EM.clear() entities still contain proxy classes.
+     * Verify that after EM.clear() entities still contain proxy classes for 1.0 apps.
      */
-    public void testClear() {
+    public void testClear10Compat() {
+        OpenJPAEntityManagerFactorySPI emf1 = 
+            (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
+            "NoProxy1Compat", "org/apache/openjpa/persistence/detach/persistence1.xml");
+        assertNotNull(emf1);
+
+        Log log = emf1.getConfiguration().getLog("test");
         if (log.isTraceEnabled())
-            log.trace("***** testClear() *****");
-        OpenJPAEntityManager em = emf.createEntityManager();
+            log.trace("***** testClear10Compat() *****");
+        
+        if (log.isTraceEnabled()) {
+            Compatibility compat = emf1.getConfiguration().getCompatibilityInstance();
+            assertNotNull(compat);
+            log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
+            log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
+            log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
+        }
+
+        OpenJPAEntityManager em = emf1.createEntityManager();
         em.clear();
 
         ArrayList<Entity20> e20List = new ArrayList<Entity20>(numEntities);
@@ -184,7 +240,7 @@ public class TestDetachNoProxy extends S
             Entity20 e20 = em.find(Entity20.class, new Integer(i));
             e20List.add(e20);
             if (log.isTraceEnabled())
-                log.trace("** after find Entity20(" + i + ")");
+                log.trace("** testClear10Compat() - after find Entity20(" + i + ")");
             assertTrue(em.contains(e20));
             assertFalse(em.isDetached(e20));
             verifySerializable(e20, true, false);            
@@ -194,19 +250,124 @@ public class TestDetachNoProxy extends S
 
         for (int i=0; i<numEntities; i++) {
             if (log.isTraceEnabled())
-                log.trace("** after EM.clear() verify Entity20(" + i + ")");
+                log.trace("** testClear10Compat() - after EM.clear() verify Entity20(" + i + ")");
             Entity20 e20 = e20List.get(i);
             assertFalse(em.contains(e20));
             assertTrue(em.isDetached(e20));
-            // entity should still have proxy classes and is detached,
-            // Old 1.2.x Behavior -
+            // Old 1.0/1.2 Behavior -
             //   the $proxy classes are not removed during serialization
-            // verifySerializable(e20, true, true);
+            verifySerializable(e20, true, true);
+        }
+
+        em.close();
+        emf1.close();
+    }
+
+    /*
+     * Verify that after EM.clear() entities still contain proxy classes for 1.0 apps.
+     */
+    public void testClear20Compat() {
+        OpenJPAEntityManagerFactorySPI emf2 = 
+            (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
+            "NoProxy2Compat", "org/apache/openjpa/persistence/detach/persistence2.xml");
+        assertNotNull(emf2);
+
+        Log log = emf2.getConfiguration().getLog("test");
+        if (log.isTraceEnabled())
+            log.trace("***** testClear20Compat() *****");
+        
+        if (log.isTraceEnabled()) {
+            Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
+            assertNotNull(compat);
+            log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
+            log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
+            log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
+        }
+
+        OpenJPAEntityManager em = emf2.createEntityManager();
+        em.clear();
+
+        ArrayList<Entity20> e20List = new ArrayList<Entity20>(numEntities);
+        for (int i=0; i<numEntities; i++) {
+            Entity20 e20 = em.find(Entity20.class, new Integer(i));
+            e20List.add(e20);
+            if (log.isTraceEnabled())
+                log.trace("** testClear20Compat() - after find Entity20(" + i + ")");
+            assertTrue(em.contains(e20));
+            assertFalse(em.isDetached(e20));
+            verifySerializable(e20, true, false);            
+        }
+
+        em.clear();
+
+        for (int i=0; i<numEntities; i++) {
+            if (log.isTraceEnabled())
+                log.trace("** testClear20Compat() - after EM.clear() verify Entity20(" + i + ")");
+            Entity20 e20 = e20List.get(i);
+            assertFalse(em.contains(e20));
+            assertTrue(em.isDetached(e20));
+            // Old 1.0/1.2 Behavior -
+            //   the $proxy classes are not removed during serialization
+            verifySerializable(e20, true, true);
+        }
+
+        em.close();
+        emf2.close();
+    }
+
+    /*
+     * Verify that after EM.clear() entities do not contain proxy classes for 2.0 apps.
+     */
+    public void testClear20New() {
+        OpenJPAEntityManagerFactorySPI emf2 = 
+            (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
+            "NoProxy2New", "org/apache/openjpa/persistence/detach/persistence2.xml");
+        assertNotNull(emf2);
+
+        Log log = emf2.getConfiguration().getLog("test");
+        if (log.isTraceEnabled())
+            log.trace("***** testClear20New() *****");
+        
+        if (log.isTraceEnabled()) {
+            Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
+            assertNotNull(compat);
+            log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
+            log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
+            log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
+        }
+
+        OpenJPAEntityManager em = emf2.createEntityManager();
+        em.clear();
+
+        ArrayList<Entity20> e20List = new ArrayList<Entity20>(numEntities);
+        for (int i=0; i<numEntities; i++) {
+            Entity20 e20 = em.find(Entity20.class, new Integer(i));
+            e20List.add(e20);
+            if (log.isTraceEnabled())
+                log.trace("** testClear20New() - after find Entity20(" + i + ")");
+            assertTrue(em.contains(e20));
+            assertFalse(em.isDetached(e20));
+            verifySerializable(e20, true, false);            
+        }
+
+        em.clear();
+
+        for (int i=0; i<numEntities; i++) {
+            if (log.isTraceEnabled())
+                log.trace("** testClear20New() - after EM.clear() verify Entity20(" + i + ")");
+            Entity20 e20 = e20List.get(i);
+            assertFalse(em.contains(e20));
+            assertTrue(em.isDetached(e20));
             // OPENJPA-1097 New behavior - $proxy classes are removed
             verifySerializable(e20, true, false);
         }
 
         em.close();
+        emf2.close();
     }
 
     /**
@@ -225,8 +386,8 @@ public class TestDetachNoProxy extends S
         ObjectOutputStream oos = null;
         byte[] e20bytes = null;
         
-        if (log.isTraceEnabled())
-            log.trace("verifySerializable() - before serialize");
+        if (_log.isTraceEnabled())
+            _log.trace("verifySerializable() - before serialize");
         verifyEntities(e20, usesProxyBefore);
 
         // first serialize
@@ -251,8 +412,8 @@ public class TestDetachNoProxy extends S
         try {
             ois = new ObjectInputStream(bais);
             e20new = (Entity20) ois.readObject();
-            if (log.isTraceEnabled())
-                log.trace("verifySerializable() - after deserialize");
+            if (_log.isTraceEnabled())
+                _log.trace("verifySerializable() - after deserialize");
             verifyEntities(e20new, usesProxyAfter);
         } catch (IOException e) {
             fail(e.toString());
@@ -269,8 +430,8 @@ public class TestDetachNoProxy extends S
     }
 
     private void verifyEntities(Entity20 e20, boolean usesProxy) {
-        if (log.isTraceEnabled()) {
-            log.trace("verifyEntities() - asserting expected proxy usage is " + usesProxy);
+        if (_log.isTraceEnabled()) {
+            _log.trace("verifyEntities() - asserting expected proxy usage is " + usesProxy);
             printClassNames(e20);
         }
         assertTrue("Expected sqlDate endsWith($proxy) to return " + usesProxy,
@@ -283,10 +444,10 @@ public class TestDetachNoProxy extends S
     }
     
     private void printClassNames(Entity20 e20) {
-        if (log.isTraceEnabled()) {
-            log.trace("sqlDate = " + e20.getDate().getClass().getCanonicalName());
-            log.trace("sqlTime = " + e20.getTime().getClass().getCanonicalName());
-            log.trace("sqlTimestamp = " + e20.getTimestamp().getClass().getCanonicalName());
+        if (_log.isTraceEnabled()) {
+            _log.trace("sqlDate = " + e20.getDate().getClass().getCanonicalName());
+            _log.trace("sqlTime = " + e20.getTime().getClass().getCanonicalName());
+            _log.trace("sqlTimestamp = " + e20.getTimestamp().getClass().getCanonicalName());
         }
     }
 }

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/TestDetachMerge.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/TestDetachMerge.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/TestDetachMerge.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/proxy/TestDetachMerge.java Sat Mar 27 03:12:07 2010
@@ -21,7 +21,9 @@ package org.apache.openjpa.persistence.p
 import java.math.BigDecimal;
 import java.util.Calendar;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import javax.persistence.EntityManager;
@@ -75,7 +77,7 @@ public class TestDetachMerge extends Sin
     /* 
      * Test default 1.0 compatibility behavior, which should pass AS-IS
      */
-    @AllowFailure(message="Will fail until OPENJPA-1597 is fixed")
+    @AllowFailure(message="Will fail until root cause of OPENJPA-1597 is found")
     public void testAnnuity1Compat() throws Exception {
         OpenJPAEntityManagerFactorySPI emf1 = 
             (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
@@ -91,6 +93,8 @@ public class TestDetachMerge extends Sin
             log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
             log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
             log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
         }
 
         try {
@@ -105,7 +109,7 @@ public class TestDetachMerge extends Sin
     /* 
      * Test 2.0 behavior with Compatibility flag and DetachedStateField=true, which should PASS
      */
-    @AllowFailure(message="Will fail until OPENJPA-1597 is fixed")
+    @AllowFailure(message="Will fail until root cause of OPENJPA-1597 is found")
     public void testAnnuity2Compat() throws Exception {
         OpenJPAEntityManagerFactorySPI emf2 = 
             (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
@@ -121,6 +125,8 @@ public class TestDetachMerge extends Sin
             log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
             log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
             log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
         }
 
         try {
@@ -150,6 +156,8 @@ public class TestDetachMerge extends Sin
             log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
             log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
             log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
         }
 
         try {
@@ -184,6 +192,8 @@ public class TestDetachMerge extends Sin
             log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
             log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
             log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
+            log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
+                compat.getIgnoreDetachedStateFieldForProxySerialization());
         }
 
         try {
@@ -613,7 +623,8 @@ public class TestDetachMerge extends Sin
         if (payors == null)
             throw new RuntimeException("Annuity: IPayor list not the same (payors was null)!");
         if (payors.size() != payors2.size())
-            throw new RuntimeException("Annuity: IPayor list not the same (payors size not the same)!");
+            throw new RuntimeException("Annuity: IPayor list not the same (payors size not the same)! payors=" +
+                payors.toArray().toString() + ", payors2=" + payors2.toString());
         for (int i = 0; i < payors.size(); i++) {
             IPayor payor = payors.get(i);
             boolean found = false;

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence1.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence1.xml?rev=928128&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence1.xml (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence1.xml Sat Mar 27 03:12:07 2010
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    version="1.0"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+    http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
+
+    <persistence-unit name="NoProxy1Compat">
+        <class>org.apache.openjpa.persistence.detach.Entity20</class>
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+        <properties>			
+            <property name="openjpa.jdbc.SynchronizeMappings"
+                value="buildSchema(ForeignKeys=true)"/>
+        </properties>
+    </persistence-unit>
+</persistence>

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence2.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence2.xml?rev=928128&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence2.xml (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence2.xml Sat Mar 27 03:12:07 2010
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    version="2.0"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+
+    <!-- 
+         This is the new PU for 2.0, which takes the default 2.0 
+         behavior of removing $proxy for default DetachedStateField=transient
+    -->
+    <persistence-unit name="NoProxy2New">
+        <class>org.apache.openjpa.persistence.detach.Entity20</class>
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+        <properties>			
+            <property name="openjpa.jdbc.SynchronizeMappings"
+                value="buildSchema(ForeignKeys=true)" />
+        </properties>
+    </persistence-unit>
+
+    <!-- 
+         This is the original PU from 1.0, but running as a 2.0 app
+         with the new Compatibility flag set to use the old 1.0 behavior,
+         which is to not remove $proxy after calling EM.clear()
+    -->
+    <persistence-unit name="NoProxy2Compat">
+        <class>org.apache.openjpa.persistence.detach.Entity20</class>
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+        <properties>			
+            <property name="openjpa.jdbc.SynchronizeMappings"
+                value="buildSchema(ForeignKeys=true)" />
+            <property name="openjpa.Compatibility"
+                value="IgnoreDetachedStateFieldForProxySerialization=true" />
+        </properties>
+    </persistence-unit>
+
+</persistence>

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/detach/persistence2.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/proxy/persistence2.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/proxy/persistence2.xml?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/proxy/persistence2.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/resources/org/apache/openjpa/persistence/proxy/persistence2.xml Sat Mar 27 03:12:07 2010
@@ -40,10 +40,10 @@
         <class>org.apache.openjpa.persistence.proxy.entities.Rider</class>
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
         <properties>			
-            <property name="openjpa.DetachState" value="fgs(DetachedStateField=true)" />
-            <!-- <property name="openjpa.jdbc.Schema" value="EJB30"/> -->
+            <property name="openjpa.DetachState"
+                value="fgs(DetachedStateField=true)" />
             <property name="openjpa.jdbc.SynchronizeMappings"
-                value="buildSchema(ForeignKeys=true)"/>
+                value="buildSchema(ForeignKeys=true)" />
         </properties>
     </persistence-unit>
 
@@ -66,10 +66,10 @@
         <class>org.apache.openjpa.persistence.proxy.entities.Rider</class>
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
         <properties>			
-            <!-- <property name="openjpa.DetachState" value="fgs(DetachedStateField=true)" /> -->
-            <!-- <property name="openjpa.jdbc.Schema" value="EJB30"/> -->
+            <!-- <property name="openjpa.DetachState"
+                value="fgs(DetachedStateField=true)" /> -->
             <property name="openjpa.jdbc.SynchronizeMappings"
-                value="buildSchema(ForeignKeys=true)"/>
+                value="buildSchema(ForeignKeys=true)" />
         </properties>
     </persistence-unit>
 
@@ -92,11 +92,12 @@
         <class>org.apache.openjpa.persistence.proxy.entities.Rider</class>
         <exclude-unlisted-classes>true</exclude-unlisted-classes>
         <properties>			
-            <!-- <property name="openjpa.Compatibility.xxxxx" value="true)" /> -->
-            <property name="openjpa.DetachState" value="fgs(DetachedStateField=true)" />
-            <!-- <property name="openjpa.jdbc.Schema" value="EJB30"/> -->
+            <property name="openjpa.Compatibility"
+                value="IgnoreDetachedStateFieldForProxySerialization=true" />
+            <property name="openjpa.DetachState"
+                value="fgs(DetachedStateField=true)" />
             <property name="openjpa.jdbc.SynchronizeMappings"
-                value="buildSchema(ForeignKeys=true)"/>
+                value="buildSchema(ForeignKeys=true)" />
         </properties>
     </persistence-unit>
 </persistence>

Modified: openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java?rev=928128&r1=928127&r2=928128&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java (original)
+++ openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java Sat Mar 27 03:12:07 2010
@@ -287,6 +287,7 @@ public class PersistenceProductDerivatio
             compatibility.setFlushBeforeDetach(true);
             compatibility.setCopyOnDetach(true);
             compatibility.setPrivatePersistentProperties(true);
+            compatibility.setIgnoreDetachedStateFieldForProxySerialization(true);
             // Disable bean validation for spec level < 2 configurations
             conf.validationMode.set(String.valueOf(ValidationMode.NONE));
         } else {