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 2014/02/03 12:28:59 UTC
git commit: ISIS-665: auto-escalate application exceptions to fatal
exceptions
Updated Branches:
refs/heads/master a8d01a60d -> 9032a866c
ISIS-665: auto-escalate application exceptions to fatal exceptions
In addition:
- added RecoverableException, NonRecoverableException, FatalException into the hierarchy
- RecoverableException is synonym for ApplicationException (immediate supertype)
- NonRecoverableException is synonym for FatalException (immediate supertype_
- basically any other runtime exception thrown by the app
extended ToDoItem to demonstrate usage.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/9032a866
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/9032a866
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/9032a866
Branch: refs/heads/master
Commit: 9032a866c477bf38a6e19bae3939fecee6d9df68
Parents: a8d01a6
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Feb 3 11:28:40 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Feb 3 11:28:40 2014 +0000
----------------------------------------------------------------------
.../jdo/applib/service/publish/IoUtils.java | 10 ++-
.../service/support/IsisJdoSupportImpl.java | 7 +-
.../viewer/wicket/model/models/ActionModel.java | 8 +-
.../ui/components/actions/ActionPanel.java | 12 ++-
.../cssmenu/ActionLinkFactoryAbstract.java | 10 ++-
.../wicket/ui/errors/JGrowlBehaviour.java | 16 ++--
.../isis/applib/ApplicationException.java | 29 ++++++-
.../org/apache/isis/applib/FatalException.java | 53 ++++++++++++
.../isis/applib/NonRecoverableException.java | 53 ++++++++++++
.../isis/applib/PersistFailedException.java | 29 +++----
.../isis/applib/RecoverableException.java | 62 +++++++++++++
.../apache/isis/applib/RepositoryException.java | 28 +++---
.../org/apache/isis/applib/clock/Clock.java | 5 +-
.../isis/applib/fixtures/BaseFixture.java | 4 +-
.../services/wrapper/InteractionException.java | 4 +-
.../exceptions/IsisApplicationException.java | 2 +-
.../core/commons/lang/ThrowableExtensions.java | 4 +-
.../runtimecontext/RuntimeContext.java | 91 +++++++++++++++++++-
.../noruntime/RuntimeContextNoRuntime.java | 11 +++
.../DeveloperUtilitiesServiceDefault.java | 7 +-
.../invoke/ActionInvocationFacetFactory.java | 16 +++-
.../invoke/ActionInvocationFacetViaMethod.java | 28 ++++--
...ostsPropertyChangedEventFacetAnnotation.java | 5 +-
.../internal/RuntimeContextFromSession.java | 16 +++-
.../background/BackgroundActionExecution.java | 5 +-
.../system/transaction/IsisTransaction.java | 21 +++--
.../isis/core/tck/dom/refs/ParentEntity.java | 2 +-
.../core/tck/dom/refs/ReferencingEntity.java | 2 +-
.../isis/core/tck/dom/refs/SimpleEntity.java | 2 +-
.../dom/src/main/java/dom/todo/ToDoItem.java | 37 ++++----
.../src/main/java/dom/todo/ToDoItem.layout.json | 10 ++-
.../java/dom/todo/ToDoItemContributions.java | 6 +-
.../ToDoItemContributionsTest_priority.java | 2 +-
33 files changed, 480 insertions(+), 117 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtils.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtils.java b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtils.java
index 1d3c976..d7f1ae0 100644
--- a/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtils.java
+++ b/component/objectstore/jdo/jdo-applib/src/main/java/org/apache/isis/objectstore/jdo/applib/service/publish/IoUtils.java
@@ -25,7 +25,9 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.RecoverableException;
+import org.apache.isis.applib.NonRecoverableException;
class IoUtils {
@@ -44,8 +46,8 @@ class IoUtils {
final byte[] utf8Bytes = toZip.getBytes(Charset.forName("UTF-8"));
zos.write(utf8Bytes);
zos.flush();
- } catch (IOException e) {
- throw new ApplicationException(e);
+ } catch (final IOException ex) {
+ throw new FatalException(ex);
} finally {
closeSafely(zos);
}
@@ -72,7 +74,7 @@ class IoUtils {
}
return null;
} catch(IOException ex) {
- throw new ApplicationException(ex);
+ throw new NonRecoverableException(ex);
} finally {
IoUtils.closeSafely(zis);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/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 279361f..2f7e3b8 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
@@ -35,7 +35,8 @@ 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.FatalException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.annotation.Hidden;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -170,8 +171,8 @@ public class IsisJdoSupportImpl implements IsisJdoSupport {
return null;
}
});
- } catch (Exception e) {
- throw new ApplicationException(e);
+ } catch (final Exception ex) {
+ throw new FatalException(ex);
}
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index e0909d3..e7ef110 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -40,7 +40,7 @@ import org.apache.wicket.request.resource.ByteArrayResource;
import org.apache.wicket.request.resource.ContentDisposition;
import org.apache.wicket.util.resource.StringResourceStream;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.BookmarkPolicy;
@@ -507,9 +507,9 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
// //////////////////////////////////////
- public static ApplicationException getApplicationExceptionIfAny(Exception ex) {
- Iterable<ApplicationException> appEx = Iterables.filter(Throwables.getCausalChain(ex), ApplicationException.class);
- Iterator<ApplicationException> iterator = appEx.iterator();
+ public static RecoverableException getApplicationExceptionIfAny(Exception ex) {
+ Iterable<RecoverableException> appEx = Iterables.filter(Throwables.getCausalChain(ex), RecoverableException.class);
+ Iterator<RecoverableException> iterator = appEx.iterator();
return iterator.hasNext() ? iterator.next() : null;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
index a2a6e51..df2b949 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
@@ -28,7 +28,7 @@ import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.Model;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.bookmark.BookmarkService;
import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
@@ -274,11 +274,11 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
}
/**
- * Executes the action, handling any {@link ApplicationException}s that
+ * Executes the action, handling any {@link RecoverableException}s that
* might be encountered.
*
* <p>
- * If an {@link ApplicationException} is encountered, then the application error will be
+ * If an {@link RecoverableException} is encountered, then the application error will be
* {@link MessageBroker#setApplicationError(String) set} so that a suitable message can be
* rendered higher up the call stack.
*
@@ -292,9 +292,13 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
return resultAdapter;
} catch (RuntimeException ex) {
+
+ // TODO: some duplication between this code and ActionLinkFactoryAbstract
// see if is an application-defined exception
- final ApplicationException appEx = ActionModel.getApplicationExceptionIfAny(ex);
+ // if so, is converted to an application error,
+ // equivalent to calling DomainObjectContainer#raiseError(...)
+ final RecoverableException appEx = ActionModel.getApplicationExceptionIfAny(ex);
if (appEx != null) {
getMessageBroker().setApplicationError(appEx.getMessage());
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
index 8cf7c9e..bb3803d 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
@@ -35,7 +35,7 @@ import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.util.resource.IResourceStream;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.core.commons.exceptions.IsisApplicationException;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -187,9 +187,13 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
return actionModel.getObject();
} catch (RuntimeException ex) {
-
+
+ // TODO: some duplication between this code and ActionPanel
+
// see if is an application-defined exception
- final ApplicationException appEx = ActionModel.getApplicationExceptionIfAny(ex);
+ // if so, is converted to an application error,
+ // equivalent to calling DomainObjectContainer#raiseError(...)
+ final RecoverableException appEx = ActionModel.getApplicationExceptionIfAny(ex);
if (appEx != null) {
IsisContext.getMessageBroker().setApplicationError(appEx.getMessage());
return null;
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
index 21ec7c8..54a8b76 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
@@ -26,16 +26,15 @@ import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.core.commons.authentication.MessageBroker;
-import org.apache.isis.core.commons.lang.StringExtensions;
import org.apache.isis.core.runtime.system.context.IsisContext;
/**
* Attach to any Ajax button that might trigger a notification (ie calls
* {@link MessageBroker#addMessage(String)}, {@link MessageBroker#addWarning(String)},
- * {@link MessageBroker#setApplicationError(String)} or throws an {@link ApplicationException}).
+ * {@link MessageBroker#setApplicationError(String)} or throws an {@link RecoverableException}).
*
* <p>
* Attach using the standard Wicket code:
@@ -50,18 +49,23 @@ public class JGrowlBehaviour extends AbstractDefaultAjaxBehavior {
@Override
protected void respond(AjaxRequestTarget target) {
- String feedbackMsg = JGrowlUtil.asJGrowlCalls(IsisContext.getMessageBroker());
+ String feedbackMsg = JGrowlUtil.asJGrowlCalls(getMessageBroker());
if(!Strings.isNullOrEmpty(feedbackMsg)) {
target.appendJavaScript(feedbackMsg);
}
}
-
+
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
- String feedbackMsg = JGrowlUtil.asJGrowlCalls(IsisContext.getMessageBroker());
+ String feedbackMsg = JGrowlUtil.asJGrowlCalls(getMessageBroker());
if(!Strings.isNullOrEmpty(feedbackMsg)) {
response.render(OnDomReadyHeaderItem.forScript(feedbackMsg));
}
}
+
+ protected org.apache.isis.core.runtime.system.transaction.MessageBroker getMessageBroker() {
+ return IsisContext.getMessageBroker();
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java b/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
index 36bcbd3..5717f17 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
@@ -20,10 +20,31 @@
package org.apache.isis.applib;
/**
- * Indicates that a problem has occurred within the application, as opposed to
- * within a supporting framework or system.
+ * Indicates that an exceptional condition/problem has occurred within the application's domain logic.
+ *
+ * <p>
+ * Throwing this exception is equivalent to calling {@link DomainObjectContainer#raiseError(String)}.
+ * The framework will trap the error and display the exception message as a warning.
+ *
+ * <p>
+ * This exception should only be thrown for "recoverable" exceptions, that is, those which
+ * could be anticipated by the application. It should not be thrown for fatal, unanticipated exceptions.
+ *
+ * <p>
+ * The framework attempts to apply some heuristics; if the underlying Isis transaction has been aborted
+ * (for example as the result of a problem persisting some data) but then the application attempts to
+ * throw this exception, the exception will be promoted to a fatal exception.
+ *
+ * <p>
+ * Note that this exception has identical semantics to {@link RecoverableException}, and can be considered a
+ * synonym.
+ *
+ * @see RecoverableException
+ * @see NonRecoverableException
+ * @see FatalException
*/
-public class ApplicationException extends RuntimeException {
+public class ApplicationException extends RecoverableException {
+
private static final long serialVersionUID = 1L;
public ApplicationException(final String msg) {
@@ -31,7 +52,7 @@ public class ApplicationException extends RuntimeException {
}
public ApplicationException(final Throwable cause) {
- this(cause.getMessage(), cause);
+ super(cause);
}
public ApplicationException(final String msg, final Throwable cause) {
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/FatalException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/FatalException.java b/core/applib/src/main/java/org/apache/isis/applib/FatalException.java
new file mode 100644
index 0000000..7284609
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/FatalException.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.isis.applib;
+
+/**
+ * Indicates that an unexpected, non-recoverable (fatal) exception has occurred within
+ * the application logic.
+ *
+ * <p>
+ * Throwing this exception will (dependent on the viewer) result in some sort of an error page being displayed to the user.
+ *
+ * <p>
+ * Note that this exception has identical semantics to {@link NonRecoverableException}, and can be considered a
+ * synonym.
+ *
+ * @see RecoverableException
+ * @see ApplicationException
+ * @see NonRecoverableException
+ */
+public class FatalException extends NonRecoverableException {
+
+ private static final long serialVersionUID = 1L;
+
+ public FatalException(final String msg) {
+ super(msg);
+ }
+
+ public FatalException(final Throwable cause) {
+ this(cause.getMessage(), cause);
+ }
+
+ public FatalException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/NonRecoverableException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/NonRecoverableException.java b/core/applib/src/main/java/org/apache/isis/applib/NonRecoverableException.java
new file mode 100644
index 0000000..9649d39
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/NonRecoverableException.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.isis.applib;
+
+/**
+ * Indicates that an unexpected, non-recoverable (fatal) exception has occurred within
+ * the application logic.
+ *
+ * <p>
+ * Throwing this exception will (dependent on the viewer) result in some sort of an error page being displayed to the user.
+ *
+ * <p>
+ * Note that this exception has identical semantics to {@link FatalException} (of which it is the immediate
+ * superclass) and can be considered a synonym.
+ *
+ * @see RecoverableException
+ * @see ApplicationException
+ * @see FatalException
+ */
+public class NonRecoverableException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public NonRecoverableException(final String msg) {
+ super(msg);
+ }
+
+ public NonRecoverableException(final Throwable cause) {
+ super(cause);
+ }
+
+ public NonRecoverableException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java b/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
index c308ca8..5506564 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/PersistFailedException.java
@@ -21,31 +21,30 @@ package org.apache.isis.applib;
/**
* Indicates that the persistence of an object failed.
+ *
+ * <p>
+ * This exception is intended to represent an unexpected and non-recoverable condition (eg a unique/primary key/
+ * foreign key constaint has been violated), and so is a subclass of {@link NonRecoverableException}.
+ * Throwing this exception will therefore result in (some sort of) error page being displayed
+ * to the user.
+ *
+ * @see NonRecoverableException
+ * @see RecoverableException
*/
-public class PersistFailedException extends RuntimeException {
+public class PersistFailedException extends NonRecoverableException {
+
private static final long serialVersionUID = 1L;
- private Throwable cause;
-
- public PersistFailedException() {
- super();
- }
-
+
public PersistFailedException(final String msg) {
super(msg);
}
public PersistFailedException(final Throwable cause) {
- this(cause.getMessage());
- this.cause = cause;
+ super(cause);
}
public PersistFailedException(final String msg, final Throwable cause) {
- this(msg);
- this.cause = cause;
+ super(msg, cause);
}
- @Override
- public Throwable getCause() {
- return cause;
- }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/RecoverableException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/RecoverableException.java b/core/applib/src/main/java/org/apache/isis/applib/RecoverableException.java
new file mode 100644
index 0000000..b3d7a43
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/RecoverableException.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package org.apache.isis.applib;
+
+/**
+ * Indicates that an exceptional condition/problem has occurred within the application's domain logic.
+ *
+ * <p>
+ * Throwing this exception is equivalent to calling {@link DomainObjectContainer#raiseError(String)}.
+ * The framework will trap the error and display the exception message as a warning.
+ *
+ * <p>
+ * This exception should only be thrown for "recoverable" exceptions, that is, those which
+ * could be anticipated by the application. It should not be thrown for fatal, unanticipated exceptions.
+ *
+ * <p>
+ * The framework attempts to apply some heuristics; if the underlying Isis transaction has been aborted
+ * (for example as the result of a problem persisting some data) but then the application attempts to
+ * throw this exception, the exception will be promoted to a fatal exception.
+ *
+ * <p>
+ * Note that this exception has identical semantics to {@link ApplicationException} (of which it is the immediate
+ * superclass), and can be considered a synonym.
+ *
+ * @see ApplicationException
+ * @see NonRecoverableException
+ * @see FatalException
+ */
+public class RecoverableException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public RecoverableException(final String msg) {
+ super(msg);
+ }
+
+ public RecoverableException(final Throwable cause) {
+ super(cause);
+ }
+
+ public RecoverableException(final String msg, final Throwable cause) {
+ super(msg, cause);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java b/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
index 786fcc2..d0839aa 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/RepositoryException.java
@@ -21,31 +21,29 @@ package org.apache.isis.applib;
/**
* Indicates that a repository method has failed.
+ *
+ * <p>
+ * This exception is intended to represent an unexpected and non-recoverable condition (eg a syntax error in some
+ * JDOQL query syntax or similar), and so is a subclass of {@link NonRecoverableException}.
+ * Throwing this exception will therefore result in (some sort of) error page being displayed
+ * to the user.
+ *
+ * @see NonRecoverableException
+ * @see RecoverableException
*/
-public class RepositoryException extends RuntimeException {
+public class RepositoryException extends NonRecoverableException {
+
private static final long serialVersionUID = 1L;
- private Throwable cause;
-
- public RepositoryException() {
- super();
- }
public RepositoryException(final String msg) {
super(msg);
}
public RepositoryException(final Throwable cause) {
- this(cause.getMessage());
- this.cause = cause;
+ super(cause);
}
public RepositoryException(final String msg, final Throwable cause) {
- this(msg);
- this.cause = cause;
- }
-
- @Override
- public Throwable getCause() {
- return cause;
+ super(msg, cause);
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java b/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
index 3ceca74..48ac2f3 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/clock/Clock.java
@@ -29,7 +29,8 @@ import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.Defaults;
import org.apache.isis.applib.fixtures.FixtureClock;
@@ -129,7 +130,7 @@ public abstract class Clock {
private static void ensureReplaceable() {
if (!isReplaceable && instance != null) {
- throw new ApplicationException("Clock already set up");
+ throw new RecoverableException("Clock already set up");
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java b/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
index 12caef0..03edfe6 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/fixtures/BaseFixture.java
@@ -19,7 +19,7 @@
package org.apache.isis.applib.fixtures;
import org.apache.isis.applib.AbstractContainedObject;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.clock.Clock;
abstract class BaseFixture extends AbstractContainedObject implements InstallableFixture {
@@ -31,7 +31,7 @@ abstract class BaseFixture extends AbstractContainedObject implements Installabl
this.fixtureType = fixtureType;
try {
clock = FixtureClock.initialize();
- } catch (final ApplicationException ex) {
+ } catch (final RecoverableException ex) {
clock = null;
System.err.println(ex.getMessage());
System.err.println("calls to change date or time will be ignored");
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/InteractionException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/InteractionException.java b/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/InteractionException.java
index cb8b643..a73f3d1 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/InteractionException.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/wrapper/InteractionException.java
@@ -19,11 +19,11 @@
package org.apache.isis.applib.services.wrapper;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.events.InteractionEvent;
-public abstract class InteractionException extends ApplicationException {
+public abstract class InteractionException extends RecoverableException {
private static final long serialVersionUID = 1L;
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/IsisApplicationException.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/IsisApplicationException.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/IsisApplicationException.java
index 3387e23..64863a6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/IsisApplicationException.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/IsisApplicationException.java
@@ -24,7 +24,7 @@ package org.apache.isis.core.commons.exceptions;
*
* <p>
* The viewer is expected to render the message within the application in a
- * user-friendly fashion.
+ * user-friendly fashion, for example as a growl-like notification.
*/
public class IsisApplicationException extends IsisException {
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ThrowableExtensions.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ThrowableExtensions.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ThrowableExtensions.java
index 571d0e4..5e96785 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ThrowableExtensions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ThrowableExtensions.java
@@ -24,7 +24,7 @@ import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.core.commons.exceptions.IsisApplicationException;
import org.apache.isis.core.metamodel.exceptions.MetaModelException;
@@ -48,7 +48,7 @@ public final class ThrowableExtensions {
public static void throwWithinIsisException(final InvocationTargetException e, final String error) {
final Throwable targetException = e.getTargetException();
- if (targetException instanceof ApplicationException) {
+ if (targetException instanceof RecoverableException) {
// an application exception from the domain code is re-thrown as an
// IsisException with same semantics
throw new IsisApplicationException(targetException);
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContext.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContext.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContext.java
index 44f3061..e5fbc52 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContext.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContext.java
@@ -83,7 +83,94 @@ public interface RuntimeContext extends Injectable, ApplicationScopedComponent {
public void setContainer(DomainObjectContainer container);
-
-
+ public TransactionState getTransactionState();
+
+ public static enum TransactionState {
+
+ /**
+ * No transaction exists.
+ */
+ NONE,
+ /**
+ * Started, still in progress.
+ *
+ * <p>
+ * May {@link IsisTransaction#flush() flush},
+ * {@link IsisTransaction#commit() commit} or
+ * {@link IsisTransaction#abort() abort}.
+ */
+ IN_PROGRESS,
+ /**
+ * Started, but has hit an exception.
+ *
+ * <p>
+ * May not {@link IsisTransaction#flush()} or
+ * {@link IsisTransaction#commit() commit} (will throw an
+ * {@link IllegalStateException}), but can only
+ * {@link IsisTransaction#abort() abort}.
+ *
+ * <p>
+ * Similar to <tt>setRollbackOnly</tt> in EJBs.
+ */
+ MUST_ABORT,
+ /**
+ * Completed, having successfully committed.
+ *
+ * <p>
+ * May not {@link IsisTransaction#flush()} or
+ * {@link IsisTransaction#abort() abort} or
+ * {@link IsisTransaction#commit() commit} (will throw
+ * {@link IllegalStateException}).
+ */
+ COMMITTED,
+ /**
+ * Completed, having aborted.
+ *
+ * <p>
+ * May not {@link IsisTransaction#flush()},
+ * {@link IsisTransaction#commit() commit} or
+ * {@link IsisTransaction#abort() abort} (will throw
+ * {@link IllegalStateException}).
+ */
+ ABORTED;
+
+ private TransactionState(){}
+
+ /**
+ * Whether it is valid to {@link IsisTransaction#flush() flush} this
+ * {@link IsisTransaction transaction}.
+ */
+ public boolean canFlush() {
+ return this == IN_PROGRESS;
+ }
+
+ /**
+ * Whether it is valid to {@link IsisTransaction#commit() commit} this
+ * {@link IsisTransaction transaction}.
+ */
+ public boolean canCommit() {
+ return this == IN_PROGRESS;
+ }
+
+ /**
+ * Whether it is valid to {@link IsisTransaction#markAsAborted() abort} this
+ * {@link IsisTransaction transaction}.
+ */
+ public boolean canAbort() {
+ return this == IN_PROGRESS || this == MUST_ABORT;
+ }
+
+ /**
+ * Whether the {@link IsisTransaction transaction} is complete (and so a
+ * new one can be started).
+ */
+ public boolean isComplete() {
+ return this == COMMITTED || this == ABORTED;
+ }
+
+ public boolean mustAbort() {
+ return this == MUST_ABORT;
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
index bf8dd81..0417498 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/noruntime/RuntimeContextNoRuntime.java
@@ -355,4 +355,15 @@ public class RuntimeContextNoRuntime extends RuntimeContextAbstract {
public LocalizationProvider getLocalizationProvider() {
return localizationProvider;
}
+
+
+ // ///////////////////////////////////////////
+ // getTransactionState
+ // ///////////////////////////////////////////
+
+ @Override
+ public TransactionState getTransactionState() {
+ throw new UnsupportedOperationException("Not supported by this implementation of RuntimeContext");
+ }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
index 031ae0b..7239695 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/devutils/DeveloperUtilitiesServiceDefault.java
@@ -35,7 +35,8 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.services.devutils.DeveloperUtilitiesService;
import org.apache.isis.applib.value.Blob;
@@ -187,8 +188,8 @@ public class DeveloperUtilitiesServiceDefault implements DeveloperUtilitiesServi
}
writer.close();
return new Blob("layouts.zip", mimeTypeApplicationZip, baos.toByteArray());
- } catch (IOException e) {
- throw new ApplicationException("Unable to create zip of layouts", e);
+ } catch (final IOException ex) {
+ throw new FatalException("Unable to create zip of layouts", ex);
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetFactory.java
index 81c3c58..06a71b1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetFactory.java
@@ -33,6 +33,8 @@ import org.apache.isis.core.metamodel.facets.actions.exploration.ExplorationFace
import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
import org.apache.isis.core.metamodel.facets.named.NamedFacet;
import org.apache.isis.core.metamodel.facets.named.NamedFacetInferred;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContextAware;
import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
@@ -47,7 +49,7 @@ import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstra
* and {@link DebugFacet}. In addition a {@link NamedFacet} is inferred from the
* name (taking into account the above well-known prefixes).
*/
-public class ActionInvocationFacetFactory extends MethodPrefixBasedFacetFactoryAbstract implements AdapterManagerAware, ServicesInjectorAware {
+public class ActionInvocationFacetFactory extends MethodPrefixBasedFacetFactoryAbstract implements AdapterManagerAware, ServicesInjectorAware, RuntimeContextAware {
private static final String EXPLORATION_PREFIX = "Exploration";
private static final String DEBUG_PREFIX = "Debug";
@@ -56,6 +58,7 @@ public class ActionInvocationFacetFactory extends MethodPrefixBasedFacetFactoryA
private AdapterManager adapterManager;
private ServicesInjector servicesInjector;
+ private RuntimeContext runtimeContext;
/**
* Note that the {@link Facet}s registered are the generic ones from
@@ -99,7 +102,7 @@ public class ActionInvocationFacetFactory extends MethodPrefixBasedFacetFactoryA
final ObjectSpecification typeSpec = getSpecificationLoader().loadSpecification(cls);
final FacetHolder holder = processMethodContext.getFacetHolder();
- FacetUtil.addFacet(new ActionInvocationFacetViaMethod(actionMethod, typeSpec, returnSpec, holder, getAdapterManager(), getServicesInjector()));
+ FacetUtil.addFacet(new ActionInvocationFacetViaMethod(actionMethod, typeSpec, returnSpec, holder, getRuntimeContext(), getAdapterManager(), getServicesInjector()));
} finally {
processMethodContext.removeMethod(actionMethod);
}
@@ -169,4 +172,13 @@ public class ActionInvocationFacetFactory extends MethodPrefixBasedFacetFactoryA
private ServicesInjector getServicesInjector() {
return servicesInjector;
}
+
+ private RuntimeContext getRuntimeContext() {
+ return runtimeContext;
+ }
+
+ @Override
+ public void setRuntimeContext(RuntimeContext runtimeContext) {
+ this.runtimeContext = runtimeContext;
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
index 07daf5f..624f8ac 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
@@ -30,6 +30,8 @@ import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.annotation.Bulk;
import org.apache.isis.applib.annotation.Bulk.InteractionContext.InvokedAs;
import org.apache.isis.applib.services.background.ActionInvocationMemento;
@@ -54,6 +56,7 @@ import org.apache.isis.core.metamodel.facets.actions.reified.ReifiedActionFacet;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
import org.apache.isis.core.metamodel.facets.typeof.ElementSpecificationProviderFromTypeOfFacet;
import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
@@ -71,12 +74,14 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
private final AdapterManager adapterManager;
private final ServicesInjector servicesInjector;
-
+ private final RuntimeContext runtimeContext;
+
public ActionInvocationFacetViaMethod(
final Method method,
final ObjectSpecification onType,
final ObjectSpecification returnType,
final FacetHolder holder,
+ final RuntimeContext runtimeContext,
final AdapterManager adapterManager,
final ServicesInjector servicesInjector) {
super(holder);
@@ -84,6 +89,7 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
this.paramCount = method.getParameterTypes().length;
this.onType = onType;
this.returnType = returnType;
+ this.runtimeContext = runtimeContext;
this.adapterManager = adapterManager;
this.servicesInjector = servicesInjector;
}
@@ -203,12 +209,22 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
} catch (final IllegalArgumentException e) {
throw e;
} catch (final InvocationTargetException e) {
- if (e.getTargetException() instanceof IllegalStateException) {
- throw new ReflectiveActionException("IllegalStateException thrown while executing " + method + " " + e.getTargetException().getMessage(), e.getTargetException());
- } else {
- ThrowableExtensions.throwWithinIsisException(e, "Exception executing " + method);
- return null;
+ final Throwable targetException = e.getTargetException();
+ if (targetException instanceof IllegalStateException) {
+ throw new ReflectiveActionException("IllegalStateException thrown while executing " + method + " " + targetException.getMessage(), targetException);
+ }
+ if(targetException instanceof RecoverableException) {
+ if (!runtimeContext.getTransactionState().canCommit()) {
+ // something severe has happened to the underlying transaction;
+ // so escalate this exception to be non-recoverable
+ final Throwable targetExceptionCause = targetException.getCause();
+ Throwable nonRecoverableCause = targetExceptionCause != null? targetExceptionCause: targetException;
+ throw new NonRecoverableException(nonRecoverableCause);
+ }
}
+
+ ThrowableExtensions.throwWithinIsisException(e, "Exception executing " + method);
+ return null;
} catch (final IllegalAccessException e) {
throw new ReflectiveActionException("Illegal access of " + method, e);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
index 57d5ff3..406ac36 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/event/PostsPropertyChangedEventFacetAnnotation.java
@@ -25,7 +25,8 @@ import java.util.List;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.FatalException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.services.eventbus.EventBusService;
import org.apache.isis.applib.services.eventbus.PropertyChangedEvent;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -110,7 +111,7 @@ public class PostsPropertyChangedEventFacetAnnotation extends PostsPropertyChang
eventBusService.post(event);
} catch (Exception e) {
- throw new ApplicationException(e);
+ throw new FatalException(e);
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
index 5bc58b7..1f13e00 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/internal/RuntimeContextFromSession.java
@@ -21,7 +21,7 @@ package org.apache.isis.core.runtime.persistence.internal;
import java.util.List;
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.profiles.Localization;
import org.apache.isis.applib.query.Query;
import org.apache.isis.applib.services.bookmark.Bookmark;
@@ -60,6 +60,8 @@ import org.apache.isis.core.runtime.persistence.container.DomainObjectContainerR
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.session.IsisSession;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction.State;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.core.runtime.system.transaction.MessageBroker;
import org.apache.isis.core.runtime.system.transaction.UpdateNotifier;
@@ -238,7 +240,7 @@ public class RuntimeContextFromSession extends RuntimeContextAbstract {
@Override
public void raiseError(final String message) {
- throw new ApplicationException(message);
+ throw new RecoverableException(message);
}
@Override
@@ -396,6 +398,14 @@ public class RuntimeContextFromSession extends RuntimeContextAbstract {
return IsisContext.getMessageBroker();
}
-
+ @Override
+ public TransactionState getTransactionState() {
+ final IsisTransaction transaction = getTransactionManager().getTransaction();
+ if(transaction == null) {
+ return TransactionState.NONE;
+ }
+ IsisTransaction.State state = transaction.getState();
+ return state.getRuntimeContextState();
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
index 9fda66f..3bf77dd 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/BackgroundActionExecution.java
@@ -33,6 +33,7 @@ import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.progmodel.facets.actions.invoke.ReifiableActionUtil;
import org.apache.isis.core.runtime.services.memento.MementoServiceDefault;
import org.apache.isis.core.runtime.sessiontemplate.AbstractIsisSessionTemplate;
@@ -93,9 +94,9 @@ public abstract class BackgroundActionExecution extends AbstractIsisSessionTempl
}
final ObjectAdapter[] argAdapters = argAdaptersFor(aim);
- ObjectAdapter resultAdapter = objectAction.execute(targetAdapter, argAdapters);
+ final ObjectAdapter resultAdapter = objectAction.execute(targetAdapter, argAdapters);
if(resultAdapter != null) {
- Bookmark resultBookmark = bookmarkService.bookmarkFor(resultAdapter.getObject());
+ Bookmark resultBookmark = ReifiableActionUtil.bookmarkFor(resultAdapter);
backgroundAction.setResult(resultBookmark);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
index 8118e4a..2862f2b 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransaction.java
@@ -70,6 +70,7 @@ import org.apache.isis.core.metamodel.facets.actions.publish.PublishedActionFace
import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet;
import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
import org.apache.isis.core.metamodel.facets.object.publish.PublishedObjectFacet;
+import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext.TransactionState;
import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
@@ -95,6 +96,7 @@ import org.apache.isis.core.runtime.system.context.IsisContext;
*/
public class IsisTransaction implements TransactionScopedComponent {
+
public static enum State {
/**
* Started, still in progress.
@@ -104,7 +106,7 @@ public class IsisTransaction implements TransactionScopedComponent {
* {@link IsisTransaction#commit() commit} or
* {@link IsisTransaction#abort() abort}.
*/
- IN_PROGRESS,
+ IN_PROGRESS(TransactionState.IN_PROGRESS),
/**
* Started, but has hit an exception.
*
@@ -117,7 +119,7 @@ public class IsisTransaction implements TransactionScopedComponent {
* <p>
* Similar to <tt>setRollbackOnly</tt> in EJBs.
*/
- MUST_ABORT,
+ MUST_ABORT(TransactionState.MUST_ABORT),
/**
* Completed, having successfully committed.
*
@@ -127,7 +129,7 @@ public class IsisTransaction implements TransactionScopedComponent {
* {@link IsisTransaction#commit() commit} (will throw
* {@link IllegalStateException}).
*/
- COMMITTED,
+ COMMITTED(TransactionState.COMMITTED),
/**
* Completed, having aborted.
*
@@ -137,9 +139,14 @@ public class IsisTransaction implements TransactionScopedComponent {
* {@link IsisTransaction#abort() abort} (will throw
* {@link IllegalStateException}).
*/
- ABORTED;
+ ABORTED(TransactionState.ABORTED);
+
+ public final TransactionState transactionState;
+
+ private State(TransactionState transactionState){
+ this.transactionState = transactionState;
+ }
- private State(){}
/**
* Whether it is valid to {@link IsisTransaction#flush() flush} this
@@ -176,6 +183,10 @@ public class IsisTransaction implements TransactionScopedComponent {
public boolean mustAbort() {
return this == MUST_ABORT;
}
+
+ public TransactionState getRuntimeContextState() {
+ return transactionState;
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ParentEntity.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ParentEntity.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ParentEntity.java
index e97dd55..2b6c43c 100644
--- a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ParentEntity.java
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ParentEntity.java
@@ -93,7 +93,7 @@ public class ParentEntity extends BaseEntity {
// {{ NotPersisted
@NotPersisted
public List<SimpleEntity> getNotPersisted() {
- throw new org.apache.isis.applib.ApplicationException("unexpected call");
+ throw new org.apache.isis.applib.NonRecoverableException("unexpected call");
}
// }}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ReferencingEntity.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ReferencingEntity.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ReferencingEntity.java
index b076705..645e03e 100644
--- a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ReferencingEntity.java
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/ReferencingEntity.java
@@ -87,7 +87,7 @@ public class ReferencingEntity extends BaseEntity {
// {{ NotPersisted
@NotPersisted
public SimpleEntity getNotPersisted() {
- throw new org.apache.isis.applib.ApplicationException("unexpected call");
+ throw new org.apache.isis.applib.NonRecoverableException("unexpected call");
}
// }}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/SimpleEntity.java
----------------------------------------------------------------------
diff --git a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/SimpleEntity.java b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/SimpleEntity.java
index 1ec2c14..89c3fc4 100644
--- a/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/SimpleEntity.java
+++ b/core/tck/tck-dom/src/main/java/org/apache/isis/core/tck/dom/refs/SimpleEntity.java
@@ -96,7 +96,7 @@ public class SimpleEntity extends BaseEntity {
// {{ NotPersisted: int (nb: throws exception if called)
@NotPersisted
public int getNotPersisted() {
- throw new org.apache.isis.applib.ApplicationException("unexpected call");
+ throw new org.apache.isis.applib.NonRecoverableException("unexpected call");
}
// }}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index df0516f..4d7ac81 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -40,6 +40,8 @@ import com.google.common.collect.Ordering;
import org.joda.time.LocalDate;
import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.RecoverableException;
import org.apache.isis.applib.DomainObjectContainer;
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.ActionSemantics.Of;
@@ -277,7 +279,7 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
this.subcategory = subcategory;
}
-
+
// //////////////////////////////////////
// OwnedBy (property)
// //////////////////////////////////////
@@ -650,25 +652,30 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
// //////////////////////////////////////
static enum DemoExceptionType {
- APPLICATION_EXCEPTION(ApplicationException.class),
- RUNTIME_EXCEPTION(RuntimeException.class);
- private final Class<? extends Exception> type;
- private DemoExceptionType(Class<? extends Exception> type) {
- this.type = type;
- }
- @Override
- public String toString() {
- return type.getName();
- }
+ RecoverableException,
+ RecoverableExceptionAutoEscalated,
+ NonRecoverableException;
}
@Prototype
@ActionSemantics(Of.SAFE)
public void demoException(final @Named("Type") DemoExceptionType type) {
- if(type == DemoExceptionType.RUNTIME_EXCEPTION)
- throw new RuntimeException("Demo throwing runtime exception");
- else
- throw new ApplicationException("Demo throwing application exception");
+ switch(type) {
+ case NonRecoverableException:
+ throw new NonRecoverableException("Demo throwing " + type.name());
+ case RecoverableException:
+ throw new RecoverableException("Demo throwing " + type.name());
+ case RecoverableExceptionAutoEscalated:
+ try {
+ // this will trigger an exception (because subcategory cannot be null), causing the xactn to be aborted
+ setSubcategory(null);
+ container.flush();
+ } catch(Exception e) {
+ // it's a programming mistake to throw only a recoverable exception here, because of the xactn's state.
+ // the framework should instead auto-escalate this to a non-recoverable exception
+ throw new RecoverableException("Demo throwing " + type.name(), e);
+ }
+ }
}
// //////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
index bc1acb8..da28f6a 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.layout.json
@@ -85,9 +85,9 @@
{
span: 6,
memberGroups: {
- Detail: {
+ Priority: {
members: {
- priority: {
+ relativePriority: {
actions: {
previous: {},
next: {}
@@ -95,7 +95,11 @@
},
dueBy: {
cssClass: { value: "x-key" }
- },
+ }
+ }
+ },
+ Other: {
+ members: {
cost: {
actions: {
updateCost:{
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
index 4762857..a264349 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
@@ -57,7 +57,7 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
@NotContributed(As.ACTION)
@Hidden(where=Where.ALL_TABLES)
@Disabled(reason="Relative priority, derived from due date")
- public Integer priority(final ToDoItem toDoItem) {
+ public Integer relativePriority(final ToDoItem toDoItem) {
if(toDoItem.isComplete()) {
return null;
}
@@ -106,7 +106,7 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
@ActionSemantics(Of.SAFE)
@NotContributed(As.ASSOCIATION)
public ToDoItem next(final ToDoItem item) {
- final Integer priority = priority(item);
+ final Integer priority = relativePriority(item);
if(priority == null) {
return item;
}
@@ -119,7 +119,7 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
@ActionSemantics(Of.SAFE)
@NotContributed(As.ASSOCIATION)
public ToDoItem previous(final ToDoItem item) {
- final Integer priority = priority(item);
+ final Integer priority = relativePriority(item);
if(priority == null) {
return item;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/9032a866/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemContributionsTest_priority.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemContributionsTest_priority.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemContributionsTest_priority.java
index 8fba902..cce36a2 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemContributionsTest_priority.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/tests/props/ToDoItemContributionsTest_priority.java
@@ -62,7 +62,7 @@ public class ToDoItemContributionsTest_priority extends ToDoIntegTest {
}
private void assertPriority(final int n, final int priority) {
- assertThat(toDoItemContributions.priority(notYetComplete.get(n)), is(Integer.valueOf(priority)));
+ assertThat(toDoItemContributions.relativePriority(notYetComplete.get(n)), is(Integer.valueOf(priority)));
}
}
\ No newline at end of file