OPENJPA-1597 Revert code added to DetachManager to unproxy objects when detached in-place. Updated tests to verify old behavior of detached entites still having references, but that they are removed during serialization.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.0.x@928271 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Donald Woods 2010-03-27 20:53:53 +00:00
parent 5655a9b462
commit 071e698899
12 changed files with 431 additions and 198 deletions

View File

@ -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
@ -295,6 +296,39 @@ public class Compatibility {
return _flushBeforeDetach;
}
/**
* 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

View File

@ -708,10 +708,8 @@ public class DetachManager
* Set the owner of the field's proxy to the detached state manager.
*/
private Object reproxy(Object obj, int field) {
if (obj != null && _detSM != null && obj instanceof Proxy) {
if (obj != null && _detSM != null && obj instanceof Proxy)
((Proxy) obj).setOwner(_detSM, field);
return ((Proxy) obj).copy(obj);
}
return obj;
}

View File

@ -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();
}

View File

@ -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;
@ -85,10 +87,18 @@ public class Proxies {
* 1) No Proxy, then return as-is
* 2) Runtime created proxy (!detachable), then unproxy
* 3) No StateManager (DetachedStateField==false), then return as-is
* 4) If detached, then unproxy
* 5) If ClassMetaData exists and DetachedStateField != TRUE
* (default of DetachedStateField==transient), then unproxy
* 6) Else, return as-is
* Get the new IgnoreDetachedStateFieldForProxySerialization
* Compatibility flag from either the metadata/configuration if
* this is a normal StateManager, otherwise use the new flag
* added to the DetachedStateManager
* 4) If new 2.0 behavior
* 4a) If ClassMetaData exists and DetachedStateField == TRUE
* then do not remove the proxy and return as-is
* 4b) Else, using DetachedStateField of transient(default) or
* false, so unproxy
* 5) If 1.0 app or requested old 1.0 behavior
* 5a) If detached, then do not unproxy and return as-is
* 5b) Else, unproxy
*
* Original code -
* 1) Runtime created proxy (!detachable), then unproxy
@ -111,19 +121,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 Compatibility settings available
}
if (compat != null) {
// new 2.0 behavior of using DetachedStateField to determine unproxy during serialization
useDSFForUnproxy = !compat.getIgnoreDetachedStateFieldForProxySerialization();
}
} else {
// DetachedStateField==true, which means to keep the SM and $proxy in the serialized objects
return proxy;
// 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 {
// use old 1.0 behavior
if (proxy.getOwner().isDetached())
return proxy;
else
return proxy.copy(proxy);
}
}
}

View File

@ -71,6 +71,7 @@ public class TestContainerSpecCompatibilityOptions
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 TestContainerSpecCompatibilityOptions
Compatibility compat = emf.getConfiguration().getCompatibilityInstance();
assertFalse(compat.getFlushBeforeDetach());
assertFalse(compat.getCopyOnDetach());
assertFalse(compat.getIgnoreDetachedStateFieldForProxySerialization());
assertFalse(compat.getPrivatePersistentProperties());
assertTrue(compat.isAbstractMappingUniDirectional());
assertTrue(compat.isNonDefaultMappingAllowed());

View File

@ -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);

View File

@ -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 SingleEMFTestCase {
/*
* 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 SingleEMFTestCase {
// 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);
verifySerializable(e20, true, 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 SingleEMFTestCase {
// 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 SingleEMFTestCase {
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 SingleEMFTestCase {
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,24 +197,42 @@ public class TestDetachNoProxy extends SingleEMFTestCase {
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));
assertTrue(em.isDetached(e20));
verifySerializable(e20, false, false);
verifySerializable(e20, true, false);
}
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 SingleEMFTestCase {
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 SingleEMFTestCase {
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 SingleEMFTestCase {
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 SingleEMFTestCase {
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 SingleEMFTestCase {
}
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 SingleEMFTestCase {
}
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());
}
}
}

View File

@ -21,7 +21,9 @@ package org.apache.openjpa.persistence.proxy;
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,6 @@ public class TestDetachMerge extends SingleEMFTestCase {
/*
* Test default 1.0 compatibility behavior, which should pass AS-IS
*/
@AllowFailure(message="Will fail until OPENJPA-1597 is fixed")
public void testAnnuity1Compat() throws Exception {
OpenJPAEntityManagerFactorySPI emf1 =
(OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
@ -91,6 +92,8 @@ public class TestDetachMerge extends SingleEMFTestCase {
log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
compat.getIgnoreDetachedStateFieldForProxySerialization());
}
try {
@ -103,9 +106,8 @@ public class TestDetachMerge extends SingleEMFTestCase {
}
/*
* Test 2.0 behavior with Compatibility flag and DetachedStateField=true, which should PASS
* Test default 2.0 compatibility behavior, which should PASS
*/
@AllowFailure(message="Will fail until OPENJPA-1597 is fixed")
public void testAnnuity2Compat() throws Exception {
OpenJPAEntityManagerFactorySPI emf2 =
(OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
@ -121,6 +123,8 @@ public class TestDetachMerge extends SingleEMFTestCase {
log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
log.trace("IgnoreDetachedStateFieldForProxySerialization=" +
compat.getIgnoreDetachedStateFieldForProxySerialization());
}
try {
@ -132,69 +136,6 @@ public class TestDetachMerge extends SingleEMFTestCase {
}
}
/*
* Test 2.0 behavior with DetachedStateField=true, which should FAIL
*/
public void testAnnuity2Fail() throws Exception {
OpenJPAEntityManagerFactorySPI emf2 =
(OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
"Annuity2Fail", "org/apache/openjpa/persistence/proxy/persistence2.xml");
assertNotNull(emf2);
Log log = emf2.getConfiguration().getLog("test");
if (log.isTraceEnabled()) {
Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
assertNotNull(compat);
log.trace("started testAnnuity2Fail()");
log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
}
try {
execute(emf2);
fail("testAnuity2Fail() should have caused an execption!");
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Annuity:")) {
// no-op caught our expected exception
} else {
fail("testAnuity2Fail() caught an unexpected execption!" + e);
}
} finally {
emf2.close();
}
}
/*
* Test default 2.0 behavior with DetachedStateField=transient, which should PASS
*/
public void testAnnuity2New() throws Exception {
OpenJPAEntityManagerFactorySPI emf2 =
(OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.createEntityManagerFactory(
"Annuity2New", "org/apache/openjpa/persistence/proxy/persistence2.xml");
assertNotNull(emf2);
Log log = emf2.getConfiguration().getLog("test");
if (log.isTraceEnabled()) {
Compatibility compat = emf2.getConfiguration().getCompatibilityInstance();
assertNotNull(compat);
log.trace("started testAnnuity2New()");
log.trace("FlushBeforeDetach=" + compat.getFlushBeforeDetach());
log.trace("CopyOnDetach=" + compat.getCopyOnDetach());
log.trace("CascadeWithDetach=" + compat.getCascadeWithDetach());
}
try {
execute(emf2);
} catch (RuntimeException e) {
fail("testAnuity2New() should not have caused an execption!" + e);
} finally {
emf2.close();
}
}
private void execute(OpenJPAEntityManagerFactorySPI myEMF) throws Exception {
Log log = myEMF.getConfiguration().getLog("test");
//EntityManager em = myEMF.createEntityManager();
@ -613,7 +554,8 @@ public class TestDetachMerge extends SingleEMFTestCase {
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;

View File

@ -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>

View File

@ -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>

View File

@ -26,58 +26,6 @@
<!--
This is the original PU from 1.0, but running as a 2.0 app
-->
<persistence-unit name="Annuity2Fail">
<class>org.apache.openjpa.persistence.proxy.entities.Address</class>
<class>org.apache.openjpa.persistence.proxy.entities.Annuity</class>
<class>org.apache.openjpa.persistence.proxy.entities.AnnuityHolder</class>
<class>org.apache.openjpa.persistence.proxy.entities.AnnuityPersistebleObject</class>
<class>org.apache.openjpa.persistence.proxy.entities.Contact</class>
<class>org.apache.openjpa.persistence.proxy.entities.EquityAnnuity</class>
<class>org.apache.openjpa.persistence.proxy.entities.FixedAnnuity</class>
<class>org.apache.openjpa.persistence.proxy.entities.Payor</class>
<class>org.apache.openjpa.persistence.proxy.entities.Payout</class>
<class>org.apache.openjpa.persistence.proxy.entities.Person</class>
<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.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>
</properties>
</persistence-unit>
<!--
This is the original PU from 1.0, but with the DetachedStateField
override removed, which will cause a transient one to be used
and the tests will pass.
-->
<persistence-unit name="Annuity2New">
<class>org.apache.openjpa.persistence.proxy.entities.Address</class>
<class>org.apache.openjpa.persistence.proxy.entities.Annuity</class>
<class>org.apache.openjpa.persistence.proxy.entities.AnnuityHolder</class>
<class>org.apache.openjpa.persistence.proxy.entities.AnnuityPersistebleObject</class>
<class>org.apache.openjpa.persistence.proxy.entities.Contact</class>
<class>org.apache.openjpa.persistence.proxy.entities.EquityAnnuity</class>
<class>org.apache.openjpa.persistence.proxy.entities.FixedAnnuity</class>
<class>org.apache.openjpa.persistence.proxy.entities.Payor</class>
<class>org.apache.openjpa.persistence.proxy.entities.Payout</class>
<class>org.apache.openjpa.persistence.proxy.entities.Person</class>
<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.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,
so the tests will pass.
-->
<persistence-unit name="Annuity2Compat">
<class>org.apache.openjpa.persistence.proxy.entities.Address</class>
<class>org.apache.openjpa.persistence.proxy.entities.Annuity</class>
@ -92,11 +40,11 @@
<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.DetachState"
value="fgs(DetachedStateField=true)" />
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>
value="buildSchema(ForeignKeys=true)" />
</properties>
</persistence-unit>
</persistence>

View File

@ -287,6 +287,7 @@ public class PersistenceProductDerivation
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 {