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/09/03 16:23:09 UTC

[2/5] isis git commit: ISIS-1194: rationalizing RuntimeContext - introducing TransactionStateProvider

ISIS-1194: rationalizing RuntimeContext - introducing TransactionStateProvider

... cf DeploymentCategoryProvider and AuthenticationSessionProvider etc.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/fe1f75dd
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/fe1f75dd
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/fe1f75dd

Branch: refs/heads/master
Commit: fe1f75dddb7ea2bfeb3f6327863f5c3e67a59ea9
Parents: 02b0bc5
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Sep 3 14:19:58 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Sep 3 14:19:58 2015 +0100

----------------------------------------------------------------------
 .../action/ActionAnnotationFacetFactory.java    | 20 +++--
 ...onInvocationFacetForDomainEventAbstract.java | 13 ++-
 ...FacetForDomainEventFromActionAnnotation.java |  7 +-
 ...ainEventFromActionInteractionAnnotation.java |  7 +-
 ...nvocationFacetForDomainEventFromDefault.java |  7 +-
 ...cetForPostsActionInvokedEventAnnotation.java |  7 +-
 .../runtimecontext/RuntimeContext.java          | 87 +-----------------
 .../runtimecontext/RuntimeContextAbstract.java  |  1 +
 .../noruntime/RuntimeContextNoRuntime.java      | 23 +++--
 .../transactions/TransactionState.java          | 94 ++++++++++++++++++++
 .../transactions/TransactionStateProvider.java  | 26 ++++++
 .../TransactionStateProviderAbstract.java       | 30 +++++++
 .../TransactionStateProviderAware.java          | 29 ++++++
 .../internal/RuntimeContextFromSession.java     | 27 ++++--
 .../system/transaction/IsisTransaction.java     |  2 +-
 15 files changed, 262 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
index a3fa1bc..58bddba 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
@@ -96,8 +96,11 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.collectiontyperegistry.CollectionTypeRegistry;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForDeprecatedAnnotation;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProvider;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProviderAware;
 
-public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware, IsisConfigurationAware, AdapterManagerAware, RuntimeContextAware, MetaModelValidatorRefiner {
+public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware, IsisConfigurationAware, AdapterManagerAware, RuntimeContextAware, MetaModelValidatorRefiner,
+        TransactionStateProviderAware {
 
     private final MetaModelValidatorForDeprecatedAnnotation actionSemanticsValidator = new MetaModelValidatorForDeprecatedAnnotation(ActionSemantics.class);
     private final MetaModelValidatorForDeprecatedAnnotation actionInteractionValidator = new MetaModelValidatorForDeprecatedAnnotation(ActionInteraction.class);
@@ -117,6 +120,7 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
     private IsisConfiguration configuration;
     private AdapterManager adapterManager;
     private RuntimeContext runtimeContext;
+    private TransactionStateProvider transactionStateProvider;
 
     private final CollectionTypeRegistry collectionTypeRegistry = new CollectionTypeRegistry();
 
@@ -211,7 +215,8 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
                         new ActionInvocationFacetForPostsActionInvokedEventAnnotation(
                                 actionInvokedEventType, actionMethod, typeSpec, returnSpec, holder,
                                 getDeploymentCategory(), configuration, getServicesInjector(),
-                                getAuthenticationSessionProvider(), getAdapterManager(), getRuntimeContext()
+                                getAuthenticationSessionProvider(), getAdapterManager(), getRuntimeContext(),
+                                transactionStateProvider
                         ), processMethodContext);
             } else
             // deprecated (but more recently)
@@ -220,7 +225,8 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
                         new ActionInvocationFacetForDomainEventFromActionInteractionAnnotation(
                                 actionDomainEventType, actionMethod, typeSpec, returnSpec, holder,
                                 getDeploymentCategory(), configuration, getServicesInjector(),
-                                getAuthenticationSessionProvider(), getAdapterManager(), getRuntimeContext()
+                                getAuthenticationSessionProvider(), getAdapterManager(), getRuntimeContext(),
+                                transactionStateProvider
                         ), processMethodContext);
             } else
             // current
@@ -229,7 +235,7 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
                         actionDomainEventType, actionMethod, typeSpec, returnSpec, holder,
                         getDeploymentCategory(), configuration, getServicesInjector(),
                         getAuthenticationSessionProvider(),
-                        getAdapterManager(), getRuntimeContext()
+                        getAdapterManager(), getRuntimeContext(), transactionStateProvider
                 );
             } else
             // default
@@ -237,7 +243,7 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
                 actionInvocationFacet = new ActionInvocationFacetForDomainEventFromDefault(
                         actionDomainEventType, actionMethod, typeSpec, returnSpec, holder,
                         getDeploymentCategory(), configuration, getServicesInjector(), getAuthenticationSessionProvider(),
-                        getAdapterManager(), getRuntimeContext()
+                        getAdapterManager(), getRuntimeContext(), transactionStateProvider
                 );
             }
             FacetUtil.addFacet(actionInvocationFacet);
@@ -580,4 +586,8 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
         this.runtimeContext = runtimeContext;
     }
 
+    @Override
+    public void setTransactionStateProvider(final TransactionStateProvider transactionStateProvider) {
+        this.transactionStateProvider = transactionStateProvider;
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/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 880f377..f78c720 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
@@ -74,6 +74,8 @@ 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.metamodel.specloader.ReflectiveActionException;
+import org.apache.isis.core.metamodel.transactions.TransactionState;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProvider;
 
 public abstract class ActionInvocationFacetForDomainEventAbstract
         extends ActionInvocationFacetAbstract
@@ -92,6 +94,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
 
     private final ServicesInjector servicesInjector;
     private final IsisConfiguration configuration;
+    private final TransactionStateProvider transactionStateProvider;
     private final Class<? extends ActionDomainEvent<?>> eventType;
     private final DomainEventHelper domainEventHelper;
 
@@ -106,7 +109,8 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
             final ServicesInjector servicesInjector,
             final AuthenticationSessionProvider authenticationSessionProvider,
             final AdapterManager adapterManager,
-            final RuntimeContext runtimeContext) {
+            final RuntimeContext runtimeContext,
+            final TransactionStateProvider transactionStateProvider) {
         super(holder);
         this.eventType = eventType;
         this.method = method;
@@ -118,6 +122,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
         this.adapterManager = adapterManager;
         this.servicesInjector = servicesInjector;
         this.configuration = configuration;
+        this.transactionStateProvider = transactionStateProvider;
         this.domainEventHelper = new DomainEventHelper(this.servicesInjector);
 
     }
@@ -469,7 +474,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
                 throw new ReflectiveActionException("IllegalStateException thrown while executing " + method + " " + targetException.getMessage(), targetException);
             }
             if(targetException instanceof RecoverableException) {
-                if (!runtimeContext.getTransactionState().canCommit()) {
+                if (!getTransactionState().canCommit()) {
                     // something severe has happened to the underlying transaction;
                     // so escalate this exception to be non-recoverable
                     final Throwable targetExceptionCause = targetException.getCause();
@@ -532,4 +537,8 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
     public AuthenticationSession getAuthenticationSession() {
         return authenticationSessionProvider.getAuthenticationSession();
     }
+
+    public TransactionState getTransactionState() {
+        return transactionStateProvider.getTransactionState();
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionAnnotation.java
index 49267e8..7f6d614 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionAnnotation.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 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.transactions.TransactionStateProvider;
 
 public class ActionInvocationFacetForDomainEventFromActionAnnotation
         extends ActionInvocationFacetForDomainEventAbstract {
@@ -46,7 +47,9 @@ public class ActionInvocationFacetForDomainEventFromActionAnnotation
             final ServicesInjector servicesInjector,
             final AuthenticationSessionProvider authenticationSessionProvider,
             final AdapterManager adapterManager,
-            final RuntimeContext runtimeContext) {
-        super(eventType, method, onType, returnType, holder, deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext);
+            final RuntimeContext runtimeContext,
+            final TransactionStateProvider transactionStateProvider) {
+        super(eventType, method, onType, returnType, holder, deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext,
+                transactionStateProvider);
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionInteractionAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionInteractionAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionInteractionAnnotation.java
index e41186e..3bda165 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionInteractionAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromActionInteractionAnnotation.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 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.transactions.TransactionStateProvider;
 
 /**
  * @deprecated
@@ -50,7 +51,9 @@ public class ActionInvocationFacetForDomainEventFromActionInteractionAnnotation
             final ServicesInjector servicesInjector,
             final AuthenticationSessionProvider authenticationSessionProvider,
             final AdapterManager adapterManager,
-            final RuntimeContext runtimeContext) {
-        super(eventType, method, onType, returnType, holder, deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext);
+            final RuntimeContext runtimeContext,
+            final TransactionStateProvider transactionStateProvider) {
+        super(eventType, method, onType, returnType, holder, deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext,
+                transactionStateProvider);
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromDefault.java
index fd55995..395f2c7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventFromDefault.java
@@ -30,6 +30,7 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 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.transactions.TransactionStateProvider;
 
 public class ActionInvocationFacetForDomainEventFromDefault
         extends ActionInvocationFacetForDomainEventAbstract {
@@ -45,8 +46,10 @@ public class ActionInvocationFacetForDomainEventFromDefault
             final ServicesInjector servicesInjector,
             final AuthenticationSessionProvider authenticationSessionProvider,
             final AdapterManager adapterManager,
-            final RuntimeContext runtimeContext) {
+            final RuntimeContext runtimeContext,
+            final TransactionStateProvider transactionStateProvider) {
         super(eventType, method, onType, returnType, holder,
-                deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext);
+                deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext,
+                transactionStateProvider);
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForPostsActionInvokedEventAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForPostsActionInvokedEventAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForPostsActionInvokedEventAnnotation.java
index ed8f587..67ad6d0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForPostsActionInvokedEventAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForPostsActionInvokedEventAnnotation.java
@@ -30,6 +30,7 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 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.transactions.TransactionStateProvider;
 
 /**
  * @deprecated
@@ -49,9 +50,11 @@ public class ActionInvocationFacetForPostsActionInvokedEventAnnotation
             final ServicesInjector servicesInjector,
             final AuthenticationSessionProvider authenticationSessionProvider,
             final AdapterManager adapterManager,
-            final RuntimeContext runtimeContext) {
+            final RuntimeContext runtimeContext,
+            final TransactionStateProvider transactionStateProvider) {
         super(eventType, method, onType, returnType, holder,
-                deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext);
+                deploymentCategory, isisConfiguration, servicesInjector, authenticationSessionProvider, adapterManager, runtimeContext,
+                transactionStateProvider);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/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 6337b36..93ad76e 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
@@ -33,6 +33,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.deployment.DeploymentCategoryProvider;
 import org.apache.isis.core.metamodel.spec.ObjectInstantiator;
 import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProvider;
 
 /**
  * Decouples the metamodel from a runtime.
@@ -42,6 +43,8 @@ public interface RuntimeContext extends Injectable, ApplicationScopedComponent {
 
     public DeploymentCategoryProvider getDeploymentCategoryProvider();
 
+    public TransactionStateProvider getTransactionStateProvider();
+
     /**
      * A mechanism for returning the <tt>current</tt>
      * {@link AuthenticationSession}.
@@ -62,9 +65,6 @@ public interface RuntimeContext extends Injectable, ApplicationScopedComponent {
 
     public ServicesProvider getServicesProvider();
 
-    /**
-     * aka the ServicesInjector...
-     */
     public ServicesInjector getServicesInjector();
 
     public ObjectDirtier getObjectDirtier();
@@ -75,85 +75,4 @@ public interface RuntimeContext extends Injectable, ApplicationScopedComponent {
 
     public LocalizationProvider getLocalizationProvider();
 
-
-    // ///////////////////////////////////////////
-    // transaction state
-    // ///////////////////////////////////////////
-
-    public TransactionState getTransactionState();
-
-    public static enum TransactionState {
-        
-        /**
-         * No transaction exists.
-         */
-        NONE,
-        /**
-         * Started, still in progress.
-         * 
-         * <p>
-         * May flush, commit or abort.
-         */
-        IN_PROGRESS,
-        /**
-         * Started, but has hit an exception.
-         * 
-         * <p>
-         * May not flush or commit (will throw an {@link IllegalStateException}),
-         * can only abort.
-         * 
-         * <p>
-         * Similar to <tt>setRollbackOnly</tt> in EJBs.
-         */
-        MUST_ABORT,
-        /**
-         * Completed, having successfully committed.
-         * 
-         * <p>
-         * May not flush or abort or commit (will throw {@link IllegalStateException}).
-         */
-        COMMITTED,
-        /**
-         * Completed, having aborted.
-         * 
-         * <p>
-         * May not flush, commit or abort (will throw {@link IllegalStateException}).
-         */
-        ABORTED;
-
-        private TransactionState(){}
-
-        /**
-         * Whether it is valid to flush the transaction.
-         */
-        public boolean canFlush() {
-            return this == IN_PROGRESS;
-        }
-
-        /**
-         * Whether it is valid to commit the transaction.
-         */
-        public boolean canCommit() {
-            return this == IN_PROGRESS;
-        }
-
-        /**
-         * Whether it is valid to mark as aborted this transaction}.
-         */
-        public boolean canAbort() {
-            return this == IN_PROGRESS || this == MUST_ABORT;
-        }
-
-        /**
-         * Whether the 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/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
index 4741a01..0f32c96 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/runtimecontext/RuntimeContextAbstract.java
@@ -64,6 +64,7 @@ public abstract class RuntimeContextAbstract implements RuntimeContext, Specific
         getAdapterManager().injectInto(candidate);
         getAuthenticationSessionProvider().injectInto(candidate);
         getDeploymentCategoryProvider().injectInto(candidate);
+        getTransactionStateProvider().injectInto(candidate);
         getServicesInjector().injectInto(candidate);
         getDomainObjectServices().injectInto(candidate);
         getLocalizationProvider().injectInto(candidate);

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/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 3a7e10f..c0c511f 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
@@ -37,11 +37,14 @@ import org.apache.isis.core.metamodel.deployment.DeploymentCategoryProvider;
 import org.apache.isis.core.metamodel.deployment.DeploymentCategoryProviderAbstract;
 import org.apache.isis.core.metamodel.runtimecontext.RuntimeContextAbstract;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.transactions.TransactionState;
 import org.apache.isis.core.metamodel.spec.ObjectInstantiationException;
 import org.apache.isis.core.metamodel.spec.ObjectInstantiator;
 import org.apache.isis.core.metamodel.spec.ObjectInstantiatorAbstract;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProvider;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProviderAbstract;
 
 public class RuntimeContextNoRuntime extends RuntimeContextAbstract {
 
@@ -317,6 +320,16 @@ public class RuntimeContextNoRuntime extends RuntimeContextAbstract {
         };
     }
 
+    @Override
+    public TransactionStateProvider getTransactionStateProvider() {
+        return new TransactionStateProviderAbstract() {
+            @Override
+            public TransactionState getTransactionState() {
+                throw new UnsupportedOperationException("Not supported by this implementation of RuntimeContext");
+            }
+        };
+    }
+
 
     @Override
     public AuthenticationSessionProvider getAuthenticationSessionProvider() {
@@ -393,13 +406,5 @@ public class RuntimeContextNoRuntime extends RuntimeContextAbstract {
         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/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionState.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionState.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionState.java
new file mode 100644
index 0000000..e6bf13f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionState.java
@@ -0,0 +1,94 @@
+/*
+ *  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.core.metamodel.transactions;
+
+public enum TransactionState {
+
+    /**
+     * No transaction exists.
+     */
+    NONE,
+    /**
+     * Started, still in progress.
+     * <p/>
+     * <p/>
+     * May flush, commit or abort.
+     */
+    IN_PROGRESS,
+    /**
+     * Started, but has hit an exception.
+     * <p/>
+     * <p/>
+     * May not flush or commit (will throw an {@link IllegalStateException}),
+     * can only abort.
+     * <p/>
+     * <p/>
+     * Similar to <tt>setRollbackOnly</tt> in EJBs.
+     */
+    MUST_ABORT,
+    /**
+     * Completed, having successfully committed.
+     * <p/>
+     * <p/>
+     * May not flush or abort or commit (will throw {@link IllegalStateException}).
+     */
+    COMMITTED,
+    /**
+     * Completed, having aborted.
+     * <p/>
+     * <p/>
+     * May not flush, commit or abort (will throw {@link IllegalStateException}).
+     */
+    ABORTED;
+
+    private TransactionState() {
+    }
+
+    /**
+     * Whether it is valid to flush the transaction.
+     */
+    public boolean canFlush() {
+        return this == IN_PROGRESS;
+    }
+
+    /**
+     * Whether it is valid to commit the transaction.
+     */
+    public boolean canCommit() {
+        return this == IN_PROGRESS;
+    }
+
+    /**
+     * Whether it is valid to mark as aborted this transaction}.
+     */
+    public boolean canAbort() {
+        return this == IN_PROGRESS || this == MUST_ABORT;
+    }
+
+    /**
+     * Whether the 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/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProvider.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProvider.java
new file mode 100644
index 0000000..26349d0
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProvider.java
@@ -0,0 +1,26 @@
+/*
+ *  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.core.metamodel.transactions;
+
+import org.apache.isis.core.commons.components.Injectable;
+
+public interface TransactionStateProvider extends Injectable {
+    public TransactionState getTransactionState();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAbstract.java
new file mode 100644
index 0000000..2ba5a9c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAbstract.java
@@ -0,0 +1,30 @@
+/**
+ *  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.core.metamodel.transactions;
+
+public abstract class TransactionStateProviderAbstract implements
+        TransactionStateProvider {
+
+    @Override
+    public void injectInto(final Object candidate) {
+        if (TransactionStateProviderAware.class.isAssignableFrom(candidate.getClass())) {
+            final TransactionStateProviderAware cast = TransactionStateProviderAware.class.cast(candidate);
+            cast.setTransactionStateProvider(this);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAware.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAware.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAware.java
new file mode 100644
index 0000000..2cb551f
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/transactions/TransactionStateProviderAware.java
@@ -0,0 +1,29 @@
+/*
+ *  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.core.metamodel.transactions;
+
+import org.apache.isis.applib.annotation.Programmatic;
+
+public interface TransactionStateProviderAware {
+
+    @Programmatic
+    public void setTransactionStateProvider(TransactionStateProvider transactionStateProvider);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fe1f75dd/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 e8b8fa1..c082ed5 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
@@ -59,6 +59,9 @@ import org.apache.isis.core.metamodel.spec.ObjectInstantiator;
 import org.apache.isis.core.metamodel.spec.ObjectInstantiatorAbstract;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.transactions.TransactionState;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProvider;
+import org.apache.isis.core.metamodel.transactions.TransactionStateProviderAbstract;
 import org.apache.isis.core.runtime.persistence.container.DomainObjectContainerObjectChanged;
 import org.apache.isis.core.runtime.persistence.container.DomainObjectContainerResolve;
 import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -398,6 +401,21 @@ public class RuntimeContextFromSession extends RuntimeContextAbstract {
         };
     }
 
+    @Override
+    public TransactionStateProvider getTransactionStateProvider() {
+        return new TransactionStateProviderAbstract() {
+            @Override
+            public TransactionState getTransactionState() {
+                final IsisTransaction transaction = getTransactionManager().getTransaction();
+                if(transaction == null) {
+                    return TransactionState.NONE;
+                }
+                IsisTransaction.State state = transaction.getState();
+                return state.getRuntimeContextState();
+            }
+        };
+    }
+
 
     private static PersistenceSession getPersistenceSession() {
         return IsisContext.getPersistenceSession();
@@ -415,14 +433,5 @@ 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/fe1f75dd/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 2a2f75c..7ad1e64 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
@@ -87,7 +87,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.publishedobject.PublishedObjectFacet;
-import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext.TransactionState;
+import org.apache.isis.core.metamodel.transactions.TransactionState;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;