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/10/11 14:15:11 UTC
git commit: ISIS-401: reinstated and refined concurrency checking for
invoking actions
Updated Branches:
refs/heads/master e57e4281d -> bda2045b3
ISIS-401: reinstated and refined concurrency checking for invoking actions
specifically
- if invoking an action with "safe" semantics, then no concurrency checking is performed
- if invoke a no-arg action, and detect change, then render the entity
and pop up a warning
- if invoke an action with args, and detect change, then render the entity (rather than
the action prompt form) and pop up a warning
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/bda2045b
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/bda2045b
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/bda2045b
Branch: refs/heads/master
Commit: bda2045b34fc7a7392f6fce68031bee7d500ccac
Parents: e57e428
Author: Dan Haywood <da...@apache.org>
Authored: Fri Oct 11 13:14:06 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Oct 11 13:14:06 2013 +0100
----------------------------------------------------------------------
.../model/mementos/ObjectAdapterMemento.java | 14 ++++++---
.../viewer/wicket/model/models/ActionModel.java | 1 -
.../ui/components/actions/ActionPanel.java | 33 +++++++++++++++-----
.../entity/EntityActionLinkFactory.java | 13 ++++----
.../metamodel/adapter/mgr/AdapterManager.java | 6 ++++
.../DeveloperUtilitiesServiceDefault.java | 1 -
.../dom/src/main/java/dom/todo/ToDoItems.java | 6 ++--
7 files changed, 51 insertions(+), 23 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
index 0193a7e..af0dc41 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ObjectAdapterMemento.java
@@ -102,12 +102,18 @@ public class ObjectAdapterMemento implements Serializable {
@Override
ObjectAdapter recreateAdapter(final ObjectAdapterMemento oam, ConcurrencyChecking concurrencyChecking) {
TypedOid oid = getOidMarshaller().unmarshal(oam.persistentOidStr, TypedOid.class);
- final ObjectAdapter adapter = getAdapterManager().adapterFor(oid, concurrencyChecking);
- // reset version
- if(concurrencyChecking == ConcurrencyChecking.NO_CHECK) {
+ try {
+ final ObjectAdapter adapter = getAdapterManager().adapterFor(oid, concurrencyChecking);
+ return adapter;
+
+ } finally {
+ // a side-effect of AdapterManager#adapterFor(...) is that it will update the oid
+ // with the correct version, even when there is a concurrency exception
+ // we copy this updated oid string into our memento so that, if we retry,
+ // we will succeed second time around
+
oam.persistentOidStr = oid.enString(getOidMarshaller());
}
- return adapter;
}
@Override
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/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 672bb53..0ecd130 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
@@ -117,7 +117,6 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
final Mode actionMode = determineActionMode(objectAction, contextAdapter);
PageParameterNames.ACTION_MODE.addEnumTo(pageParameters, actionMode);
- //addActionParamContextIfPossible(objectAction, contextAdapter, pageParameters);
return pageParameters;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/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 756b53c..fafe250 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
@@ -108,12 +108,33 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
}
private void buildGuiForParameters(ActionModel actionModel) {
- hideAllBut(ComponentType.PARAMETERS, ComponentType.ENTITY_ICON_AND_TITLE);
- getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.PARAMETERS, getActionModel());
- getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.ENTITY_ICON_AND_TITLE, new EntityModel(getActionModel().getTargetAdapter()));
- final String actionName = getActionModel().getActionMemento().getAction().getName();
- addOrReplace(new Label(ID_ACTION_NAME, Model.of(actionName)));
+
+ ObjectAdapter targetAdapter = null;
+ try {
+ targetAdapter = getActionModel().getTargetAdapter();
+
+ hideAllBut(ComponentType.PARAMETERS, ComponentType.ENTITY_ICON_AND_TITLE);
+ getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.PARAMETERS, getActionModel());
+ getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.ENTITY_ICON_AND_TITLE, new EntityModel(targetAdapter));
+
+ final String actionName = getActionModel().getActionMemento().getAction().getName();
+ addOrReplace(new Label(ID_ACTION_NAME, Model.of(actionName)));
+
+ } catch (final ConcurrencyException ex) {
+
+ // second attempt should succeed, because the Oid would have
+ // been updated in the attempt
+ if (targetAdapter == null) {
+ targetAdapter = getModel().getTargetAdapter();
+ }
+
+ // forward onto the target page with the concurrency exception
+ ResultType.OBJECT.addResults(this, targetAdapter, ex);
+
+ getMessageBroker().addWarning(ex.getMessage());
+
+ }
}
protected void bookmarkPage(BookmarkableModel<?> model) {
@@ -153,8 +174,6 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
// forward onto the target page with the concurrency exception
-
- // REVIEW: doesn't seem to get rendered
ResultType.OBJECT.addResults(this, targetAdapter, ex);
getMessageBroker().addWarning(ex.getMessage());
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
index 1dde6e8..89cb386 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
@@ -25,6 +25,7 @@ import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.request.mapper.parameter.PageParameters;
+import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.Where;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -102,13 +103,11 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
final ObjectAdapter contextAdapter = entityModel.getObject();
- // use NO concurrency checking because the link is rendered on the entity page.
-
- // REVIEW: is this good enough?
- // - On the one hand we need it because otherwise a change done by this user basically prevents all actions from working
- // - on the other hand, if a change were made by some other user, then this user would want to know...
- // perhaps the generated bookmarks need to subscribe to the EntityModel that backs the page?
- final PageParameters pageParameters = ActionModel.createPageParameters(adapter, action, contextAdapter, ActionModel.SingleResultsMode.REDIRECT, ConcurrencyChecking.NO_CHECK);
+ // use the action semantics to determine whether invoking this action will require a concurrency check or not
+ // if it's "safe", then we'll just continue without any checking.
+ final ConcurrencyChecking concurrencyChecking =
+ action.getSemantics() == ActionSemantics.Of.SAFE? ConcurrencyChecking.NO_CHECK: ConcurrencyChecking.CHECK;
+ final PageParameters pageParameters = ActionModel.createPageParameters(adapter, action, contextAdapter, ActionModel.SingleResultsMode.REDIRECT, concurrencyChecking);
final Class<? extends Page> pageClass = getPageClassRegistry().getPageClass(PageType.ACTION);
return Links.newBookmarkablePageLink(linkId, pageParameters, pageClass);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/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 2634a65..28fc618 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
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.adapter.ResolveState;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.adapter.version.Version;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
@@ -154,6 +155,11 @@ public interface AdapterManager extends Injectable {
* of the {@link TypedOid oid} of the recreated adapter is the same as that of the provided {@link TypedOid oid}.
* If the version differs, then a {@link ConcurrencyException} is thrown.
*
+ * <p>
+ * ALSO, even if a {@link ConcurrencyException}, then the provided {@link TypedOid oid}'s {@link Version version}
+ * will be {@link TypedOid#setVersion(org.apache.isis.core.metamodel.adapter.version.Version) set} to the current
+ * value. This allows the client to retry if they wish.
+ *
* @throws {@link ObjectNotFoundException} if the object does not exist.
*/
ObjectAdapter adapterFor(TypedOid oid, ConcurrencyChecking concurrencyChecking);
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/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 47cbee7..1c13ab6 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
@@ -43,7 +43,6 @@ import org.apache.isis.applib.value.Clob;
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.AdapterManagerAware;
-import org.apache.isis.core.metamodel.facets.actions.homepage.HomePageFacet;
import org.apache.isis.core.metamodel.layoutmetadata.json.LayoutMetadataReaderFromJson;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
http://git-wip-us.apache.org/repos/asf/isis/blob/bda2045b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
index 1d9b7fb..57e7dfc 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
@@ -141,15 +141,15 @@ public class ToDoItems {
final String ownedBy = currentUserName();
return newToDo(description, category, subcategory, ownedBy, dueBy, cost);
}
- public LocalDate default3NewToDo() {
- return new LocalDate(Clock.getTime()).plusDays(14);
- }
public Category default1NewToDo() {
return Category.Professional;
}
public Subcategory default2NewToDo() {
return Category.Professional.subcategories().get(0);
}
+ public LocalDate default3NewToDo() {
+ return clockService.now().plusDays(14);
+ }
public List<Subcategory> choices2NewToDo(
final String description, final Category category) {
return Subcategory.listFor(category);