You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/09/24 07:58:05 UTC
[1/2] git commit: ISIS-536: disable concurrency checking in
IsisJdoSupport#deleteAll
Updated Branches:
refs/heads/master 3fd5244e0 -> 9e550a98f
ISIS-536: disable concurrency checking in IsisJdoSupport#deleteAll
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/beb614a9
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/beb614a9
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/beb614a9
Branch: refs/heads/master
Commit: beb614a986669741452132a210a895478abf062f
Parents: 3fd5244
Author: Dan Haywood <da...@apache.org>
Authored: Tue Sep 24 06:55:28 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Tue Sep 24 06:55:28 2013 +0100
----------------------------------------------------------------------
.../applib/service/support/IsisJdoSupport.java | 15 ++++++++
.../persistence/FrameworkSynchronizer.java | 3 +-
.../service/support/IsisJdoSupportImpl.java | 18 ++++++++-
.../metamodel/adapter/mgr/AdapterManager.java | 40 +++++++++++++++++++-
.../adapter/version/ConcurrencyException.java | 21 ----------
.../persistence/adapter/PojoAdapter.java | 3 +-
.../adaptermanager/AdapterManagerDefault.java | 2 +-
7 files changed, 75 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
index 4014476..23faeb2 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/support/IsisJdoSupport.java
@@ -62,6 +62,21 @@ public interface IsisJdoSupport {
@Programmatic
Integer executeUpdate(String sql);
+ /**
+ * Force the deletion of all instances of the specified class.
+ *
+ * <p>
+ * Note: this is intended primarily for testing purposes, eg clearing existing data as part of
+ * installing fixtures. It will generate a <tt>SQL DELETE</tt> for each instance. To perform
+ * a bulk deletion with a single <tt>SQL DELETE</tt>, use {@link #executeUpdate(String)}.
+ *
+ * <p>
+ * Implementation note: It can occasionally be the case that Isis' internal adapter for the domain object is
+ * still in memory. JDO/DataNucleus seems to bump up the version of the object prior to its deletion,
+ * which under normal circumstances would cause Isis to throw a concurrency exception. Therefore
+ * To prevent this from happening (ie to <i>force</i> the deletion of all instances), concurrency checking
+ * is temporarily disabled while this method is performed.
+ */
@Programmatic
void deleteAll(Class<?>... pcClasses);
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
index edbeec0..b9f9132 100644
--- a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
+++ b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
@@ -33,6 +33,7 @@ import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ResolveState;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
@@ -91,7 +92,7 @@ public class FrameworkSynchronizer {
otherVersion != null &&
thisVersion.different(otherVersion)) {
- if(ConcurrencyException.concurrencyChecking.get().isChecking()) {
+ if(ConcurrencyChecking.isCurrentlyEnabled()) {
LOG.info("concurrency conflict detected on " + thisOid + " (" + otherVersion + ")");
final String currentUser = getAuthenticationSession().getUserName();
final ConcurrencyException abortCause = new ConcurrencyException(currentUser, thisOid, thisVersion, otherVersion);
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/service/support/IsisJdoSupportImpl.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/service/support/IsisJdoSupportImpl.java b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/service/support/IsisJdoSupportImpl.java
index 2c08b3b..279361f 100644
--- a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/service/support/IsisJdoSupportImpl.java
+++ b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/service/support/IsisJdoSupportImpl.java
@@ -26,6 +26,7 @@ import java.sql.Statement;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Callable;
import javax.jdo.Extent;
import javax.jdo.PersistenceManager;
@@ -34,10 +35,13 @@ import javax.jdo.datastore.JDOConnection;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.apache.isis.applib.ApplicationException;
import org.apache.isis.applib.annotation.Hidden;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -156,7 +160,19 @@ public class IsisJdoSupportImpl implements IsisJdoSupport {
for (Class<?> pcClass : pcClasses) {
final Extent<?> extent = getJdoPersistenceManager().getExtent(pcClass);
final List<Object> instances = Lists.newArrayList(extent.iterator());
- getJdoPersistenceManager().deletePersistentAll(instances);
+
+ // temporarily disable concurrency checking while this method is performed
+ try {
+ ConcurrencyChecking.executeWithConcurrencyCheckingDisabled(new Callable<Void>(){
+ @Override
+ public Void call() {
+ getJdoPersistenceManager().deletePersistentAll(instances);
+ return null;
+ }
+ });
+ } catch (Exception e) {
+ throw new ApplicationException(e);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
index 0ff8a82..2634a65 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
@@ -19,6 +19,8 @@
package org.apache.isis.core.metamodel.adapter.mgr;
+import java.util.concurrent.Callable;
+
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.core.commons.components.Injectable;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -73,14 +75,48 @@ public interface AdapterManager extends Injectable {
NO_CHECK,
CHECK;
+ public boolean isChecking() {
+ return this == CHECK;
+ }
+
public static ConcurrencyChecking concurrencyCheckingFor(ActionSemantics.Of actionSemantics) {
return actionSemantics == ActionSemantics.Of.SAFE
? ConcurrencyChecking.NO_CHECK
: ConcurrencyChecking.CHECK;
}
- public boolean isChecking() {
- return this == CHECK;
+ /**
+ * Provides a mechanism to temporarily disable concurrency checking.
+ *
+ * <p>
+ * A {@link ThreadLocal} is used because typically there is JDO/DataNucleus code between the Isis code
+ * that wishes to disable the concurrency checking and the code (an Isis callback) that needs to
+ * check if checking has been disabled.
+ */
+ private static ThreadLocal<ConcurrencyChecking> concurrencyChecking = new ThreadLocal<ConcurrencyChecking>(){
+ protected ConcurrencyChecking initialValue() {
+ return CHECK;
+ };
+ };
+
+ /**
+ * Whether concurrency checking is currently disabled.
+ */
+ public static boolean isCurrentlyEnabled() {
+ return concurrencyChecking.get().isChecking();
+ }
+
+ /**
+ * Allows a caller to temporarily disable concurrency checking for the current thread.
+ */
+ public static <T> T executeWithConcurrencyCheckingDisabled(final Callable<T> callable) throws Exception {
+ final ConcurrencyChecking prior = ConcurrencyChecking.concurrencyChecking.get();
+ try {
+ ConcurrencyChecking.concurrencyChecking.set(ConcurrencyChecking.NO_CHECK);
+ return callable.call();
+ } finally {
+ ConcurrencyChecking.concurrencyChecking.set(prior);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/version/ConcurrencyException.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/version/ConcurrencyException.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/version/ConcurrencyException.java
index af3fdfc..2197550 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/version/ConcurrencyException.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/version/ConcurrencyException.java
@@ -20,7 +20,6 @@
package org.apache.isis.core.metamodel.adapter.version;
import org.apache.isis.core.commons.exceptions.IsisException;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
@@ -28,26 +27,6 @@ public class ConcurrencyException extends IsisException {
private static final long serialVersionUID = 1L;
- /**
- * Provides a mechanism to temporarily disable concurrency checking.
- *
- * <p>
- * This thread-local is not used by this class, but is defined here as a central point for other methods
- * to read/write. The idea is that if concurrency checking is to be temporarily disabled, then the caller can
- * set this threadlocal to {@link ConcurrencyChecking#NO_CHECK no-check}, and then the code that would normally
- * detect the concurrency problem and throw this exception would instead consult this thread local and suppress
- * the exception being raised.
-
- * <p>
- * In this design, it is the responsibility of the caller that is disabling concurrency exception handling to reinstate it
- * afterwards. This should normally be done using a try...finally.
- */
- public static ThreadLocal<ConcurrencyChecking> concurrencyChecking = new ThreadLocal<ConcurrencyChecking>(){
- protected ConcurrencyChecking initialValue() {
- return ConcurrencyChecking.CHECK;
- };
- };
-
private static String buildMessage(String currentUser, Oid oid, Version staleVersion, Version datastoreVersion) {
final StringBuilder buf = new StringBuilder();
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
index 5128cb8..07cf7bb 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
@@ -34,6 +34,7 @@ import org.apache.isis.core.commons.util.ToString;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ResolveState;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
import org.apache.isis.core.metamodel.adapter.oid.AggregatedOid;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.oid.ParentedOid;
@@ -340,7 +341,7 @@ public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
otherVersion != null &&
thisVersion.different(otherVersion)) {
- if(ConcurrencyException.concurrencyChecking.get().isChecking()) {
+ if(ConcurrencyChecking.isCurrentlyEnabled()) {
LOG.info("concurrency conflict detected on " + thisOid + " (" + otherVersion + ")");
final String currentUser = getAuthenticationSession().getUserName();
throw new ConcurrencyException(currentUser, thisOid, thisVersion, otherVersion);
http://git-wip-us.apache.org/repos/asf/isis/blob/beb614a9/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adaptermanager/AdapterManagerDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adaptermanager/AdapterManagerDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adaptermanager/AdapterManagerDefault.java
index 0e561b1..fc76dd7 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adaptermanager/AdapterManagerDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adaptermanager/AdapterManagerDefault.java
@@ -325,7 +325,7 @@ public class AdapterManagerDefault implements AdapterManagerSpi {
otherVersion != null &&
thisVersion.different(otherVersion)) {
- if(ConcurrencyException.concurrencyChecking.get().isChecking()) {
+ if(ConcurrencyChecking.isCurrentlyEnabled()) {
LOG.info("concurrency conflict detected on " + recreatedOid + " (" + otherVersion + ")");
final String currentUser = getAuthenticationSession().getUserName();
throw new ConcurrencyException(currentUser, recreatedOid, thisVersion, otherVersion);
[2/2] git commit: ISIS-540: Exception Recognizer for
JDODataStoreException now does *not* recognise...
Posted by da...@apache.org.
ISIS-540: Exception Recognizer for JDODataStoreException now does *not* recognise...
.. certain phrases that would likely constitute an error in the system that should be surfaced to the dev team, ie not swallowed in a friendly error message
* "NOT NULL check constraint" -- eg a mandatory property has most likely not been set.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/9e550a98
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/9e550a98
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/9e550a98
Branch: refs/heads/master
Commit: 9e550a98f8698259167732466681fb7a8521e5b6
Parents: beb614a
Author: Dan Haywood <da...@apache.org>
Authored: Tue Sep 24 06:57:50 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Tue Sep 24 06:57:50 2013 +0100
----------------------------------------------------------------------
...ptionRecognizerForJDODataStoreException.java | 2 +-
.../exceprecog/ExceptionRecognizerForType.java | 41 +++++++++++++++++++-
2 files changed, 40 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/9e550a98/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/exceprecog/ExceptionRecognizerForJDODataStoreException.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/exceprecog/ExceptionRecognizerForJDODataStoreException.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/exceprecog/ExceptionRecognizerForJDODataStoreException.java
index 94d9381..a79e090 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/exceprecog/ExceptionRecognizerForJDODataStoreException.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/exceprecog/ExceptionRecognizerForJDODataStoreException.java
@@ -23,7 +23,7 @@ import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerForType;
public class ExceptionRecognizerForJDODataStoreException extends ExceptionRecognizerForType {
public ExceptionRecognizerForJDODataStoreException() {
- super(javax.jdo.JDODataStoreException.class,
+ super(ofTypeExcluding(javax.jdo.JDODataStoreException.class, "NOT NULL check constraint"),
prefix("Unable to save changes. " +
"Does similar data already exist, or has referenced data been deleted?"));
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9e550a98/core/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java b/core/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
index 7a3e74b..76760a3 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/exceprecog/ExceptionRecognizerForType.java
@@ -18,8 +18,11 @@
*/
package org.apache.isis.applib.services.exceprecog;
+import java.util.List;
+
import com.google.common.base.Function;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.base.Throwables;
import org.apache.isis.applib.annotation.Hidden;
@@ -37,7 +40,11 @@ import org.apache.isis.applib.annotation.Hidden;
@Hidden
public class ExceptionRecognizerForType extends ExceptionRecognizerDelegating {
- private final static Predicate<Throwable> ofType(final Class<? extends Throwable> exceptionType) {
+ protected final static Predicate<Throwable> ofTypeExcluding(final Class<? extends Throwable> exceptionType, final String... messages) {
+ return Predicates.and(ofType(exceptionType), excluding(messages));
+ }
+
+ protected final static Predicate<Throwable> ofType(final Class<? extends Throwable> exceptionType) {
return new Predicate<Throwable>() {
@Override
public boolean apply(Throwable input) {
@@ -45,9 +52,39 @@ public class ExceptionRecognizerForType extends ExceptionRecognizerDelegating {
}
};
}
+
+ /**
+ * A {@link Predicate} that {@link Predicate#apply(Object) applies} only if the message(s)
+ * supplied do <i>NOT</i> appear in the {@link Throwable} or any of its {@link Throwable#getCause() cause}s
+ * (recursively).
+ *
+ * <p>
+ * Intended to prevent too eager matching of an overly general exception type.
+ */
+ protected final static Predicate<Throwable> excluding(final String... messages) {
+ return new Predicate<Throwable>() {
+ @Override
+ public boolean apply(Throwable input) {
+ final List<Throwable> causalChain = Throwables.getCausalChain(input);
+ for (String message : messages) {
+ for (Throwable throwable : causalChain) {
+ final String throwableMessage = throwable.getMessage();
+ if(throwableMessage != null && throwableMessage.contains(message)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ };
+ }
public ExceptionRecognizerForType(final Class<? extends Exception> exceptionType, final Function<String,String> messageParser) {
- super(new ExceptionRecognizerGeneral(ofType(exceptionType), messageParser));
+ this(ofType(exceptionType), messageParser);
+ }
+
+ public ExceptionRecognizerForType(final Predicate<Throwable> predicate, final Function<String,String> messageParser) {
+ super(new ExceptionRecognizerGeneral(predicate, messageParser));
}
public ExceptionRecognizerForType(Class<? extends Exception> exceptionType) {