You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2007/07/28 21:53:14 UTC
svn commit: r560601 - in /openjpa/trunk:
openjpa-kernel/src/main/java/org/apache/openjpa/kernel/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/
Author: pcl
Date: Sat Jul 28 12:53:13 2007
New Revision: 560601
URL: http://svn.apache.org/viewvc?view=rev&rev=560601
Log:
OPENJPA-293. Fixed problem with transactional state maintenance that was preventing lifecycle tests from passing.
Modified:
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SaveFieldManager.java
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java
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?view=diff&rev=560601&r1=560600&r2=560601
==============================================================================
--- 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 Sat Jul 28 12:53:13 2007
@@ -1584,7 +1584,7 @@
Collection saved = save.rollback(_savepoints.values());
if (_savepointCache != null)
_savepointCache.clear();
- if (_transCache != null) {
+ if (hasTransactionalObjects()) {
// build up a new collection of states
TransactionalCache oldTransCache = _transCache;
TransactionalCache newTransCache = new TransactionalCache
@@ -2156,8 +2156,10 @@
_fc.setWriteLockLevel(LOCK_NONE);
_fc.setLockTimeout(-1);
- Collection transStates = _transCache;
- if (transStates == null)
+ Collection transStates;
+ if (hasTransactionalObjects())
+ transStates = _transCache;
+ else
transStates = Collections.EMPTY_LIST;
// fire after rollback/commit event
@@ -3750,16 +3752,26 @@
* Return a copy of all transactional state managers.
*/
protected Collection getTransactionalStates() {
- if (_transCache == null)
+ if (!hasTransactionalObjects())
return Collections.EMPTY_LIST;
return _transCache.copy();
}
/**
+ * Whether or not there are any transactional objects in the current
+ * persistence context. If there are any instances with untracked state,
+ * this method will cause those instances to be scanned.
+ */
+ private boolean hasTransactionalObjects() {
+ _cache.dirtyCheck();
+ return _transCache != null;
+ }
+
+ /**
* Return a copy of all dirty state managers.
*/
protected Collection getDirtyStates() {
- if (_transCache == null)
+ if (!hasTransactionalObjects())
return Collections.EMPTY_LIST;
return _transCache.copyDirty();
@@ -3823,7 +3835,7 @@
lock();
try {
- if (_transCache == null)
+ if (!hasTransactionalObjects())
_transCache = new TransactionalCache(_orderDirty);
_transCache.addClean(sm);
} finally {
@@ -3839,6 +3851,8 @@
lock();
try {
if (_transCache != null)
+ // intentional direct access; we don't want to recompute
+ // dirtiness while removing instances from the transaction
_transCache.remove(sm);
if (_derefCache != null && !sm.isPersistent())
_derefCache.remove(sm);
@@ -3866,7 +3880,7 @@
lock();
try {
// cache dirty instance
- if (_transCache == null)
+ if (!hasTransactionalObjects())
_transCache = new TransactionalCache(_orderDirty);
_transCache.addDirty(sm);
@@ -4427,6 +4441,12 @@
* Call this method when a new state manager initializes itself.
*/
public void add(StateManagerImpl sm) {
+ if (!sm.isIntercepting()) {
+ if (_untracked == null)
+ _untracked = new HashSet();
+ _untracked.add(sm);
+ }
+
if (!sm.isPersistent() || sm.isEmbedded()) {
if (_embeds == null)
_embeds = new ReferenceHashSet(ReferenceHashSet.WEAK);
@@ -4453,12 +4473,6 @@
(orig.getManagedInstance()))).
setFailedObject(sm.getManagedInstance());
}
-
- if (!sm.isIntercepting()) {
- if (_untracked == null)
- _untracked = new HashSet();
- _untracked.add(sm);
- }
}
/**
@@ -4623,6 +4637,14 @@
public void clearNew() {
if (_news != null)
_news.clear();
+ }
+
+ private void dirtyCheck() {
+ if (_untracked == null)
+ return;
+
+ for (Iterator iter = _untracked.iterator(); iter.hasNext(); )
+ ((StateManagerImpl) iter.next()).dirtyCheck();
}
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SaveFieldManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SaveFieldManager.java?view=diff&rev=560601&r1=560600&r2=560601
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SaveFieldManager.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SaveFieldManager.java Sat Jul 28 12:53:13 2007
@@ -177,12 +177,13 @@
// if the field is not available, assume that it has changed.
if (_saved == null || !_saved.get(field))
return false;
- if (!(_state.pcGetStateManager() instanceof OpenJPAStateManager))
+ if (!(_state.pcGetStateManager() instanceof StateManagerImpl))
return false;
- OpenJPAStateManager sm = (OpenJPAStateManager)
- _state.pcGetStateManager();
- Object old = sm.fetch(field);
+ StateManagerImpl sm = (StateManagerImpl) _state.pcGetStateManager();
+ SingleFieldManager single = new SingleFieldManager(sm, sm.getBroker());
+ sm.provideField(_state, single, field);
+ Object old = single.fetchObjectField(field);
return current == old || current != null && current.equals(old);
}
Modified: openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?view=diff&rev=560601&r1=560600&r2=560601
==============================================================================
--- openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java (original)
+++ openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java Sat Jul 28 12:53:13 2007
@@ -795,8 +795,8 @@
for (int i = 0; i < fmds.length; i++) {
// pk and version fields cannot be mutated; don't mark them
// as such. ##### validate?
- if (!fmds[i].isPrimaryKey()
- && !fmds[i].isVersion()) {
+ if (!fmds[i].isPrimaryKey() && !fmds[i].isVersion()
+ && _loaded.get(i)) {
if (!saved.isFieldEqual(i, fetch(i))) {
dirty(i);
}
@@ -810,9 +810,6 @@
if (isDeleted())
return false;
if (isNew() && !isFlushed())
- return false;
- if (getMetaData().getAccessType() != ClassMetaData.ACCESS_FIELD
- && !(isNew() && isFlushed()))
return false;
return true;
}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java?view=diff&rev=560601&r1=560600&r2=560601
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/enhance/AbstractUnenhancedClassTest.java Sat Jul 28 12:53:13 2007
@@ -33,6 +33,8 @@
import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.util.ImplHelper;
+import org.apache.openjpa.event.AbstractLifecycleListener;
+import org.apache.openjpa.event.LifecycleEvent;
public abstract class AbstractUnenhancedClassTest
extends SingleEMFTestCase {
@@ -60,6 +62,11 @@
protected abstract UnenhancedSubtype newUnenhancedSubclassInstance();
+ private UnenhancedType newInstance(boolean sub) {
+ return sub ? newUnenhancedSubclassInstance()
+ : newUnenhancedInstance();
+ }
+
public void testMetaData() {
ClassMetaData meta = OpenJPAPersistence.getMetaData(emf,
getUnenhancedClass());
@@ -136,15 +143,23 @@
assertNotNull(em.getObjectId(un));
}
- public void testOperations() {
- opsHelper(false);
+ public void testOperationsOnUserDefined() {
+ opsHelper(false, true);
+ }
+
+ public void testSubclassOperationsOnUserDefined() {
+ opsHelper(true, true);
}
- public void testSubclassOperations() {
- opsHelper(true);
+ public void testOperationsOnOpenJPADefined() {
+ opsHelper(false, false);
}
- private void opsHelper(boolean sub) {
+ public void testSubclassOperationsOnOpenJPADefined() {
+ opsHelper(true, false);
+ }
+
+ private void opsHelper(boolean sub, boolean userDefined) {
OpenJPAEntityManager em = null;
try {
UnenhancedType un = newInstance(sub);
@@ -154,22 +169,30 @@
em.persist(un);
un.setStringField("bar");
assertEquals("bar", un.getStringField());
+ assertPersistenceContext(em, un, true, true, sub);
em.flush();
+ assertPersistenceContext(em, un, true, true, sub);
assertTrue(un.getId() != 0);
UnenhancedType un2 = em.find(getUnenhancedClass(), un.getId());
assertSame(un, un2);
em.getTransaction().commit();
+ assertPersistenceContext(em, un, false, false, sub);
un2 = em.find(getUnenhancedClass(), un.getId());
assertSame(un, un2);
- em.close();
- em = emf.createEntityManager();
+ if (!userDefined) {
+ em.close();
+ em = emf.createEntityManager();
+ }
+
un = em.find(getUnenhancedClass(), un.getId());
assertNotNull(un);
- assertTrue(un instanceof PersistenceCapable);
+ if (!userDefined)
+ assertTrue(un instanceof PersistenceCapable);
assertEquals("bar", un.getStringField());
em.getTransaction().begin();
un.setStringField("baz");
+ assertPersistenceContext(em, un, true, true, sub);
assertEquals("baz", un.getStringField());
if (sub)
@@ -178,6 +201,11 @@
assertTrue(em.isDirty(un));
em.getTransaction().commit();
+
+ // make sure that the values are still up-to-date after
+ // the commit happens
+ assertEquals("baz", un.getStringField());
+
em.close();
em = emf.createEntityManager();
@@ -196,6 +224,17 @@
}
}
+ private void assertPersistenceContext(OpenJPAEntityManager em,
+ UnenhancedType un, boolean transactional, boolean dirty, boolean sub) {
+ assertEquals(transactional, em.getTransactionalObjects().contains(un));
+ assertEquals(dirty, em.getDirtyObjects().contains(un));
+ if (dirty) {
+ Class cls = sub ? getUnenhancedSubclass() : getUnenhancedClass();
+ assertTrue(em.getUpdatedClasses().contains(cls)
+ || em.getPersistedClasses().contains(cls));
+ }
+ }
+
public void testRelations() {
OpenJPAEntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -480,9 +519,51 @@
em.getTransaction().commit();
}
- private UnenhancedType newInstance(boolean sub) {
- return sub ? newUnenhancedSubclassInstance()
- : newUnenhancedInstance();
+ public void testListenersOnUserDefinedInstance()
+ throws IOException, ClassNotFoundException, CloneNotSupportedException {
+ listenerHelper(true, false);
+ }
+
+ public void testListenersOnUserDefinedSubclassInstance()
+ throws IOException, ClassNotFoundException, CloneNotSupportedException {
+ listenerHelper(true, true);
+ }
+
+ public void testListenersOnOpenJPADefinedInstance()
+ throws IOException, ClassNotFoundException, CloneNotSupportedException {
+ listenerHelper(false, false);
+ }
+
+ public void testListenersOnOpenJPADefinedSubclassInstance()
+ throws IOException, ClassNotFoundException, CloneNotSupportedException {
+ listenerHelper(false, true);
+ }
+
+ private void listenerHelper(boolean userDefined, boolean sub)
+ throws IOException, ClassNotFoundException, CloneNotSupportedException {
+ ListenerImpl listener = new ListenerImpl();
+ emf.addLifecycleListener(listener, (Class[]) null);
+ OpenJPAEntityManager em = emf.createEntityManager();
+ UnenhancedType un = newInstance(sub);
+ em.getTransaction().begin();
+ em.persist(un);
+ em.getTransaction().commit();
+
+ if (!userDefined) {
+ em.close();
+ em = emf.createEntityManager();
+ }
+
+ listener.invoked = false;
+
+ un = em.find(getUnenhancedClass(), un.getId());
+ em.getTransaction().begin();
+ un.setStringField("updated");
+ em.getTransaction().commit();
+ assertTrue(listener.invoked);
+ em.close();
+
+ assertEquals("updated", listener.stringField);
}
public void testGetMetaDataOfSubtype() {
@@ -498,5 +579,18 @@
emf.getConfiguration(),
Collections.singleton(getUnenhancedSubclass()), null);
assertSame(meta, OpenJPAPersistence.getMetaData(emf, subs.get(0)));
+ }
+
+ private class ListenerImpl
+ extends AbstractLifecycleListener {
+
+ String stringField;
+ boolean invoked;
+
+ @Override
+ public void afterStore(LifecycleEvent event) {
+ invoked = true;
+ stringField = ((UnenhancedType) event.getSource()).getStringField();
+ }
}
}