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/01/22 17:53:57 UTC

[42/52] [abbrv] isis git commit: ISIS-970: some unit tests for @ActionAnnotationFacetFactory; fixes/improvements to the todoapp.

ISIS-970: some unit tests for @ActionAnnotationFacetFactory; fixes/improvements to the todoapp.


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

Branch: refs/heads/ISIS-970
Commit: d21123e85e1b657762270bbf763c64893f0a1551
Parents: 6de787a
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Jan 21 08:36:32 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jan 22 16:32:43 2015 +0000

----------------------------------------------------------------------
 .../services/eventbus/ActionDomainEvent.java    |   7 +-
 .../core/metamodel/facets/FacetFactory.java     |   6 +-
 .../action/ActionAnnotationFacetFactory.java    |   6 +-
 .../ActionDomainEventFacetAbstract.java         |   9 +-
 ...onInvocationFacetForDomainEventAbstract.java |   9 +-
 ...ainEventFromActionInteractionAnnotation.java |   4 +
 ...cetForPostsActionInvokedEventAnnotation.java |   3 +-
 .../ActionAnnotationFacetFactoryTest.java       | 198 ++++++++++++++++++-
 .../dom/src/main/java/dom/todo/ToDoItem.java    |  13 +-
 .../java/dom/todo/ToDoItemSubscriptions.java    |  56 ++++--
 10 files changed, 265 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
index 6321228..434831a 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/ActionDomainEvent.java
@@ -23,6 +23,7 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.util.ObjectContracts;
 
@@ -94,9 +95,13 @@ public abstract class ActionDomainEvent<S> extends AbstractInteractionEvent<S> {
     }
     //endregion
 
-
     //region > actionSemantics
+    public SemanticsOf getSemantics() {
+        return SemanticsOf.from(actionSemantics);
+    }
+
     private ActionSemantics.Of actionSemantics;
+    @Deprecated
     public ActionSemantics.Of getActionSemantics() {
         return actionSemantics;
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactory.java
index fbedb4a..0ddb5d2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetFactory.java
@@ -118,7 +118,7 @@ public interface FacetFactory {
             methodRemover.removeMethods(methods);
         }
 
-        public Properties metadataProperties(String subKey) {
+        public Properties metadataProperties(final String subKey) {
             if(metadataProperties == null) {
                 return null;
             }
@@ -187,12 +187,12 @@ public interface FacetFactory {
             methodRemover.removeMethods(methods);
         }
 
-        public Properties metadataProperties(String subKey) {
+        public Properties metadataProperties(final String subKey) {
             
             if(metadataProperties == null) {
                 return null;
             }
-            Identifier identifier = featureType.identifierFor(getCls(), getMethod());
+            final Identifier identifier = featureType.identifierFor(getCls(), getMethod());
             final String id = identifier.getMemberName();
             
             // build list of keys to search for... 

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/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 49ace9f..d453274 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
@@ -129,8 +129,9 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
             //
             // Set up ActionDomainEventFacet, which will act as the hiding/disabling/validating advisor
             //
-            final Action action = Annotations.getAnnotation(actionMethod, Action.class);
+            final PostsActionInvokedEvent postsActionInvokedEvent = Annotations.getAnnotation(actionMethod, PostsActionInvokedEvent.class);
             final ActionInteraction actionInteraction =Annotations.getAnnotation(actionMethod, ActionInteraction.class);
+            final Action action = Annotations.getAnnotation(actionMethod, Action.class);
             final Class<? extends ActionDomainEvent<?>> actionDomainEventType;
 
             final ActionDomainEventFacetAbstract actionDomainEventFacet;
@@ -147,7 +148,7 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
                 actionDomainEventFacet = new ActionDomainEventFacetForActionAnnotation(
                         actionDomainEventType, servicesInjector, getSpecificationLoader(), holder);
             } else
-            // else use default event type
+            // else use default event type (also for @PostsActionInvoked)
             {
                 actionDomainEventType = ActionDomainEvent.Default.class;
                 actionDomainEventFacet = new ActionDomainEventFacetDefault(
@@ -158,7 +159,6 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract implement
 
             // replace the current actionInvocationFacet with one that will
             // emit the appropriate domain event and then delegate onto the underlying
-            final PostsActionInvokedEvent postsActionInvokedEvent = Annotations.getAnnotation(actionMethod, PostsActionInvokedEvent.class);
 
             final ActionInvocationFacetForDomainEventAbstract actionInvocationFacet;
             // deprecated

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
index 2a1bccc..036f619 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
@@ -24,10 +24,10 @@ import org.apache.isis.applib.events.ValidityEvent;
 import org.apache.isis.applib.events.VisibilityEvent;
 import org.apache.isis.applib.services.eventbus.AbstractDomainEvent;
 import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
+import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.InteractionHelper;
 import org.apache.isis.core.metamodel.facets.SingleClassValueFacetAbstract;
-import org.apache.isis.core.metamodel.facets.collections.collection.modify.CollectionDomainEventFacet;
 import org.apache.isis.core.metamodel.interactions.ActionInvocationContext;
 import org.apache.isis.core.metamodel.interactions.UsabilityContext;
 import org.apache.isis.core.metamodel.interactions.ValidityContext;
@@ -38,6 +38,10 @@ import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 public abstract class ActionDomainEventFacetAbstract
         extends SingleClassValueFacetAbstract implements ActionDomainEventFacet {
 
+    static Class<? extends Facet> type() {
+        return ActionDomainEventFacet.class;
+    }
+
     private final InteractionHelper interactionHelper;
 
     /**
@@ -55,10 +59,11 @@ public abstract class ActionDomainEventFacetAbstract
             final FacetHolder holder,
             final ServicesInjector servicesInjector,
             final SpecificationLoader specificationLoader) {
-        super(CollectionDomainEventFacet.class, holder, eventType, specificationLoader);
+        super(type(), holder, eventType, specificationLoader);
         interactionHelper = new InteractionHelper(servicesInjector);
     }
 
+
     @Override
     public String hides(final VisibilityContext<? extends VisibilityEvent> ic) {
         if(!interactionHelper.hasEventBusService()) {

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/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 eabcf7b..0389035 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
@@ -178,7 +178,7 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
             final Command command = commandContext != null ? commandContext.getCommand() : null;
 
             // pick up existing event (saved in thread local during the validation phase)
-            final ActionDomainEvent<?> existingEvent = actionInteractionFacet.currentInteraction.get();
+            final ActionDomainEvent<?> existingEvent = ActionDomainEventFacetAbstract.currentInteraction.get();
 
             // ... post the executing event
             final ActionDomainEvent<?> event =
@@ -207,15 +207,16 @@ public abstract class ActionInvocationFacetForDomainEventAbstract
             // note that if the action invoked some other action via a wrapper then this will already have been cleared
             // out.  That isn't a problem; we only need to pass the event from validate to pre-execute, not to formally
             // "nest" the events.
-            actionInteractionFacet.currentInteraction.set(null);
+            ActionDomainEventFacetAbstract.currentInteraction.set(null);
         }
     }
 
     /**
      * Optional hook to allow the facet implementation for the deprecated {@link org.apache.isis.applib.annotation.PostsActionInvokedEvent} annotation
-     * to discard the event if of a different type.
+     * to discard the event if the domain event is of a different type (specifically if was installed by virtue of a no
+     * @{@link org.apache.isis.applib.annotation.Action} or @{@link org.apache.isis.applib.annotation.ActionInteraction} annotations.
      */
-    protected ActionDomainEvent<?> verify(ActionDomainEvent<?> event) {
+    protected ActionDomainEvent<?> verify(final ActionDomainEvent<?> event) {
         return event;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/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 703e306..5504b4c 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
@@ -27,6 +27,10 @@ import org.apache.isis.core.metamodel.runtimecontext.RuntimeContext;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
+/**
+ * @deprecated
+ */
+@Deprecated
 public class ActionInvocationFacetForDomainEventFromActionInteractionAnnotation
         extends ActionInvocationFacetForDomainEventAbstract {
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/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 898b1b7..20c1ed7 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
@@ -45,7 +45,8 @@ public class ActionInvocationFacetForPostsActionInvokedEventAnnotation
 
     @Override
     protected ActionDomainEvent<?> verify(final ActionDomainEvent<?> event) {
-        // will discard event if different type to that specified in the PostsActionInvokedEvent annotation.
+        // will discard event if different type to that specified in the PostsActionInvokedEvent annotation
+        // (that is, if the ActionDomainEventFacetDefault was installed by virtue of a no @Action or @ActionInteraction annotation)
         return event != null && eventType == event.getClass() ? event : null;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest.java
index 0969d90..abe3955 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest.java
@@ -22,18 +22,36 @@ package org.apache.isis.core.metamodel.facets.actions.action;
 import java.lang.reflect.Method;
 import java.util.UUID;
 import org.jmock.Expectations;
+import org.jmock.auto.Mock;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionInteraction;
 import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.PostsActionInvokedEvent;
 import org.apache.isis.applib.services.HasTransactionId;
+import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
+import org.apache.isis.applib.services.eventbus.ActionInteractionEvent;
+import org.apache.isis.applib.services.eventbus.ActionInvokedEvent;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
 import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionDomainEventFacet;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionDomainEventFacetDefault;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionDomainEventFacetForActionAnnotation;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionDomainEventFacetForActionInteractionAnnotation;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacet;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetForDomainEventFromActionAnnotation;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetForDomainEventFromActionInteractionAnnotation;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetForDomainEventFromDefault;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacetForPostsActionInvokedEventAnnotation;
 import org.apache.isis.core.metamodel.facets.actions.command.CommandFacet;
 import org.apache.isis.core.metamodel.facets.actions.command.CommandFacetAbstract;
 import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacetAbstract;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -41,7 +59,28 @@ import static org.junit.Assert.assertTrue;
 public class ActionAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4TestCase {
 
     ActionAnnotationFacetFactory facetFactory;
-    Method customerActionMethod;
+    Method actionMethod;
+
+    @Mock
+    ObjectSpecification mockTypeSpec;
+    @Mock
+    ObjectSpecification mockReturnTypeSpec;
+
+    void expectRemoveMethod(final Method actionMethod1) {
+        context.checking(new Expectations() {{
+            oneOf(mockMethodRemover).removeMethod(actionMethod1);
+        }});
+    }
+
+    void allowingLoadSpecificationRequestsFor(final Class<?> cls, final Class<?> returnType) {
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(cls);
+            will(returnValue(mockTypeSpec));
+
+            allowing(mockSpecificationLoaderSpi).loadSpecification(returnType);
+            will(returnValue(mockReturnTypeSpec));
+        }});
+    }
 
     @Before
     public void setUp() throws Exception {
@@ -49,7 +88,7 @@ public class ActionAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4
         facetFactory.setConfiguration(mockConfiguration);
         facetFactory.setSpecificationLookup(mockSpecificationLoaderSpi);
 
-        customerActionMethod = findMethod(Customer.class, "someAction");
+        actionMethod = findMethod(Customer.class, "someAction");
     }
 
     @After
@@ -72,7 +111,154 @@ public class ActionAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4
         }
 
         @Override
-        public void setTransactionId(UUID transactionId) {
+        public void setTransactionId(final UUID transactionId) {
+        }
+    }
+
+    public static class Invocation extends ActionAnnotationFacetFactoryTest {
+
+        @Test
+        public void withPostsActionInvokedEvent() {
+
+            class Customer {
+
+                class SomeActionInvoked extends ActionInvokedEvent<Customer> {
+                    public SomeActionInvoked(final Customer source, final Identifier identifier, final Object... arguments) {
+                        super(source, identifier, arguments);
+                    }
+                }
+
+                @PostsActionInvokedEvent(Customer.SomeActionInvoked.class)
+                public void someAction() {
+                }
+            }
+
+            // given
+            final Class<?> cls = Customer.class;
+            actionMethod = findMethod(cls, "someAction");
+
+            // expect
+            allowingLoadSpecificationRequestsFor(cls, actionMethod.getReturnType());
+            expectRemoveMethod(actionMethod);
+
+            // when
+            final ProcessMethodContext processMethodContext = new ProcessMethodContext(cls, null, null, actionMethod, mockMethodRemover, facetedMethod);
+            facetFactory.processInvocation(processMethodContext);
+
+            // then
+            final Facet domainEventFacet = facetedMethod.getFacet(ActionDomainEventFacet.class);
+            Assert.assertNotNull(domainEventFacet);
+            Assert.assertTrue(domainEventFacet instanceof ActionDomainEventFacetDefault); // this is discarded at runtime, see ActionInvocationFacetForPostsActionInvokedEventAnnotation#verify(...)
+
+            final Facet invocationFacet = facetedMethod.getFacet(ActionInvocationFacet.class);
+            Assert.assertNotNull(invocationFacet);
+            Assert.assertTrue(invocationFacet instanceof ActionInvocationFacetForPostsActionInvokedEventAnnotation);
+        }
+
+        @Test
+        public void withActionInteractionEvent() {
+
+            class Customer {
+
+                class SomeActionInvoked extends ActionInteractionEvent<Customer> {
+                    public SomeActionInvoked(final Customer source, final Identifier identifier, final Object... arguments) {
+                        super(source, identifier, arguments);
+                    }
+                }
+
+                @ActionInteraction(Customer.SomeActionInvoked.class)
+                public void someAction() {
+                }
+            }
+
+            // given
+            final Class<?> cls = Customer.class;
+            actionMethod = findMethod(cls, "someAction");
+
+            // expect
+            allowingLoadSpecificationRequestsFor(cls, actionMethod.getReturnType());
+            expectRemoveMethod(actionMethod);
+
+            // when
+            final ProcessMethodContext processMethodContext = new ProcessMethodContext(cls, null, null, actionMethod, mockMethodRemover, facetedMethod);
+            facetFactory.processInvocation(processMethodContext);
+
+            // then
+            final Facet domainEventFacet = facetedMethod.getFacet(ActionDomainEventFacet.class);
+            Assert.assertNotNull(domainEventFacet);
+            Assert.assertTrue(domainEventFacet instanceof ActionDomainEventFacetForActionInteractionAnnotation);
+
+            final Facet invocationFacet = facetedMethod.getFacet(ActionInvocationFacet.class);
+            Assert.assertNotNull(invocationFacet);
+            Assert.assertTrue(invocationFacet instanceof ActionInvocationFacetForDomainEventFromActionInteractionAnnotation);
+        }
+
+        @Test
+        public void withActionDomainEvent() {
+
+            class Customer {
+
+                class SomeActionInvoked extends ActionDomainEvent<Customer> {
+                    public SomeActionInvoked(final Customer source, final Identifier identifier, final Object... arguments) {
+                        super(source, identifier, arguments);
+                    }
+                }
+
+                @Action(domainEvent=Customer.SomeActionInvoked.class)
+                public void someAction() {
+                }
+            }
+
+            // given
+            final Class<?> cls = Customer.class;
+            actionMethod = findMethod(cls, "someAction");
+
+            // expect
+            allowingLoadSpecificationRequestsFor(cls, actionMethod.getReturnType());
+            expectRemoveMethod(actionMethod);
+
+            // when
+            final ProcessMethodContext processMethodContext = new ProcessMethodContext(cls, null, null, actionMethod, mockMethodRemover, facetedMethod);
+            facetFactory.processInvocation(processMethodContext);
+
+            // then
+            final Facet domainEventFacet = facetedMethod.getFacet(ActionDomainEventFacet.class);
+            Assert.assertNotNull(domainEventFacet);
+            Assert.assertTrue(domainEventFacet instanceof ActionDomainEventFacetForActionAnnotation);
+
+            final Facet invocationFacet = facetedMethod.getFacet(ActionInvocationFacet.class);
+            Assert.assertNotNull(invocationFacet);
+            Assert.assertTrue(invocationFacet instanceof ActionInvocationFacetForDomainEventFromActionAnnotation);
+        }
+
+        @Test
+        public void withDefaultEvent() {
+
+            class Customer {
+                public void someAction() {
+                }
+            }
+
+            // given
+            final Class<?> cls = Customer.class;
+            actionMethod = findMethod(cls, "someAction");
+
+            // expect
+            allowingLoadSpecificationRequestsFor(cls, actionMethod.getReturnType());
+            expectRemoveMethod(actionMethod);
+
+            // when
+            final ProcessMethodContext processMethodContext = new ProcessMethodContext(cls, null, null, actionMethod, mockMethodRemover, facetedMethod);
+            facetFactory.processInvocation(processMethodContext);
+
+            // then
+            final Facet domainEventFacet = facetedMethod.getFacet(ActionDomainEventFacet.class);
+            Assert.assertNotNull(domainEventFacet);
+            Assert.assertTrue(domainEventFacet instanceof ActionDomainEventFacetDefault);
+
+            final Facet invocationFacet = facetedMethod.getFacet(ActionInvocationFacet.class);
+            Assert.assertNotNull(invocationFacet);
+            Assert.assertTrue(invocationFacet instanceof ActionInvocationFacetForDomainEventFromDefault);
         }
     }
 
@@ -128,7 +314,7 @@ public class ActionAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4
 
             facetedMethod.addFacet(new ActionSemanticsFacetAbstract(actionSemantics, facetedMethod) {});
 
-            facetFactory.processCommand(new ProcessMethodContext(Customer.class, null, null, customerActionMethod, mockMethodRemover, facetedMethod));
+            facetFactory.processCommand(new ProcessMethodContext(Customer.class, null, null, actionMethod, mockMethodRemover, facetedMethod));
 
             final Facet facet = facetedMethod.getFacet(CommandFacet.class);
             assertTrue(facet instanceof CommandFacetAbstract);
@@ -143,7 +329,7 @@ public class ActionAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4
             allowingConfigurationToReturn("ignoreQueryOnly");
 
             facetedMethod.addFacet(new ActionSemanticsFacetAbstract(actionSemantics, facetedMethod) {});
-            facetFactory.processCommand(new ProcessMethodContext(Customer.class, null, null, customerActionMethod, mockMethodRemover, facetedMethod));
+            facetFactory.processCommand(new ProcessMethodContext(Customer.class, null, null, actionMethod, mockMethodRemover, facetedMethod));
 
             final Facet facet = facetedMethod.getFacet(CommandFacet.class);
             Assert.assertNull(facet);
@@ -158,7 +344,7 @@ public class ActionAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4
             allowingConfigurationToReturn("none");
 
             facetedMethod.addFacet(new ActionSemanticsFacetAbstract(actionSemantics, facetedMethod) {});
-            facetFactory.processCommand(new ProcessMethodContext(Customer.class, null, null, customerActionMethod, mockMethodRemover, facetedMethod));
+            facetFactory.processCommand(new ProcessMethodContext(Customer.class, null, null, actionMethod, mockMethodRemover, facetedMethod));
 
             final Facet facet = facetedMethod.getFacet(CommandFacet.class);
             Assert.assertNull(facet);

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
index d7c92a3..de43a9a 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItem.java
@@ -28,11 +28,13 @@ import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
-
 import javax.jdo.JDOHelper;
 import javax.jdo.annotations.IdentityType;
 import javax.jdo.annotations.VersionStrategy;
-
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Ordering;
+import org.joda.time.LocalDate;
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.NonRecoverableException;
@@ -65,11 +67,6 @@ import org.apache.isis.applib.util.ObjectContracts;
 import org.apache.isis.applib.util.TitleBuffer;
 import org.apache.isis.applib.value.Blob;
 import org.apache.isis.applib.value.Clob;
-import org.joda.time.LocalDate;
-
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Ordering;
 
 @javax.jdo.annotations.PersistenceCapable(identityType=IdentityType.DATASTORE)
 @javax.jdo.annotations.DatastoreIdentity(
@@ -372,7 +369,7 @@ public class ToDoItem implements Categorized, Comparable<ToDoItem> {
 
         // if invoked as a regular action, return this object;
         // otherwise (if invoked as bulk), return null (so go back to the list)
-        return actionInvocationContext.getInvokedOn() == InvokedOn.COLLECTION ? this: null;
+        return actionInvocationContext.getInvokedOn() == InvokedOn.OBJECT ? this: null;
     }
     // disable action dependent on state of object
     public String disableNotYetCompleted() {

http://git-wip-us.apache.org/repos/asf/isis/blob/d21123e8/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
index 176c4a5..b66b327 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
@@ -138,7 +138,10 @@ public class ToDoItemSubscriptions {
             restrictTo = Environment.DEVELOPMENT
     )
     public void subscriberBehaviour(
-            @ParameterLayout(named="Behaviour") Behaviour behaviour) {
+            @ParameterLayout(
+                    named="Behaviour"
+            )
+            final Behaviour behaviour) {
         this.behaviour = behaviour;
         container.informUser("Subscriber behaviour set to: " + behaviour);
     }
@@ -150,7 +153,23 @@ public class ToDoItemSubscriptions {
     public Behaviour getSubscriberBehaviour() {
         return behaviour;
     }
-    private void onExecutedVetoIfRequired() {
+
+
+    private void onExecutedThrowExceptionIfSet(final ActionDomainEvent<?> ev) {
+        if(ev != null && ev.getSemantics().isSafe()) {
+            return;
+        }
+        onExecutedThrowExceptionIfSet();
+    }
+    private void onExecutedThrowExceptionIfSet(final PropertyDomainEvent<?, ?> ev) {
+        onExecutedThrowExceptionIfSet();
+    }
+    private void onExecutedThrowExceptionIfSet(final CollectionDomainEvent<?, ?> ev) {
+        onExecutedThrowExceptionIfSet();
+    }
+
+
+    private void onExecutedThrowExceptionIfSet() {
         if(behaviour == Behaviour.AnyExecuteVetoWithRecoverableException) {
             throw new RecoverableException("Rejecting event (recoverable exception thrown)");
         }
@@ -168,7 +187,7 @@ public class ToDoItemSubscriptions {
     @Subscribe
     public void on(final ToDoItem.CompletedEvent ev) {
         recordEvent(ev);
-        switch(ev.getPhase()) {
+        switch(ev.getEventPhase()) {
             case HIDE:
                 break;
             case DISABLE:
@@ -190,7 +209,7 @@ public class ToDoItemSubscriptions {
     @Subscribe
     public void on(final ActionDomainEvent<?> ev) {
         recordEvent(ev);
-        switch(ev.getPhase()) {
+        switch(ev.getEventPhase()) {
             case HIDE:
                 if(getSubscriberBehaviour() == Behaviour.UpdateCostActionHide) {
                     if(ev.getIdentifier().getMemberName().equals("updateCost")) {
@@ -215,7 +234,7 @@ public class ToDoItemSubscriptions {
                 break;
             case EXECUTED:
                 LOG.info("Received ActionInteractionEvent, " + ev.getSource().toString() + ", invoked " + ev.getIdentifier().getMemberName());
-                onExecutedVetoIfRequired();
+                onExecutedThrowExceptionIfSet(ev);
                 break;
         }
     }
@@ -224,30 +243,30 @@ public class ToDoItemSubscriptions {
     @Subscribe
     public void on(PropertyDomainEvent<?,?> ev) {
         recordEvent(ev);
-        switch(ev.getPhase()) {
+        switch(ev.getEventPhase()) {
             case HIDE:
                 if(getSubscriberBehaviour() == Behaviour.DescriptionPropertyHide &&
                     ev.getIdentifier().getMemberName().equals("description")) {
-                    ev.hide();
+                    ev.veto("");
                 }
                 break;
             case DISABLE:
                 if(getSubscriberBehaviour() == Behaviour.DescriptionPropertyDisable &&
                     ev.getIdentifier().getMemberName().equals("description")) {
-                    ev.disable("ToDoItemSubscriptions says: description property disabled!");
+                    ev.veto("ToDoItemSubscriptions says: description property disabled!");
                 }
                 break;
             case VALIDATE:
                 if(getSubscriberBehaviour() == Behaviour.DescriptionPropertyInvalidate &&
                     ev.getIdentifier().getMemberName().equals("description")) {
-                    ev.disable("ToDoItemSubscriptions says: can't change description property to this value!");
+                    ev.veto("ToDoItemSubscriptions says: can't change description property to this value!");
                 }
                 break;
             case EXECUTING:
                 break;
             case EXECUTED:
                 LOG.info("Received PropertyInteractionEvent, " + ev.getSource().toString() + ", changed " + ev.getIdentifier().getMemberName() + " : " + ev.getOldValue() + " -> " + ev.getNewValue());
-                onExecutedVetoIfRequired();
+                onExecutedThrowExceptionIfSet(ev);
 
                 if(ev.getIdentifier().getMemberName().contains("description")) {
                     String newValue = (String) ev.getNewValue();
@@ -258,38 +277,38 @@ public class ToDoItemSubscriptions {
                 break;
         }
     }
-    
+
     @Programmatic
     @Subscribe
     public void on(CollectionDomainEvent<?,?> ev) {
         recordEvent(ev);
-        switch (ev.getPhase()) {
+        switch (ev.getEventPhase()) {
             case HIDE:
                 if(getSubscriberBehaviour() == Behaviour.DependenciesCollectionHide &&
                     ev.getIdentifier().getMemberName().equals("dependencies")) {
-                    ev.hide();
+                    ev.veto("");
                 }
                 if (getSubscriberBehaviour() == Behaviour.SimilarToCollectionHide &&
                     ev.getIdentifier().getMemberName().equals("similarTo")) {
-                    ev.hide();
+                    ev.veto("");
                 }
                 break;
             case DISABLE:
                 if (getSubscriberBehaviour() == Behaviour.DependenciesCollectionDisable &&
                     ev.getIdentifier().getMemberName().equals("dependencies")) {
-                    ev.disable("ToDoItemSubscriptions says: dependencies collection disabled!");
+                    ev.veto("ToDoItemSubscriptions says: dependencies collection disabled!");
                 }
                 break;
             case VALIDATE:
                 if(getSubscriberBehaviour() == Behaviour.DependenciesCollectionInvalidateAdd &&
                     ev.getIdentifier().getMemberName().equals("dependencies") &&
                     ev.getOf() == CollectionDomainEvent.Of.ADD_TO ) {
-                    ev.invalidate("ToDoItemSubscriptions says: can't add this object to dependencies collection!");
+                    ev.veto("ToDoItemSubscriptions says: can't add this object to dependencies collection!");
                 }
                 if(getSubscriberBehaviour() == Behaviour.DependenciesCollectionInvalidateRemove &&
                     ev.getIdentifier().getMemberName().equals("dependencies") &&
                     ev.getOf() == CollectionDomainEvent.Of.REMOVE_FROM ) {
-                    ev.invalidate("ToDoItemSubscriptions says: can't remove this object from dependencies collection!");
+                    ev.veto("ToDoItemSubscriptions says: can't remove this object from dependencies collection!");
                 }
                 break;
             case EXECUTING:
@@ -300,11 +319,12 @@ public class ToDoItemSubscriptions {
                 } else {
                     LOG.info("Received CollectionInteractionEvent, " + ev.getSource().toString() + ", removed from " + ev.getIdentifier().getMemberName() + " : " + ev.getValue());
                 }
-                onExecutedVetoIfRequired();
+                onExecutedThrowExceptionIfSet(ev);
                 break;
         }
 
     }
+
     //endregion
 
     //region > receivedEvents