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/02/28 18:10:59 UTC
git commit: ISIS-351: exceptions on edit page now rendered via its
feedback
Updated Branches:
refs/heads/master 1e84d8507 -> a30c737d1
ISIS-351: exceptions on edit page now rendered via its feedback
... similar to how we handle actions with args.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/a30c737d
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/a30c737d
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/a30c737d
Branch: refs/heads/master
Commit: a30c737d180356427df5c92ddbe56f7178ed9370
Parents: 1e84d85
Author: Dan Haywood <da...@apache.org>
Authored: Thu Feb 28 17:10:34 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Thu Feb 28 17:10:34 2013 +0000
----------------------------------------------------------------------
.../jdo/datanucleus/DataNucleusObjectStore.java | 42 ++---
.../integration/wicket/WebRequestCycleForIsis.java | 15 ++-
.../wicket/ui/components/actions/ActionPanel.java | 67 ++++----
.../entity/properties/EntityPropertiesForm.java | 131 +++++++++++----
.../system/transaction/IsisTransaction.java | 16 ++-
5 files changed, 171 insertions(+), 100 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/a30c737d/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusObjectStore.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusObjectStore.java b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusObjectStore.java
index f8016ea..490cdb4 100644
--- a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusObjectStore.java
+++ b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusObjectStore.java
@@ -330,38 +330,30 @@ public class DataNucleusObjectStore implements ObjectStoreSpi {
ensureOpened();
ensureInTransaction();
- if (LOG.isDebugEnabled()) {
- LOG.debug("execute " + commands.size() + " commands");
- }
+ // no longer check if there are no commands; it could be that
+ // DataNucleus has some dirty objects anyway that don't have
+ // commands wrapped around them...
- if (commands.size() <= 0) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("no commands");
- }
- return;
- }
+// if (LOG.isDebugEnabled()) {
+// LOG.debug("execute " + commands.size() + " commands");
+// }
+//
+// if (commands.size() <= 0) {
+// if (LOG.isDebugEnabled()) {
+// LOG.debug("no commands");
+// }
+// return;
+// }
executeCommands(commands);
}
private void executeCommands(final List<PersistenceCommand> commands) {
- // there's no need to do any exception handling here, because we are called
- // from IsisTransaction.flush() that will catch exceptions and set its abortCause
- // if need be.
-
-// try {
- for (final PersistenceCommand command : commands) {
- command.execute(null);
- }
- getPersistenceManager().flush();
-// } catch (final RuntimeException e) {
-// LOG.warn("Failure during execution - aborting transaction and rethrowing", e);
-//
-// abortTransaction();
-//
-// throw e;
-// }
+ for (final PersistenceCommand command : commands) {
+ command.execute(null);
+ }
+ getPersistenceManager().flush();
}
// ///////////////////////////////////////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/a30c737d/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
index f5d7b0e..8d547b7 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
@@ -49,7 +49,7 @@ import org.apache.wicket.request.cycle.RequestCycle;
* automatically opening a {@link IsisSession} at the beginning of the request
* and committing the transaction and closing the session at the end.
*/
-public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends AbstractRequestCycleListener {
+public class WebRequestCycleForIsis extends AbstractRequestCycleListener {
private static final Logger LOG = Logger.getLogger(WebRequestCycleForIsis.class);
@@ -91,6 +91,13 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract
// an abort will cause the exception to be thrown.
getTransactionManager().endTransaction();
} catch(Exception ex) {
+ if(handler instanceof RenderPageRequestHandler) {
+ RenderPageRequestHandler requestHandler = (RenderPageRequestHandler) handler;
+ if(requestHandler.getPage() instanceof ErrorPage) {
+ // do nothing;
+ return;
+ }
+ }
throw new RestartResponseException(errorPageProviderFor(ex), RedirectPolicy.ALWAYS_REDIRECT);
}
}
@@ -118,9 +125,11 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract
// previously we had a handler in here. However, it seems to be sufficient to just
// use the exception handling in the onRequestHandlerExecuted(...) callback
// which fires before the onEndRequest(...) callback.
+ //return super.onException(cycle, ex);
- //return new RenderPageRequestHandler(errorPageProviderFor(ex));
- return super.onException(cycle, ex);
+ // hmm, maybe not. making in edit page do a flush seems to belie that.
+
+ return new RenderPageRequestHandler(errorPageProviderFor(ex), RedirectPolicy.ALWAYS_REDIRECT);
}
protected PageProvider errorPageProviderFor(Exception ex) {
http://git-wip-us.apache.org/repos/asf/isis/blob/a30c737d/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 d519f00..a397f33 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
@@ -23,12 +23,7 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
-import org.apache.wicket.MarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.model.Model;
-
import org.apache.isis.applib.ApplicationException;
-import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
import org.apache.isis.core.commons.authentication.MessageBroker;
@@ -39,7 +34,6 @@ 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;
import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.viewer.wicket.model.common.SelectionHandler;
import org.apache.isis.viewer.wicket.model.isis.PersistenceSessionProvider;
@@ -55,6 +49,10 @@ import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
import org.apache.isis.viewer.wicket.ui.pages.BookmarkedPagesModelProvider;
import org.apache.isis.viewer.wicket.ui.pages.entity.EntityPage;
import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
+import org.apache.wicket.Component;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.model.Model;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
@@ -194,31 +192,19 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
} catch (RuntimeException ex) {
- // see if the exception is recognized as being a non-serious error
- // (nb: similar code in WebRequestCycleForIsis, as a fallback)
- List<ExceptionRecognizer> exceptionRecognizers = getServicesInjector().lookupServices(ExceptionRecognizer.class);
- String message = new ExceptionRecognizerComposite(exceptionRecognizers).recognize(ex);
- if(message != null) {
- // recognized
- if(feedbackForm != null) {
- feedbackForm.error(message);
- } else {
- // use notification mechanism otherwise
- getMessageBroker().setApplicationError(message);
-
- // forward on instead to void page
- final ResultType resultType = ResultType.determineFor(null);
- resultType.addResults(this, null);
+ String message = recognizeException(ex, feedbackForm);
+
+ if (message != null) {
+ if(feedbackForm == null) {
+ // forward on instead to void page
+ // (otherwise, we'll have rendered an action parameters page
+ // and so we'll be staying on that page)
+ final ResultType resultType = ResultType.determineFor(null);
+ resultType.addResults(this, null);
}
-
- // there's no need to abort the transaction, it will have already been done
- // (in IsisTransactionManager#executeWithinTransaction(...)).
-
- getTransactionManager().getTransaction().clearAbortCause();
-
return false;
- }
+ }
// not handled, so propagate
throw ex;
@@ -226,6 +212,28 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
}
+ private String recognizeException(RuntimeException ex, Component feedbackComponent) {
+ // see if the exception is recognized as being a non-serious error
+ // (nb: similar code in WebRequestCycleForIsis, as a fallback)
+ List<ExceptionRecognizer> exceptionRecognizers = getServicesInjector().lookupServices(ExceptionRecognizer.class);
+ String message = new ExceptionRecognizerComposite(exceptionRecognizers).recognize(ex);
+ if(message != null) {
+ // recognized
+ if(feedbackComponent != null) {
+ feedbackComponent.error(message);
+ } else {
+ // use notification mechanism otherwise
+ getMessageBroker().setApplicationError(message);
+ }
+
+ // there's no need to abort the transaction, it will have already been done
+ // (in IsisTransactionManager#executeWithinTransaction(...)).
+ getTransactionManager().getTransaction().clearAbortCause();
+
+ }
+ return message;
+ }
+
/**
* Executes the action, handling any {@link ApplicationException}s that
* might be encountered.
@@ -446,9 +454,6 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
return IsisContext.getTransactionManager();
}
- /**
- * Factored out so can be overridden in testing.
- */
protected ServicesInjector getServicesInjector() {
return IsisContext.getPersistenceSession().getServicesInjector();
}
http://git-wip-us.apache.org/repos/asf/isis/blob/a30c737d/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
index c317438..168d5cc 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
@@ -21,35 +21,24 @@ package org.apache.isis.viewer.wicket.ui.components.entity.properties;
import java.util.List;
import java.util.Map;
-import org.apache.wicket.Component;
-import org.apache.wicket.Session;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.feedback.FeedbackMessage;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.html.form.FormComponent;
-import org.apache.wicket.markup.html.form.validation.AbstractFormValidator;
-import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
-import org.apache.wicket.markup.html.panel.FeedbackPanel;
-import org.apache.wicket.markup.repeater.RepeatingView;
-import org.apache.wicket.model.Model;
-import org.apache.wicket.util.visit.IVisit;
-import org.apache.wicket.util.visit.IVisitor;
-
import org.apache.isis.applib.annotation.Where;
import org.apache.isis.applib.filter.Filter;
import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
+import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
+import org.apache.isis.core.commons.authentication.MessageBroker;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
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.runtimecontext.ServicesInjector;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociationFilters;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.core.progmodel.facets.object.validate.ValidateObjectFacet;
import org.apache.isis.core.runtime.memento.Memento;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
import org.apache.isis.viewer.wicket.model.models.EntityModel;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
@@ -61,6 +50,22 @@ import org.apache.isis.viewer.wicket.ui.panels.AjaxButtonWithPreSubmitHook;
import org.apache.isis.viewer.wicket.ui.panels.ButtonWithPreSubmitHook;
import org.apache.isis.viewer.wicket.ui.panels.FormAbstract;
import org.apache.isis.viewer.wicket.ui.util.EvenOrOddCssClassAppenderFactory;
+import org.apache.wicket.Component;
+import org.apache.wicket.Session;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.feedback.FeedbackMessage;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.validation.AbstractFormValidator;
+import org.apache.wicket.markup.html.panel.ComponentFeedbackPanel;
+import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import org.apache.wicket.markup.repeater.RepeatingView;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.util.visit.IVisit;
+import org.apache.wicket.util.visit.IVisitor;
class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
@@ -195,28 +200,40 @@ class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
@Override
public void onSubmit() {
- if (!getForm().hasError()) {
- final ObjectAdapter object = getEntityModel().getObject();
- final Memento snapshotToRollbackToIfInvalid = new Memento(object);
- // to perform object-level validation, we must apply the
- // changes first
- // contrast this with ActionPanel (for validating action
- // arguments) where
- // we do the validation prior to the execution of the
- // action
- getEntityModel().apply();
- final String invalidReasonIfAny = getEntityModel().getReasonInvalidIfAny();
- if (invalidReasonIfAny != null) {
- getForm().error(invalidReasonIfAny);
- snapshotToRollbackToIfInvalid.recreateObject();
- return;
- } else {
- getEntityModel().resetPropertyModels();
- toViewMode(null);
- }
- } else {
+ if (getForm().hasError()) {
// stay in edit mode
+ return;
+ }
+
+ final ObjectAdapter object = getEntityModel().getObject();
+ final Memento snapshotToRollbackToIfInvalid = new Memento(object);
+ // to perform object-level validation, we must apply the
+ // changes first
+ // contrast this with ActionPanel (for validating action
+ // arguments) where
+ // we do the validation prior to the execution of the
+ // action
+ getEntityModel().apply();
+ final String invalidReasonIfAny = getEntityModel().getReasonInvalidIfAny();
+ if (invalidReasonIfAny != null) {
+ getForm().error(invalidReasonIfAny);
+ snapshotToRollbackToIfInvalid.recreateObject();
+ return;
+ }
+
+ try {
+ EntityPropertiesForm.this.getTransactionManager().flushTransaction();
+ } catch(RuntimeException ex) {
+ String message = recognizeException(ex, EntityPropertiesForm.this);
+ if(message == null) {
+ throw ex;
+ }
+ return;
}
+
+ getEntityModel().resetPropertyModels();
+
+ toViewMode(null);
}
};
@@ -263,6 +280,28 @@ class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
cancelButton.setOutputMarkupPlaceholderTag(true);
}
+ private String recognizeException(RuntimeException ex, Component feedbackComponent) {
+ // see if the exception is recognized as being a non-serious error
+ // (nb: similar code in WebRequestCycleForIsis, as a fallback)
+ List<ExceptionRecognizer> exceptionRecognizers = getServicesInjector().lookupServices(ExceptionRecognizer.class);
+ String message = new ExceptionRecognizerComposite(exceptionRecognizers).recognize(ex);
+ if(message != null) {
+ // recognized
+ if(feedbackComponent != null) {
+ feedbackComponent.error(message);
+ } else {
+ // use notification mechanism otherwise
+ getMessageBroker().setApplicationError(message);
+ }
+
+ // there's no need to abort the transaction, it will have already been done
+ // (in IsisTransactionManager#executeWithinTransaction(...)).
+ getTransactionManager().getTransaction().clearAbortCause();
+
+ }
+ return message;
+ }
+
private void requestRepaintPanel(final AjaxRequestTarget target) {
if (target != null) {
target.add(owningPanel);
@@ -341,6 +380,7 @@ class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
private void addFeedbackGui() {
final FeedbackPanel feedback = addOrReplaceFeedback();
+ feedback.setEscapeModelStrings(false);
final ObjectAdapter adapter = getEntityModel().getObject();
if (adapter == null) {
@@ -354,4 +394,21 @@ class EntityPropertiesForm extends FormAbstract<ObjectAdapter> {
addOrReplace(feedback);
return feedback;
}
+
+ ///////////////////////////////////////////////////////
+ // Dependencies (from context)
+ ///////////////////////////////////////////////////////
+
+ protected IsisTransactionManager getTransactionManager() {
+ return IsisContext.getTransactionManager();
+ }
+
+ protected ServicesInjector getServicesInjector() {
+ return IsisContext.getPersistenceSession().getServicesInjector();
+ }
+
+ protected MessageBroker getMessageBroker() {
+ return getAuthenticationSession().getMessageBroker();
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/a30c737d/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 d20f791..5f89c1c 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
@@ -303,10 +303,18 @@ public class IsisTransaction implements TransactionScopedComponent {
// ////////////////////////////////////////////////////////////////
public synchronized final void flush() {
- if(commands.isEmpty()) {
- // nothing to do
- return;
- }
+ // have removed the guard below because not every objectstore necessarily
+ // wraps up every change inside a command.
+
+ // for example, the JDO object store just lets DataNucleus do the change tracking
+ // itself
+
+// if(commands.isEmpty()) {
+// // nothing to do
+// return;
+// }
+
+
ensureThatState(getState().canFlush(), is(true), "state is: " + getState());
if (LOG.isDebugEnabled()) {
LOG.debug("flush transaction " + this);