Repository: isis
Updated Branches:
  refs/heads/master 8a9378b1f -> 0bca9b01b


ISIS-948, ISIS-947: refactoring event bus, removing special case handling of 
event bus in Isis core runtime; adding in ability to inject into request-scoped 
services and for request-scoped services to be event bus subscribers.

Some of the new reference counting logic has moved from EventBusDefault into 
EventBusService (abstract class in applib).

Also (for ISIS-947) includes enhancements to ServiceInstantiator so that can 
call toString(), equals() and hashCode() even if there is no session.

In addition:
- ToDoItemSubscriptions (for todoapp) moved to menu item, rather than 
contributed (better intent traded against slightly worse workflow during demos).


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

Branch: refs/heads/master
Commit: f90a62ec16986937ca12b21f39d1e66d7c344c1f
Parents: 8a9378b
Author: Dan Haywood <[email protected]>
Authored: Thu Nov 13 00:40:34 2014 +0000
Committer: Dan Haywood <[email protected]>
Committed: Thu Nov 13 00:40:34 2014 +0000

----------------------------------------------------------------------
 .../services/eventbus/EventBusService.java      |  75 +++++---
 .../services/ServicesInjectorDefault.java       |   1 +
 .../runtime/services/RequestScopedService.java  |  67 +++++--
 .../runtime/services/ServiceInstantiator.java   |  43 ++++-
 .../eventbus/EventBusServiceDefault.java        |  52 ++----
 .../eventbus/RequestScopedEventBus.java         | 186 +++++++++++++++++++
 .../runtime/system/session/IsisSession.java     |  18 --
 .../system/session/IsisSessionDefault.java      |  40 ----
 .../system/transaction/IsisTransaction.java     |   5 -
 .../transaction/IsisTransactionManager.java     |  38 ++--
 .../services/ServiceInstantiatorTest.java       |  22 ++-
 .../java/dom/todo/ToDoItemSubscriptions.java    |  65 +++++--
 .../integration/tests/ToDoItemIntegTest.java    |  24 +--
 13 files changed, 448 insertions(+), 188 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusService.java
----------------------------------------------------------------------
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusService.java
 
b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusService.java
index 059b91d..8325e8a 100644
--- 
a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusService.java
+++ 
b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusService.java
@@ -16,8 +16,13 @@
  */
 package org.apache.isis.applib.services.eventbus;
 
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import com.google.common.collect.MapMaker;
+import com.google.common.collect.Sets;
 import com.google.common.eventbus.EventBus;
-
 import org.apache.isis.applib.annotation.Hidden;
 import org.apache.isis.applib.annotation.Programmatic;
 
@@ -26,10 +31,15 @@ import org.apache.isis.applib.annotation.Programmatic;
  * subscribed to.
  *  
  * <p>
- * It is highly advisable that only domain services - not domain entities - 
are registered as subscribers.  
- * Domain services are guaranteed to be instantiated and resident in memory, 
whereas the same is not true
- * of domain entities.  The typical implementation of a domain service 
subscriber is to identify the impacted entities,
- * load them using a repository, and then to delegate to the event to them.
+ *      Only domain services (not domain entities or view models) should be 
registered; only they are guaranteed to be
+ *      instantiated and resident in memory.
+ * </p>
+ * <p>
+ *     It <i>is</i> possible to register request-scoped services, however they 
should register their proxy
+ *     rather than themselves.  This ensures that the actual subscribers are 
all singletons.  This implementation uses
+ *     reference counting to keep track of whether there are any concurrent 
instances of a request-scoped service
+ *     (keeps things nice and symmetrical).
+ * </p>
  */
 @Hidden
 public abstract class EventBusService {
@@ -56,34 +66,47 @@ public abstract class EventBusService {
     /**
      * @return an {@link EventBus} scoped to the current session.
      */
+    @Programmatic
     protected abstract EventBus getEventBus();
-    
-    /**
-     * Register the domain object with the service.
-     * 
-     * <p>
-     * This must be called manually, but a good technique is for the domain 
object to call
-     * this method when the service is injected into it.
-     * 
-     * <p>
-     * For example:
-     * <pre>
-     * private EventBusService eventBusService;
-     * public void injectEventBusService(final EventBusService 
eventBusService) {
-     *     this.eventBusService = eventBusService;
-     *     eventBusService.register(this);
-     * }
-     * </pre>
-     */
+
+    //region > register, unregister
+
     @Programmatic
     public void register(Object domainObject) {
-        getEventBus().register(domainObject);
+        referenceCountBySubscriber.putIfAbsent(domainObject, new 
AtomicInteger(0));
+        referenceCountBySubscriber.get(domainObject).incrementAndGet();
     }
-    
+
     @Programmatic
     public void unregister(Object domainObject) {
-        getEventBus().unregister(domainObject);
+        final AtomicInteger atomicInteger = 
referenceCountBySubscriber.get(domainObject);
+        atomicInteger.decrementAndGet();
+    }
+
+    //endregion
+
+    //region > subscribers
+
+    private final ConcurrentMap<Object, AtomicInteger> 
referenceCountBySubscriber = new MapMaker().weakKeys().makeMap();
+
+    /**
+     * Not API
+     */
+    @Programmatic
+    public Set<Object> getSubscribers() {
+
+
+
+        // only those subscribers that are "active"
+        Set<Object> subscribers = Sets.newLinkedHashSet();
+        for (Map.Entry<Object, AtomicInteger> subscriberReferenceCount : 
this.referenceCountBySubscriber.entrySet()) {
+            if(subscriberReferenceCount.getValue().get()>0) {
+                subscribers.add(subscriberReferenceCount.getKey());
+            }
+        }
+        return subscribers;
     }
+    //endregion
     
     /**
      * Post an event.

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
index 5a2b3de..dd34686 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjectorDefault.java
@@ -169,6 +169,7 @@ public class ServicesInjectorDefault implements 
ServicesInjectorSpi, Specificati
     //region > helpers
 
     private void injectServices(final Object object, final List<Object> 
services) {
+
         final Class<?> cls = object.getClass();
 
         autowireViaFields(object, services, cls);

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/services/RequestScopedService.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/RequestScopedService.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/RequestScopedService.java
index b85eb6f..c01b459 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/RequestScopedService.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/RequestScopedService.java
@@ -19,25 +19,62 @@
 
 package org.apache.isis.core.runtime.services;
 
-import com.google.common.base.Predicate;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 
 
+/**
+ * Interface in support of request-scoped domain services (is implemented by 
the Javassist proxy).
+ *
+ * <p>
+ *     Do NOT implement directly (will cause the javassist generation to 
fail).  Instead the request-scoped service
+ *     can provide a (conventional) <code>@PostConstruct</code> and 
<code>@PreDestroy</code> method.
+ * </p>
+ */
 public interface RequestScopedService {
 
-    public static final class Predicates {
-        private Predicates(){}
-        public static Predicate<Object> instanceOf() {
-            return new Predicate<Object>(){
-                @Override
-                public boolean apply(Object input) {
-                    return input instanceof RequestScopedService;
-                }
-            };
-        }
-    };
-
-    public void __isis_startRequest();
-    
+    /**
+     * Indicates to the proxy that a new request is starting, so should 
instantiate a new instance of the underlying
+     * service and bind to the thread, and inject into that service using the 
provided {@link org.apache.isis.core.metamodel.runtimecontext.ServicesInjector}.
+     *
+     * <p>
+     *     This is done before the <code>@PostConstruct</code>, see {@link 
#__isis_postConstruct()}.
+     * </p>
+     */
+    @Programmatic
+    public void __isis_startRequest(ServicesInjector injector);
+
+    /**
+     * Indicates to the proxy that <code>@PostConstruct</code> should be 
called on
+     * underlying instance for current thread.
+     *
+     * <p>
+     *     This is done after the request has started, see {@link 
#__isis_startRequest(org.apache.isis.core.metamodel.runtimecontext.ServicesInjector)}.
+     * </p>
+     */
+    @Programmatic
+    public void __isis_postConstruct();
+
+    /**
+     * Indicates to the proxy that <code>@PreDestroy</code> should be called on
+     * underlying instance for current thread.
+     *
+     * <p>
+     *     This is done prior to the request ending, see {@link 
#__isis_endRequest()}.
+     * </p>
+     */
+    @Programmatic
+    public void __isis_preDestroy();
+
+    /**
+     * Indicates to the proxy that request is ending, so should clean up and 
remove the
+     * underlying instance for current thread.
+     *
+     * <p>
+     *     This is done after the <code>@PreDestroy</code>, see {@link 
#__isis_preDestroy()}.
+     * </p>
+     */
+    @Programmatic
     public void __isis_endRequest();
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServiceInstantiator.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServiceInstantiator.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServiceInstantiator.java
index 31705db..36d5145 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServiceInstantiator.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/ServiceInstantiator.java
@@ -41,6 +41,7 @@ import 
org.apache.isis.core.commons.factory.InstanceCreationClassException;
 import org.apache.isis.core.commons.factory.InstanceCreationException;
 import org.apache.isis.core.commons.lang.ArrayExtensions;
 import org.apache.isis.core.commons.lang.MethodExtensions;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import 
org.apache.isis.core.metamodel.specloader.classsubstitutor.JavassistEnhanced;
 
 /**
@@ -131,7 +132,7 @@ public final class ServiceInstantiator {
             final T newInstance = proxySubclass.newInstance();
             final ProxyObject proxyObject = (ProxyObject) newInstance;
             proxyObject.setHandler(new MethodHandler() {
-                private ThreadLocal<T> serviceByThread = new ThreadLocal<T>();
+                private ThreadLocal<T> serviceByThread = new ThreadLocal<>();
                 
                 @Override
                 public Object invoke(final Object proxied, final Method 
proxyMethod, final Method proxiedMethod, final Object[] args) throws Throwable {
@@ -139,24 +140,58 @@ public final class ServiceInstantiator {
                     cacheMethodsIfNecessary(cls);
 
                     if(proxyMethod.getName().equals("__isis_startRequest")) {
+
                         T service = instantiate(cls);
+                        serviceByThread.set(service);
+
+                        ServicesInjector servicesInjector = (ServicesInjector) 
args[0];
+                        servicesInjector.injectServicesInto(service);
+
+                        return null;
+
+                    } else 
if(proxyMethod.getName().equals("__isis_postConstruct")) {
+
+                        final T service = serviceByThread.get();
 
                         callPostConstructIfPresent(service);
 
-                        serviceByThread.set(service);
                         return null;
-                    } else 
if(proxyMethod.getName().equals("__isis_endRequest")) {
+
+                    } else 
if(proxyMethod.getName().equals("__isis_preDestroy")) {
 
                         final T service = serviceByThread.get();
 
                         callPreDestroyIfPresent(service);
 
+                        return null;
+
+                    } else 
if(proxyMethod.getName().equals("__isis_endRequest")) {
+
                         serviceByThread.set(null);
                         return null;
+
+                    } else if(proxyMethod.getName().equals("hashCode") && 
proxyMethod.getParameterTypes().length == 0) {
+
+                        final T service = serviceByThread.get();
+                        return service != null? service.hashCode(): 
this.hashCode();
+
+                    } else if(proxyMethod.getName().equals("equals") && 
proxyMethod.getParameterTypes().length == 1 && 
proxyMethod.getParameterTypes()[0] == Object.class) {
+
+                        final T service = serviceByThread.get();
+                        return service != null? service.equals(args[0]): 
this.equals(args[0]);
+
+                    } else if(proxyMethod.getName().equals("toString") && 
proxyMethod.getParameterTypes().length == 0) {
+
+                        final T service = serviceByThread.get();
+                        return service != null? service.toString(): 
this.toString();
+
                     } else {
                         T service = serviceByThread.get();
                         if(service == null) {
-                            throw new IllegalStateException("No service found 
for thread; make sure ((RequestScopedService)service).__isis_startRequest() is 
called first");
+                            // ignore; this could potentially happen during an 
application-level init (PersistenceSessionFactory#init)
+                            // it has also happened in past when enabling 
debugging, though the
+                            // new hashCode(), equals() and toString() checks 
above should mitigate.
+                            return null;
                         }
                         final Object proxiedReturn = 
proxyMethod.invoke(service, args); 
                         return proxiedReturn;

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
index e79243b..3e5e5f9 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusServiceDefault.java
@@ -16,57 +16,33 @@
  */
 package org.apache.isis.core.runtime.services.eventbus;
 
-import java.util.Set;
-
-import com.google.common.collect.Sets;
+import javax.inject.Inject;
 import com.google.common.eventbus.EventBus;
-
+import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.eventbus.EventBusService;
-import org.apache.isis.core.runtime.system.context.IsisContext;
 
 /**
  * @deprecated - because <tt>EventBusServiceJdo</tt> is annotated as the 
default implementation.
  */
 @Deprecated
 public class EventBusServiceDefault extends EventBusService {
-    
-    private final Set<Object> objectsToRegister = Sets.newHashSet();
-    
+
+    //region > API (getEventBus)
+
+    @Programmatic
     @Override
     protected EventBus getEventBus() {
-        return IsisContext.getSession().getEventBus();
-    }
-    
-    
-    @Override
-    public void register(Object domainObject) {
-        // lazily registered
-        // (a) there may be no session initially
-        // (b) so can be unregistered at when closed
-        objectsToRegister.add(domainObject);
-    }
-    
-    @Override
-    public void unregister(Object domainObject) {
-        if(IsisContext.inSession()) {
-            getEventBus().unregister(domainObject);
-        }
-        objectsToRegister.remove(domainObject);
+        return requestScopedEventBus.getEventBus();
     }
+    //endregion
 
-    public void open() {
-        final Set<Object> objectsToRegister = this.objectsToRegister;
-        for (final Object object : objectsToRegister) {
-            getEventBus().register(object);
-        }
-    }
 
-    public void close() {
-        final Set<Object> objectsToRegister = this.objectsToRegister;
-        for (final Object object : objectsToRegister) {
-            getEventBus().unregister(object);
-        }
-    }
+    //region > injected services
+
+    @Inject
+    private RequestScopedEventBus requestScopedEventBus;
+
+    //endregion
 
 }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/RequestScopedEventBus.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/RequestScopedEventBus.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/RequestScopedEventBus.java
new file mode 100644
index 0000000..39b12ba
--- /dev/null
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/RequestScopedEventBus.java
@@ -0,0 +1,186 @@
+/**
+ *  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.runtime.services.eventbus;
+
+import java.util.List;
+import java.util.Set;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.enterprise.context.RequestScoped;
+import com.google.common.base.Throwables;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.SubscriberExceptionContext;
+import com.google.common.eventbus.SubscriberExceptionHandler;
+import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.RecoverableException;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.core.commons.exceptions.IsisApplicationException;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+
+
+/**
+ * Manages a guava {@link com.google.common.eventbus.EventBus}, scoped and 
private to a given request.
+ *
+ * <p>
+ *     This involves obtaining the set of subscribers from the (owning, 
singleton) {@link org.apache.isis.applib.services.eventbus.EventBusService 
event bus service}
+ *     and registering/unregistering them with the guava event bus at the 
appropriate time.
+ * </p>
+ */
+@DomainService
+@RequestScoped
+public class RequestScopedEventBus {
+
+    //region > startRequest, endRequest
+
+    /**
+     * Cannot do the setup of the event bus here (so this is asymmetric with 
<code>@PreDestroy</code>) because there is
+     * no guarantee of the order in which <code>@PostConstruct</code> is 
called on any request-scoped services.  We
+     * therefore let the request-scoped services register themselves with (the 
owning, singleton)
+     * {@link org.apache.isis.applib.services.eventbus.EventBusService} in 
their
+     * <code>@PostConstruct</code> and do the actual instantiation of the 
guava {@link com.google.common.eventbus.EventBus}
+     * and registering of subscribers lazily, in {@link #getEventBus()}.  This 
lifecycle method ({@link #startRequest()})
+     * is therefore a no-op.
+     *
+     * <p>
+     *     The guava {@link com.google.common.eventbus.EventBus} can however 
(and is) be torndown in the
+     *     <code>@PreDestroy</code> {@link #endRequest()} lifecycle method.
+     * </p>
+     */
+    @Programmatic
+    @PostConstruct
+    public void startRequest() {
+        // no-op
+    }
+
+    @Programmatic
+    @PreDestroy
+    public void endRequest() {
+        teardownEventBus();
+    }
+
+    //endregion
+
+    //region > (guava) event bus
+
+    /**
+     * Lazily populated in {@link #getEventBus()}.
+     */
+    private EventBus eventBus;
+
+    /**
+     * Lazily populates the event bus and captures the set of subscribers from
+     * {@link EventBusServiceDefault#getSubscribers()}}.
+     *
+     * <p>
+     *     These are torn down when the {@link #endRequest() request ends}.
+     * </p>
+     */
+    @Programmatic
+    public EventBus getEventBus() {
+        setupEventBus();
+        return eventBus;
+    }
+
+    /**
+     * Set of subscribers registered with the event bus.
+     *
+     * <p>
+     * Lazily populated in {@link #setupEventBus()}.
+     * </p>
+     */
+    private Set<Object> subscribers;
+
+    /**
+     * Populates {@link #eventBus} and {@link #subscribers}.
+     *
+     * <p>
+     *     Guava event bus will throw an exception if attempt to unsubscribe 
any subscribers that were not subscribed.
+     *     It is therefore the responsibility of this (wrapper) service to 
remember which services were registered
+     *     at the start of the request, and to unregister precisely this same 
set of services at the end.
+     * </p>
+     */
+    protected void setupEventBus() {
+        if(eventBus != null) {
+            return;
+        }
+        this.eventBus = newEventBus();
+
+        // "pulls" subscribers from the (singleton) event bus service
+        subscribers = eventBusService.getSubscribers();
+
+        for (Object subscriber : this.subscribers) {
+            eventBus.register(subscriber);
+        }
+    }
+
+    protected void teardownEventBus() {
+        if(subscribers != null) {
+            for (Object subscriber : this.subscribers) {
+                eventBus.unregister(subscriber);
+            }
+        }
+
+        this.eventBus = null;
+    }
+
+    protected EventBus newEventBus() {
+        return new EventBus(newEventBusSubscriberExceptionHandler());
+    }
+
+    protected SubscriberExceptionHandler 
newEventBusSubscriberExceptionHandler() {
+        return new SubscriberExceptionHandler(){
+            @Override
+            public void handleException(Throwable exception, 
SubscriberExceptionContext context) {
+                final List<Throwable> causalChain = 
Throwables.getCausalChain(exception);
+                for (Throwable cause : causalChain) {
+                    if(cause instanceof RecoverableException || cause 
instanceof NonRecoverableException) {
+                        
getTransactionManager().getTransaction().setAbortCause(new 
IsisApplicationException(exception));
+                        return;
+                    }
+                }
+                // otherwise simply ignore
+            }
+        };
+    }
+
+    protected IsisTransactionManager getTransactionManager() {
+        return IsisContext.getTransactionManager();
+    }
+
+    //endregion
+
+    //region > injected services
+    private EventBusServiceDefault eventBusService;
+    /**
+     * Singleton holding the list of subscribers.
+     *
+     * <p>
+     *     Must use an <code>injectXxx</code> method because Isis does not 
(currently) support field injection into
+     *     request-scoped services (the javassist proxy does not delegate on).
+     * </p>
+     */
+    @Programmatic
+    public void injectEventBusService(EventBusServiceDefault eventBusService) {
+        this.eventBusService = eventBusService;
+    }
+
+    //endregion
+
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
index a06be35..db5b7d2 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
@@ -39,15 +39,6 @@ import 
org.apache.isis.core.runtime.system.transaction.IsisTransaction;
 public interface IsisSession extends SessionScopedComponent {
 
     // //////////////////////////////////////////////////////
-    // ExecutionContextFactory
-    // //////////////////////////////////////////////////////
-
-    /**
-     * The {@link IsisSessionFactory factory} that created this session.
-     */
-    public IsisSessionFactory getSessionFactory();
-
-    // //////////////////////////////////////////////////////
     // closeAll
     // //////////////////////////////////////////////////////
 
@@ -95,15 +86,6 @@ public interface IsisSession extends SessionScopedComponent {
 
     
     // //////////////////////////////////////////////////////
-    // EventBus
-    // //////////////////////////////////////////////////////
-
-    /**
-     * Guava {@link EventBus}, scoped to this session.
-     */
-    public EventBus getEventBus();
-
-    // //////////////////////////////////////////////////////
     // Transaction (if in progress)
     // //////////////////////////////////////////////////////
 

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
index 0f20891..c74a4b8 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
@@ -21,20 +21,14 @@ package org.apache.isis.core.runtime.system.session;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
-import com.google.common.eventbus.EventBus;
-import com.google.common.eventbus.SubscriberExceptionContext;
-import com.google.common.eventbus.SubscriberExceptionHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.isis.applib.NonRecoverableException;
-import org.apache.isis.applib.RecoverableException;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.components.SessionScopedComponent;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.debug.DebugBuilder;
 import org.apache.isis.core.commons.debug.DebugString;
 import org.apache.isis.core.commons.debug.DebuggableWithTitle;
-import org.apache.isis.core.commons.exceptions.IsisApplicationException;
 import org.apache.isis.core.commons.util.ToString;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.runtime.system.DeploymentType;
@@ -71,8 +65,6 @@ public class IsisSessionDefault implements IsisSession {
     private long accessTime;
     private String debugSnapshot;
 
-    private EventBus eventBus;
-
     public IsisSessionDefault(
             final IsisSessionFactory sessionFactory,
             final AuthenticationSession authenticationSession,
@@ -102,29 +94,9 @@ public class IsisSessionDefault implements IsisSession {
 
     @Override
     public void open() {
-        this.eventBus = newEventBus();
-        
         persistenceSession.open();
     }
 
-    protected EventBus newEventBus() {
-        return new EventBus(newEventBusSubscriberExceptionHandler());
-    }
-
-    protected SubscriberExceptionHandler 
newEventBusSubscriberExceptionHandler() {
-        return new SubscriberExceptionHandler(){
-            @Override
-            public void handleException(Throwable exception, 
SubscriberExceptionContext context) {
-                if(exception instanceof RecoverableException ||
-                   exception instanceof NonRecoverableException) {
-                    getTransactionManager().getTransaction().setAbortCause(new 
IsisApplicationException(exception));
-                } else {
-                    // simply ignore
-                }
-            }
-        };
-    }
-
     /**
      * Closes session.
      */
@@ -132,8 +104,6 @@ public class IsisSessionDefault implements IsisSession {
     public void close() {
         takeSnapshot();
         getPersistenceSession().close();
-        
-        eventBus = null;
     }
 
     // //////////////////////////////////////////////////////
@@ -161,11 +131,6 @@ public class IsisSessionDefault implements IsisSession {
     // ExecutionContextFactory
     // //////////////////////////////////////////////////////
 
-    @Override
-    public IsisSessionFactory getSessionFactory() {
-        return isisSessionFactory;
-    }
-
     /**
      * Convenience method.
      */
@@ -251,11 +216,6 @@ public class IsisSessionDefault implements IsisSession {
         return getTransactionManager().getTransaction();
     }
 
-    @Override
-    public EventBus getEventBus() {
-        return eventBus;
-    }
-
     // //////////////////////////////////////////////////////
     // testSetObjectPersistor
     // //////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/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 c5171e9..aeea2db 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
@@ -75,7 +75,6 @@ import 
org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
 import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
 import org.apache.isis.core.runtime.persistence.PersistenceConstants;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.*;
-import org.apache.isis.core.runtime.services.eventbus.EventBusServiceDefault;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 
 import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
@@ -872,10 +871,6 @@ public class IsisTransaction implements 
TransactionScopedComponent {
         if(bic != null) {
             Bulk.InteractionContext.current.set(null);
         }
-        EventBusServiceDefault ebs = 
getServiceOrNull(EventBusServiceDefault.class);
-        if(ebs != null) {
-            ebs.close();
-        }
     }
 
     private void completeCommandIfConfigured() {

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
index 2d89384..0fd9308 100644
--- 
a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
+++ 
b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/IsisTransactionManager.java
@@ -40,7 +40,6 @@ import 
org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
 import 
org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
 import 
org.apache.isis.core.runtime.persistence.objectstore.transaction.TransactionalResource;
 import org.apache.isis.core.runtime.services.RequestScopedService;
-import org.apache.isis.core.runtime.services.eventbus.EventBusServiceDefault;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.session.IsisSession;
@@ -251,11 +250,10 @@ public class IsisTransactionManager implements 
SessionScopedComponent {
         if (getTransaction() == null || 
getTransaction().getState().isComplete()) {
             noneInProgress = true;
 
-            final List<Object> registeredServices = 
servicesInjector.getRegisteredServices();
 
-            startRequestOnRequestScopedServices(registeredServices);
+            startRequestOnRequestScopedServices();
             createCommandIfConfigured();
-            initOtherApplibServicesIfConfigured(registeredServices);
+            initOtherApplibServicesIfConfigured();
             
             IsisTransaction isisTransaction = createTransaction();
             transactionLevel = 0;
@@ -273,29 +271,43 @@ public class IsisTransactionManager implements 
SessionScopedComponent {
     }
 
     
-    private void initOtherApplibServicesIfConfigured(final List<Object> 
registeredServices) {
-        
-        final EventBusServiceDefault ebsd = 
getServiceOrNull(EventBusServiceDefault.class);
-        if(ebsd != null) {
-            ebsd.open();
-        }
+    private void initOtherApplibServicesIfConfigured() {
         
         final Bulk.InteractionContext bic = 
getServiceOrNull(Bulk.InteractionContext.class);
         if(bic != null) {
             Bulk.InteractionContext.current.set(bic);
         }
-        
     }
 
-    private void startRequestOnRequestScopedServices(final List<Object> 
registeredServices) {
+    private void startRequestOnRequestScopedServices() {
+
+        final List<Object> registeredServices = 
servicesInjector.getRegisteredServices();
+
+        // tell the proxy of all request-scoped services to instantiate the 
underlying
+        // services, store onto the thread-local and inject into them...
+        for (final Object service : registeredServices) {
+            if(service instanceof RequestScopedService) {
+                
((RequestScopedService)service).__isis_startRequest(servicesInjector);
+            }
+        }
+        // ... and invoke all @PostConstruct
         for (final Object service : registeredServices) {
             if(service instanceof RequestScopedService) {
-                ((RequestScopedService)service).__isis_startRequest();
+                ((RequestScopedService)service).__isis_postConstruct();
             }
         }
     }
 
     private void endRequestOnRequestScopeServices() {
+        // tell the proxy of all request-scoped services to invoke @PreDestroy
+        // (if any) on all underlying services stored on their thread-locals...
+        for (final Object service : servicesInjector.getRegisteredServices()) {
+            if(service instanceof RequestScopedService) {
+                ((RequestScopedService)service).__isis_preDestroy();
+            }
+        }
+
+        // ... and then remove those underlying services from the thread-local
         for (final Object service : servicesInjector.getRegisteredServices()) {
             if(service instanceof RequestScopedService) {
                 ((RequestScopedService)service).__isis_endRequest();

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/core/runtime/src/test/java/org/apache/isis/core/runtime/services/ServiceInstantiatorTest.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/test/java/org/apache/isis/core/runtime/services/ServiceInstantiatorTest.java
 
b/core/runtime/src/test/java/org/apache/isis/core/runtime/services/ServiceInstantiatorTest.java
index 049d2d3..ff16b30 100644
--- 
a/core/runtime/src/test/java/org/apache/isis/core/runtime/services/ServiceInstantiatorTest.java
+++ 
b/core/runtime/src/test/java/org/apache/isis/core/runtime/services/ServiceInstantiatorTest.java
@@ -19,20 +19,32 @@ package org.apache.isis.core.runtime.services;
 import java.util.concurrent.BrokenBarrierException;
 import java.util.concurrent.CyclicBarrier;
 import javax.enterprise.context.RequestScoped;
+import org.jmock.auto.Mock;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import org.apache.isis.core.commons.config.IsisConfigurationDefault;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertThat;
 
 public class ServiceInstantiatorTest {
 
+    @Rule
+    public JUnitRuleMockery2 context = 
JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES);
+
     private ServiceInstantiator serviceInstantiator;
-    
+
+    @JUnitRuleMockery2.Ignoring
+    @Mock
+    private ServicesInjector mockServiceInjector;
+
     @Before
     public void setUp() throws Exception {
+
         serviceInstantiator = new ServiceInstantiator();
         serviceInstantiator.setConfiguration(new IsisConfigurationDefault());
     }
@@ -53,7 +65,7 @@ public class ServiceInstantiatorTest {
     public void requestScoped_justOneThread() {
         AccumulatingCalculator calculator = 
serviceInstantiator.createInstance(AccumulatingCalculator.class);
         try {
-            ((RequestScopedService)calculator).__isis_startRequest();
+            
((RequestScopedService)calculator).__isis_startRequest(mockServiceInjector);
             assertThat(calculator.add(3), is(3));
             assertThat(calculator.add(4), is(7));
             assertThat(calculator.getTotal(), is(7));
@@ -88,16 +100,14 @@ public class ServiceInstantiatorTest {
             new Thread() {
                 public void run() {
                     try {
-                        
((RequestScopedService)calculator).__isis_startRequest();
+                        
((RequestScopedService)calculator).__isis_startRequest(mockServiceInjector);
                         // keep incrementing, til no more steps
                         while(steps[0]>0) {
                             try {
                                 calculator.add((j+1));
                                 totals[j] = calculator.getTotal();
                                 barrier.await();
-                            } catch (InterruptedException e) {
-                                throw new RuntimeException(e);
-                            } catch (BrokenBarrierException e) {
+                            } catch (InterruptedException | 
BrokenBarrierException e) {
                                 throw new RuntimeException(e);
                             }
                         }

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/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 9e3aa4c..d2fce51 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
@@ -20,6 +20,8 @@ package dom.todo;
 
 import java.util.EventObject;
 import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Lists;
@@ -37,6 +39,16 @@ import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
 import static com.google.common.collect.Lists.newArrayList;
 
+/**
+ * Subscribes to changes made to  the {@link dom.todo.ToDoItem} entity.
+ *
+ * <p>
+ *     (For demo purposes) the behaviour can be influenced using {@link 
#subscriberBehaviour(dom.todo.ToDoItemSubscriptions.Behaviour)}.
+ *     In particular, the subscriber can be used to hide/disable/validate 
actions, or just to perform pre- or post-execute
+ *     tasks.  This also includes being set to throw an exception during the 
execution of the action (also in effect
+ *     vetoing the change).
+ * </p>
+ */
 @DomainService
 public class ToDoItemSubscriptions {
 
@@ -44,6 +56,38 @@ public class ToDoItemSubscriptions {
     private final static org.slf4j.Logger LOG = 
org.slf4j.LoggerFactory.getLogger(ToDoItemSubscriptions.class);
     //endregion
 
+    //region > postConstruct, preDestroy
+
+    /**
+     * Registers this service with the {@link 
org.apache.isis.applib.services.eventbus.EventBusService}.
+     *
+     * <p>
+     *     Because this service is a singleton, this is called during initial 
bootstrap.
+     * </p>
+     */
+    @Programmatic
+    @PostConstruct
+    public void postConstruct() {
+        LOG.info("postConstruct: registering to event bus");
+        eventBusService.register(this);
+    }
+
+    /**
+     * Unregisters this service from the {@link 
org.apache.isis.applib.services.eventbus.EventBusService}.
+     *
+     * <p>
+     *     Because this service is a singleton, this is only done when the 
system is shutdown.
+     * </p>
+     */
+    @Programmatic
+    @PreDestroy
+    public void preDestroy() {
+        LOG.info("preDestroy: unregistering from event bus");
+        eventBusService.unregister(this);
+    }
+    //endregion
+
+
     //region > on(Event)...
 
     public static enum Behaviour {
@@ -65,6 +109,10 @@ public class ToDoItemSubscriptions {
         DependenciesCollectionInvalidateRemove,
         SimilarToCollectionHide
     }
+
+    /**
+     * The desired behaviour of this service.
+     */
     private Behaviour behaviour = Behaviour.AnyExecuteAccept;
 
     /**
@@ -73,14 +121,13 @@ public class ToDoItemSubscriptions {
     @Prototype
     @MemberOrder(name = "Prototyping", sequence = "80")
     @Named("Set subscriber behaviour")
-    @NotInServiceMenu
+    @NotContributed
     @ActionSemantics(ActionSemantics.Of.IDEMPOTENT)
-    public ToDoItem subscriberBehaviour(ToDoItem toDoItem, @Named("Behaviour") 
Behaviour behaviour) {
+    public void subscriberBehaviour(@Named("Behaviour") Behaviour behaviour) {
         this.behaviour = behaviour;
         container.informUser("Subscriber behaviour set to: " + behaviour);
-        return toDoItem;
     }
-    public Behaviour default1SubscriberBehaviour() {
+    public Behaviour default0SubscriberBehaviour() {
         return this.behaviour;
     }
 
@@ -93,7 +140,7 @@ public class ToDoItemSubscriptions {
             throw new RecoverableException("Rejecting event (recoverable 
exception thrown)");
         }
         if(behaviour == Behaviour.AnyExecuteVetoWithNonRecoverableException) {
-            throw new NonRecoverableException("Rejecting event (recoverable 
exception thrown)");
+            throw new NonRecoverableException("Rejecting event 
(non-recoverable exception thrown)");
         }
         if(behaviour == Behaviour.AnyExecuteVetoWithOtherException) {
             throw new RuntimeException("Throwing some other exception");
@@ -302,7 +349,7 @@ public class ToDoItemSubscriptions {
     @Programmatic
     public void reset() {
         receivedEvents.clear();
-        subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteAccept);
+        subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteAccept);
     }
     //endregion
 
@@ -310,12 +357,8 @@ public class ToDoItemSubscriptions {
     @javax.inject.Inject
     private DomainObjectContainer container;
 
-    @SuppressWarnings("unused")
+    @javax.inject.Inject
     private EventBusService eventBusService;
-    @Programmatic
-    public final void injectEventBusService(EventBusService eventBusService) {
-        eventBusService.register(this);
-    }
     //endregion
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/f90a62ec/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
----------------------------------------------------------------------
diff --git 
a/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
 
b/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
index ff63e8f..d95c2ee 100644
--- 
a/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
+++ 
b/example/application/todoapp/integtests/src/test/java/integration/tests/ToDoItemIntegTest.java
@@ -233,7 +233,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
             public void subscriberVetoesEventWithRecoverableException() throws 
Exception {
 
                 // given
-                toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+                
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
 
                 // then
                 expectedExceptions.expect(RecoverableException.class);
@@ -246,7 +246,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
             public void subscriberVetoesEventWithNonRecoverableException() 
throws Exception {
 
                 // given
-                toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+                
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
 
                 // then
                 expectedExceptions.expect(NonRecoverableException.class);
@@ -259,7 +259,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
             public void subscriberThrowingOtherExceptionIsIgnored() throws 
Exception {
 
                 // given
-                toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+                
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
 
                 // when
                 toDoItem.completed();
@@ -536,7 +536,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
                 public void subscriberVetoesEventWithRecoverableException() 
throws Exception {
 
                     // given
-                    toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+                    
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
 
                     // then
                     expectedExceptions.expect(RecoverableException.class);
@@ -549,7 +549,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
                 public void subscriberVetoesEventWithNonRecoverableException() 
throws Exception {
 
                     // given
-                    toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+                    
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
 
                     // then
                     expectedExceptions.expect(NonRecoverableException.class);
@@ -562,7 +562,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
                 public void subscriberThrowingOtherExceptionIsIgnored() throws 
Exception {
 
                     // given
-                    toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+                    
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
 
                     // when
                     toDoItem.add(otherToDoItem);
@@ -634,7 +634,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
                 public void subscriberVetoesEventWithRecoverableException() 
throws Exception {
 
                     // given
-                    toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+                    
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
 
                     // then
                     expectedExceptions.expect(RecoverableException.class);
@@ -647,7 +647,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
                 public void subscriberVetoesEventWithNonRecoverableException() 
throws Exception {
 
                     // given
-                    toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+                    
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
 
                     // then
                     expectedExceptions.expect(NonRecoverableException.class);
@@ -660,7 +660,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
                 public void subscriberThrowingOtherExceptionIsIgnored() throws 
Exception {
 
                     // given
-                    toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+                    
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
 
                     // when
                     toDoItem.remove(otherToDoItem);
@@ -873,7 +873,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
             public void subscriberVetoesEventWithRecoverableException() throws 
Exception {
 
                 // given
-                toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
+                
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithRecoverableException);
 
                 // then
                 expectedExceptions.expect(RecoverableException.class);
@@ -887,7 +887,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
             public void subscriberVetoesEventWithNonRecoverableException() 
throws Exception {
 
                 // given
-                toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
+                
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithNonRecoverableException);
 
                 // then
                 expectedExceptions.expect(NonRecoverableException.class);
@@ -901,7 +901,7 @@ public class ToDoItemIntegTest extends 
AbstractToDoIntegTest {
             public void subscriberThrowingOtherExceptionIsIgnored() throws 
Exception {
 
                 // given
-                toDoItemSubscriptions.subscriberBehaviour(null, 
ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
+                
toDoItemSubscriptions.subscriberBehaviour(ToDoItemSubscriptions.Behaviour.AnyExecuteVetoWithOtherException);
 
                 // when
                 toDoItem.setDescription("Buy bread and butter");

Reply via email to