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 2015/07/27 09:25:43 UTC
isis git commit: ISIS-1157: simplified design for
SAFE_AND_REQUEST_CACHEABLE.
Repository: isis
Updated Branches:
refs/heads/master 5e8764fee -> c67e372f0
ISIS-1157: simplified design for SAFE_AND_REQUEST_CACHEABLE.
Instead add the caching to ActionInvocationFacetForDomainEventAbstract. No need for a new facet, just use the value of ActionSemanticsFacet.
Also:
- introduce new #isSafeInNature() to the SemanticsOf enum (also the deprecated equivalent ActionSemantics enum), which incorporates both #SAFE and #SAFE_AND_REQUEST_CACHEABLE
- go through codebase and change any hardcoded comparisons with SemanticsOf.SAFE (also the deprecated equivalent ActionSemantics enum) to use SemanticsOf#isSafeInNature() instead
- whether an action is bookmarkable
- whether concurrency checking should be performed
- a couple of uses in Restful Objects
- deprecate old #isSafe() method, since is potentially confusing
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/c67e372f
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/c67e372f
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/c67e372f
Branch: refs/heads/master
Commit: c67e372f00e9fe6a91aff70bb1f5b6330cb9126d
Parents: 5e8764f
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Jul 27 08:17:57 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Jul 27 08:17:57 2015 +0100
----------------------------------------------------------------------
.../guides/_rg_annotations_manpage-Action.adoc | 4 +-
...rg_annotations_manpage-Action_semantics.adoc | 66 +++++++++++++++++---
.../apache/isis/applib/annotation/Action.java | 2 +-
.../isis/applib/annotation/ActionSemantics.java | 31 +++++++--
.../isis/applib/annotation/SemanticsOf.java | 27 +++++++-
.../metamodel/adapter/mgr/AdapterManager.java | 2 +-
.../CommandFacetForActionAnnotation.java | 3 +-
...onInvocationFacetForDomainEventAbstract.java | 28 +++++++--
...PublishedActionFacetForActionAnnotation.java | 3 +-
...cyFacetViaBookmarkableAnnotationFactory.java | 4 +-
.../specimpl/ObjectSpecificationAbstract.java | 2 +-
.../system/transaction/IsisTransaction.java | 2 +-
.../rendering/domainobjects/InvokeKeys.java | 1 +
.../server/resources/DomainResourceHelper.java | 6 +-
.../viewer/wicket/model/models/ActionModel.java | 6 +-
.../actionlink/ActionLinkPanelFactory.java | 3 +-
16 files changed, 151 insertions(+), 39 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action.adoc
index 2f2628b..0079b56 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action.adoc
@@ -73,9 +73,9 @@ Currently this is only supported for no-arg actions.
|whether the action is only available in prototyping mode, or whether it is available also in production mode.
|xref:rg.adoc#_rg_annotations_manpage-Action_semantics[`semantics()`]
-|`QUERY`, `IDEMPOTENT`, `NON_IDEMPOTENT` +
+|`SAFE_AND_REQUEST_CACHEABLE`, `SAFE`, `IDEMPOTENT`, `NON_IDEMPOTENT` +
(`NON_IDEMPOTENT`)
-|the action's semantics (ie whether objects are modified as the result of invoking this action, and if so whether reinvoking the action would result in no further change)
+|the action's semantics (ie whether objects are modified as the result of invoking this action, and if so whether reinvoking the action would result in no further change; if not whether the results can be cached for the remainder of the request)
|xref:rg.adoc#_rg_annotations_manpage-Action_typeOf[`typeOf()`]
|(none)
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action_semantics.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action_semantics.adoc b/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action_semantics.adoc
index 3fccf4c..d8551ae 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action_semantics.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_rg_annotations_manpage-Action_semantics.adoc
@@ -6,21 +6,52 @@
-The `semantics()` attribute describes whether the invocation is safe (as no side-effects), is idempotent (may have side-effects but always has the same post-conditions), or is neither safe nor idempotent. If the annotation is missing then the framework assumes non-idempotent.
+The `semantics()` attribute describes whether the invocation modifies state of the system, and if so whether it does so idempotently. If the action invocation does _not_ modify the state of the system, in other words is safe, then it also can beused to specify whether the results of the action can be cached automatically for the remainder of the request.
-[TIP]
-====
-The attribute was originally introduced for the xref:ug.adoc#_ug_restfulobjects-viewer[RestfulObjects viewer] in order that action invocations could be made available using either HTTP GET, PUT or POST (respectively).
+The attribute was originally introduced for the xref:ug.adoc#_ug_restfulobjects-viewer[RestfulObjects viewer] in order that action invocations could be using the appropriate `HTTP` verb (`GET`, `PUT` and `POST`).
-Since then its use has been extended into the core runtime. For example, it is now aso used for the in-built concurrency checking; the invocation of a safe action does not perform a concurrency check, whereas non-safe actions do perform a concurrency check.
-====
+The table below summarizes the semantics:
+
+Action semantics
+[cols="2,1,2,1", options="header"]
+|===
+| Semantic
+| Changes state
+| Effect of multiple calls
+| HTTP verb +
+(Restful Objects)
+
+| SAFE_AND_REQUEST_CACHEABLE
+| No
+| Will always return the same result each time invoked (within a given request scope)
+| GET
+
+| SAFE
+| No
+| Might result in different results each invocation
+| GET
+
+| IDEMPOTENT
+| Yes
+| Will make no further changes if called multiple times (eg sets a property or adds to a `Set`)
+| PUT
+
+| NON_IDEMPOTENT
+| Yes
+| Might change the state of the system each time called (eg increments a counter or adds to a `List`)
+| POST
+
+|===
+
+
+The actions' semantics are also used by the core runtime as part of the in-built concurrency checkng; invocation of a safe action (which includes request-cacheable) does _not_ perform a concurrency check, whereas non-safe actions _do_ perform a concurrency check.
For example:
[source,java]
----
public class Customer {
- @Action(semantics=SemanticsOf.SAFE)
+ @Action(semantics=SemanticsOf.SAFE_AND_REQUEST_CACHEABLE)
public CreditRating checkCredit() { ... }
@Action(semantics=SemanticsOf.IDEMPOTENT)
@@ -32,5 +63,26 @@ public class Customer {
}
----
+Actions that are safe and request-cacheable automatically use the xref:rg.adoc#_rg_services-api_manpage-QueryResultsCache[`QueryResultsCache`] service to cache the result of the method. Note though that the results of this caching will only be apparent if the action is invoked from another method using the xref:rg.adoc#_rg_services-api_manpage-WrapperFactory[`WrapperFactory`] service.
+
+Continuing the example above, imagine code that loops over a set of ``Order``s where each `Order` has an associated `Customer`. We want to check the credit rating of each `Customer` (a potentially expensive operation) but we don't want to do it more than once per `Customer`. Invoking through the `WrapperFactory` will allow us to accomplish this by exploiting the semantics of `checkCredit()` action:
+
+[source,java]
+----
+public void dispatchToCreditWorthyCustomers(final List<Order> orders) {
+ for(Order order: orders) {
+ Customer customer = order.getCustomer();
+ CreditRating creditRating = wrapperFactory.wrapSkipRules(customer).checkCredit(); // <1>
+ if(creditRating.isWorthy()) {
+ order.dispatch();
+ }
+ }
+}
+@Inject
+WrapperFactory wrapperFactory;
+----
+<1> wrap the customer to dispatch.
+
+In the above example we've used `wrapSkipRules(...)` but if we wanted to enforce any business rules associated with the `checkCredit()` method, we would have used `wrap(...)`.
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
index 5149200..b94926b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Action.java
@@ -88,7 +88,7 @@ public @interface Action {
/**
- * The action semantics, either {@link SemanticsOf#SAFE safe} (query-only),
+ * The action semantics, either {@link SemanticsOf#SAFE_AND_REQUEST_CACHEABLE cached}, {@link SemanticsOf#SAFE safe} (query-only),
* {@link SemanticsOf#IDEMPOTENT idempotent} or
* {@link SemanticsOf#NON_IDEMPOTENT non-idempotent}.
*/
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionSemantics.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionSemantics.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionSemantics.java
index c3782f7..d5e21d7 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionSemantics.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionSemantics.java
@@ -40,10 +40,15 @@ public @interface ActionSemantics {
@Deprecated
public enum Of {
/**
+ * @deprecated - see {@link SemanticsOf#SAFE_AND_REQUEST_CACHEABLE}
+ */
+ @Deprecated
+ SAFE_AND_REQUEST_CACHEABLE,
+ /**
* @deprecated - see {@link SemanticsOf#SAFE}
*/
@Deprecated
- SAFE,
+ SAFE,
/**
* @deprecated - see {@link SemanticsOf#IDEMPOTENT}
*/
@@ -73,7 +78,7 @@ public @interface ActionSemantics {
}
/**
- * {@link #SAFE} is idempotent in nature, as well as, obviously, {@link #IDEMPOTENT}.
+ * Any of {@link #SAFE}, {@link #SAFE_AND_REQUEST_CACHEABLE} or (obviously) {@link #IDEMPOTENT}.
*
* @deprecated - see {@link SemanticsOf#isIdempotentInNature()}
*/
@@ -83,11 +88,29 @@ public @interface ActionSemantics {
}
/**
- * @deprecated - see {@link SemanticsOf#isSafe()}.
+ * Either of {@link #SAFE} or {@link #SAFE_AND_REQUEST_CACHEABLE}.
+ *
+ * @deprecated - see {@link SemanticsOf#isSafeInNature()}.
+ */
+ @Deprecated
+ public boolean isSafeInNature() {
+ return SemanticsOf.from(this).isSafeInNature();
+ }
+
+ /**
+ * @deprecated - see {@link #isSafeInNature()} (avoid any ambiguity)
*/
@Deprecated
public boolean isSafe() {
- return SemanticsOf.from(this).isSafe();
+ return isSafeInNature();
+ }
+
+ /**
+ * @deprecated - see {@link SemanticsOf#isSafeInNature()}.
+ */
+ @Deprecated
+ public boolean isSafeAndRequestCacheable() {
+ return SemanticsOf.from(this).isSafeAndRequestCacheable();
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/applib/src/main/java/org/apache/isis/applib/annotation/SemanticsOf.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/SemanticsOf.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/SemanticsOf.java
index fe05ab2..5cbe820 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/SemanticsOf.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/SemanticsOf.java
@@ -23,6 +23,10 @@ import org.apache.isis.applib.util.Enums;
public enum SemanticsOf {
/**
+ * Safe, with no side effects, and caching the returned value when invoked multiple times in the same request.
+ */
+ SAFE_AND_REQUEST_CACHEABLE,
+ /**
* Safe, with no side-effects.
*
* <p>
@@ -53,19 +57,35 @@ public enum SemanticsOf {
}
/**
- * {@link #SAFE} is idempotent in nature, as well as, obviously, {@link #IDEMPOTENT}.
+ * Any of {@link #SAFE}, {@link #SAFE_AND_REQUEST_CACHEABLE} or (obviously) {@link #IDEMPOTENT}.
*/
public boolean isIdempotentInNature() {
- return this == SAFE || this == IDEMPOTENT;
+ return isSafeInNature() || this == IDEMPOTENT;
+ }
+
+ /**
+ * Either of {@link #SAFE} or {@link #SAFE_AND_REQUEST_CACHEABLE}.
+ */
+ public boolean isSafeInNature() {
+ return isSafeAndRequestCacheable() || this == SAFE;
}
+ /**
+ * @deprecated - use {@link #isSafeInNature()} instead (avoid any ambiguity).
+ */
+ @Deprecated
public boolean isSafe() {
- return this == SAFE;
+ return isSafeInNature();
+ }
+
+ public boolean isSafeAndRequestCacheable() {
+ return this == SAFE_AND_REQUEST_CACHEABLE;
}
@Deprecated
public static ActionSemantics.Of from(final SemanticsOf semantics) {
if(semantics == null) return null;
+ if(semantics == SAFE_AND_REQUEST_CACHEABLE) return ActionSemantics.Of.SAFE_AND_REQUEST_CACHEABLE;
if(semantics == SAFE) return ActionSemantics.Of.SAFE;
if(semantics == IDEMPOTENT) return ActionSemantics.Of.IDEMPOTENT;
if(semantics == NON_IDEMPOTENT) return ActionSemantics.Of.NON_IDEMPOTENT;
@@ -76,6 +96,7 @@ public enum SemanticsOf {
@Deprecated
public static SemanticsOf from(final ActionSemantics.Of semantics) {
if(semantics == null) return null;
+ if(semantics == ActionSemantics.Of.SAFE_AND_REQUEST_CACHEABLE) return SAFE_AND_REQUEST_CACHEABLE;
if(semantics == ActionSemantics.Of.SAFE) return SAFE;
if(semantics == ActionSemantics.Of.IDEMPOTENT) return IDEMPOTENT;
if(semantics == ActionSemantics.Of.NON_IDEMPOTENT) return NON_IDEMPOTENT;
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/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 50ba736..49821cd 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
@@ -81,7 +81,7 @@ public interface AdapterManager extends Injectable {
}
public static ConcurrencyChecking concurrencyCheckingFor(ActionSemantics.Of actionSemantics) {
- return actionSemantics == ActionSemantics.Of.SAFE
+ return actionSemantics.isSafeInNature()
? ConcurrencyChecking.NO_CHECK
: ConcurrencyChecking.CHECK;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
index 3777d1d..66c309b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/command/CommandFacetForActionAnnotation.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.metamodel.facets.actions.action.command;
import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.Command.ExecuteIn;
import org.apache.isis.applib.annotation.Command.Persistence;
import org.apache.isis.applib.annotation.CommandExecuteIn;
@@ -56,7 +55,7 @@ public class CommandFacetForActionAnnotation extends CommandFacetAbstract {
if(actionSemanticsFacet == null) {
throw new IllegalStateException("Require ActionSemanticsFacet in order to process");
}
- if(actionSemanticsFacet.value() == ActionSemantics.Of.SAFE) {
+ if(actionSemanticsFacet.value().isSafeInNature()) {
return null;
}
// else fall through
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index df0c123..679f695 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.Callable;
import com.google.common.base.Strings;
@@ -44,6 +45,7 @@ import org.apache.isis.applib.services.command.CommandContext;
import org.apache.isis.applib.services.command.spi.CommandService;
import org.apache.isis.applib.services.eventbus.AbstractDomainEvent;
import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
+import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
import org.apache.isis.core.commons.exceptions.IsisException;
import org.apache.isis.core.commons.lang.ThrowableExtensions;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -56,6 +58,7 @@ import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.facets.actions.bulk.BulkFacet;
import org.apache.isis.core.metamodel.facets.actions.command.CommandFacet;
import org.apache.isis.core.metamodel.facets.actions.publish.PublishedActionFacet;
+import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacet;
import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
@@ -232,6 +235,8 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
try {
+
+
final Object[] executionParameters = new Object[arguments.length];
for (int i = 0; i < arguments.length; i++) {
executionParameters[i] = unwrap(arguments[i]);
@@ -257,8 +262,6 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
bulkInteractionContext.setInvokedAs(Bulk.InteractionContext.InvokedAs.REGULAR);
actionInvocationContext.setDomainObjects(Collections.singletonList(targetPojo));
}
-
-
}
if(command != null && command.getExecutor() == Command.Executor.USER && owningAction != null) {
@@ -314,8 +317,8 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
// deal with background commands
if( command != null &&
- command.getExecutor() == Command.Executor.USER &&
- command.getExecuteIn() == org.apache.isis.applib.annotation.Command.ExecuteIn.BACKGROUND) {
+ command.getExecutor() == Command.Executor.USER &&
+ command.getExecuteIn() == org.apache.isis.applib.annotation.Command.ExecuteIn.BACKGROUND) {
// persist command so can be this command can be in the 'background'
final CommandService commandService = getServicesInjector().lookupService(CommandService.class);
@@ -333,12 +336,25 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
// otherwise, go ahead and execute action in the 'foreground'
-
if(command != null) {
command.setStartedAt(Clock.getTimeAsJavaSqlTimestamp());
}
- Object result = method.invoke(targetPojo, executionParameters);
+ final ActionSemanticsFacet semanticsFacet = getFacetHolder().getFacet(ActionSemanticsFacet.class);
+ final boolean cacheable = semanticsFacet != null && semanticsFacet.value().isSafeAndRequestCacheable();
+
+ Object result;
+ if(cacheable) {
+ final QueryResultsCache queryResultsCache = getServicesInjector().lookupService(QueryResultsCache.class);
+ result = queryResultsCache.execute(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ return method.invoke(targetPojo, executionParameters);
+ }
+ }, targetPojo.getClass(), method.getName(), executionParameters);
+ } else {
+ result = method.invoke(targetPojo, executionParameters);
+ }
if (LOG.isDebugEnabled()) {
LOG.debug(" action result " + result);
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/publishing/PublishedActionFacetForActionAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/publishing/PublishedActionFacetForActionAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/publishing/PublishedActionFacetForActionAnnotation.java
index d0c09cd..13809a2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/publishing/PublishedActionFacetForActionAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/publishing/PublishedActionFacetForActionAnnotation.java
@@ -20,7 +20,6 @@
package org.apache.isis.core.metamodel.facets.actions.action.publishing;
import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.Publishing;
import org.apache.isis.applib.annotation.PublishingPayloadFactoryForAction;
import org.apache.isis.core.commons.config.IsisConfiguration;
@@ -51,7 +50,7 @@ public class PublishedActionFacetForActionAnnotation extends PublishedActionFace
throw new IllegalStateException("Require ActionSemanticsFacet in order to process");
}
- if(actionSemanticsFacet.value() == ActionSemantics.Of.SAFE) {
+ if(actionSemanticsFacet.value().isSafeInNature()) {
return null;
}
// else fall through
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/bookmarkpolicy/bookmarkable/BookmarkPolicyFacetViaBookmarkableAnnotationFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/bookmarkpolicy/bookmarkable/BookmarkPolicyFacetViaBookmarkableAnnotationFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/bookmarkpolicy/bookmarkable/BookmarkPolicyFacetViaBookmarkableAnnotationFactory.java
index cbedd11..e37473b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/bookmarkpolicy/bookmarkable/BookmarkPolicyFacetViaBookmarkableAnnotationFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/bookmarkpolicy/bookmarkable/BookmarkPolicyFacetViaBookmarkableAnnotationFactory.java
@@ -20,7 +20,7 @@
package org.apache.isis.core.metamodel.facets.object.bookmarkpolicy.bookmarkable;
import java.util.List;
-import org.apache.isis.applib.annotation.ActionSemantics.Of;
+
import org.apache.isis.applib.annotation.BookmarkPolicy;
import org.apache.isis.applib.annotation.Bookmarkable;
import org.apache.isis.core.commons.config.IsisConfiguration;
@@ -90,7 +90,7 @@ public class BookmarkPolicyFacetViaBookmarkableAnnotationFactory extends FacetFa
continue;
}
final ActionSemanticsFacet semanticsFacet = objectAction.getFacet(ActionSemanticsFacet.class);
- if(semanticsFacet == null || semanticsFacet.isNoop() || semanticsFacet.value() != Of.SAFE) {
+ if(semanticsFacet == null || semanticsFacet.isNoop() || !semanticsFacet.value().isSafeInNature()) {
validationFailures.add(
"%s: action is bookmarkable but action semantics are not explicitly indicated as being safe. " +
"Either add @Action(semantics=SemanticsOf.SAFE), or remove @ActionLayout(bookmarking=...).",
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index 040de6b..13e78d9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -976,7 +976,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
if(!(serviceAction instanceof ObjectActionImpl)) {
continue;
}
- if(!serviceAction.getSemantics().isSafe()) {
+ if(!serviceAction.getSemantics().isSafeInNature()) {
continue;
}
contributedActions.add((ObjectActionImpl) serviceAction);
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/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 8464d84..b07a00c 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
@@ -865,7 +865,7 @@ public class IsisTransaction implements TransactionScopedComponent {
// are all safe?
for (ActionDomainEvent<?> event : events) {
- if(!event.getActionSemantics().isSafe()) {
+ if(!event.getActionSemantics().isSafeInNature()) {
// found at least one non-safe action, so all bets are off.
return;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java
index bf116e9..760c87b 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/InvokeKeys.java
@@ -26,6 +26,7 @@ public final class InvokeKeys {
private final static EnumMap<ActionSemantics.Of, String> map = new EnumMap<ActionSemantics.Of, String>(ActionSemantics.Of.class);
static {
+ map.put(ActionSemantics.Of.SAFE_AND_REQUEST_CACHEABLE, "invokeQueryOnly");
map.put(ActionSemantics.Of.SAFE, "invokeQueryOnly");
map.put(ActionSemantics.Of.IDEMPOTENT, "invokeIdempotent");
map.put(ActionSemantics.Of.NON_IDEMPOTENT, "invoke");
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
index 7ef878d..57f77fc 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/DomainResourceHelper.java
@@ -248,7 +248,7 @@ public class DomainResourceHelper {
* of the result of that action.
*
* <p>
- * The action must have {@link org.apache.isis.applib.annotation.ActionSemantics.Of#SAFE safe} semantics
+ * The action must have {@link ActionSemantics.Of#isSafeInNature()} safe/request-cacheable} semantics
* otherwise an error response is thrown.
* </p>
*/
@@ -259,8 +259,8 @@ public class DomainResourceHelper {
final ObjectAction action = accessHelper.getObjectActionThatIsVisibleForIntent(actionId, ObjectAdapterAccessHelper.Intent.MUTATE);
final ActionSemantics.Of actionSemantics = action.getSemantics();
- if (actionSemantics != ActionSemantics.Of.SAFE) {
- throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.METHOD_NOT_ALLOWED, "Method not allowed; action '%s' is not query only", action.getId());
+ if (! actionSemantics.isSafeInNature()) {
+ throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.METHOD_NOT_ALLOWED, "Method not allowed; action '%s' does not have safe semantics", action.getId());
}
return invokeActionUsingAdapters(action, arguments, ActionResultReprRenderer.SelfLink.INCLUDED);
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index ee5e341..96c3bb5 100644
--- a/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/core/viewer-wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -28,10 +28,12 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
import org.apache.wicket.request.http.handler.RedirectRequestHandler;
@@ -41,9 +43,9 @@ import org.apache.wicket.util.resource.AbstractResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.apache.wicket.util.resource.StringResourceStream;
+
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.BookmarkPolicy;
import org.apache.isis.applib.annotation.Where;
import org.apache.isis.applib.value.Blob;
@@ -518,7 +520,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
public boolean isBookmarkable() {
final ObjectAction action = getActionMemento().getAction();
final BookmarkPolicyFacet bookmarkPolicy = action.getFacet(BookmarkPolicyFacet.class);
- final boolean safeSemantics = action.getSemantics() == ActionSemantics.Of.SAFE;
+ final boolean safeSemantics = action.getSemantics().isSafeInNature();
return bookmarkPolicy.value() == BookmarkPolicy.AS_ROOT && safeSemantics;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/c67e372f/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
index 29229e8..f36ac36 100644
--- a/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
+++ b/core/viewer-wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionlink/ActionLinkPanelFactory.java
@@ -21,7 +21,6 @@ package org.apache.isis.viewer.wicket.ui.components.actionlink;
import org.apache.wicket.Component;
import org.apache.wicket.model.IModel;
-import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.viewer.wicket.model.models.ActionModel;
@@ -47,7 +46,7 @@ public class ActionLinkPanelFactory extends ComponentFactoryAbstract {
}
final ActionModel actionModel = (ActionModel) model;
final ActionSemantics.Of semantics = actionModel.getActionMemento().getAction().getSemantics();
- return ApplicationAdvice.appliesIf(semantics == ActionSemantics.Of.SAFE);
+ return ApplicationAdvice.appliesIf(semantics.isSafeInNature());
}
@Override