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/03/25 02:04:17 UTC

[6/9] isis git commit: ISIS-1028: rename EventBus to EventBusImplementation; EventBusAdapter to EventBusImplementationAbstract; also...

ISIS-1028: rename EventBus to EventBusImplementation; EventBusAdapter to EventBusImplementationAbstract; also...

... select the implementation by reading from "isis.services.eventbus.implementation" property (either "guava" or "axon" or a fully-qualified classname)
... improved some javadoc


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

Branch: refs/heads/master
Commit: e95494ff92d48a24a49aaa2406019ab2fc6d83ed
Parents: a62594b
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Mar 24 23:59:37 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Mar 24 23:59:37 2015 +0000

----------------------------------------------------------------------
 .../isis/applib/services/eventbus/EventBus.java | 81 -----------------
 .../eventbus/EventBusImplementation.java        | 33 +++++++
 .../services/eventbus/EventBusService.java      | 34 ++++---
 .../DefaultSubscriberExceptionHandler.java      | 82 -----------------
 .../EventBusImplementationAbstract.java         | 81 +++++++++++++++++
 .../eventbus/EventBusServiceDefault.java        | 68 ++++++++------
 .../eventbus/adapter/EventBusAdapter.java       | 23 -----
 .../adapter/EventBusAdapterForAxonSimple.java   | 95 --------------------
 .../adapter/EventBusAdapterForGuava.java        | 59 ------------
 .../EventBusImplementationForAxonSimple.java    | 92 +++++++++++++++++++
 .../adapter/EventBusImplementationForGuava.java | 61 +++++++++++++
 11 files changed, 321 insertions(+), 388 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBus.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBus.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBus.java
deleted file mode 100644
index 217d12b..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBus.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package org.apache.isis.applib.services.eventbus;
-
-
-/**
- * Common interface for all Event Bus implementations.
- * <p>
- * Currently, there are implementations based on Guava and Axon frameworks.
- * 
- */
-public interface EventBus {
-
-    /**
-     * Both singleton and request-scoped domain services can register on the event bus; this should be done in their
-     * <code>@PostConstruct</code> callback method.
-     *
-     * <p>
-     *     <b>Important:</b> Request-scoped services should register their proxy, not themselves.  This is because it is
-     *     the responsibility of the proxy to ensure that the correct underlying (thread-local) instance of the service
-     *     is delegated to.  If the actual instance were to be registered, this would cause a memory leak and all sorts
-     *     of other unexpected issues.
-     * </p>
-     *
-     * <p>
-     *     Also, request-scoped services should <i>NOT</i> unregister themselves.  This is because the
-     *     <code>@PreDestroy</code> lifecycle method is called at the end of each transaction.  The proxy needs to
-     *     remain registered on behalf for any subsequent transactions.
-     * </p>
-     *
-     * <p>For example:</p>
-     * <pre>
-     *     @RequestScoped @DomainService
-     *     public class SomeSubscribingService {
-     *
-     *         @Inject private EventBusService ebs;
-     *         @Inject private SomeSubscribingService proxy;
-     *
-     *         @PostConstruct
-     *         public void startRequest() {
-     *              // register with bus
-     *              ebs.register(proxy);
-     *         }
-     *         @PreDestroy
-     *         public void endRequest() {
-     *              //no-op
-     *         }
-     *     }
-     * </pre>
-     *
-     * <p>
-     *     The <code>@PostConstruct</code> callback is the correct place to register for both singleton and
-     *     request-scoped services.  For singleton domain services, this is done during the initial bootstrapping of
-     *     the system.  For request-scoped services, this is done for the first transaction.  In fact, because
-     *     singleton domain services are initialized <i>within a current transaction</i>, the request-scoped services
-     *     will actually be registered <i>before</i> the singleton services.  Each subsequent transaction will have the
-     *     request-scoped service re-register with the event bus, however the event bus stores its subscribers in a
-     *     set and so these re-registrations are basically a no-op.
-     * </p>
-     *
-     * @param domainService
-     */
-    void register(Object domainService);
-
-    /**
-     * Notionally allows subscribers to unregister from the event bus; however this is a no-op.
-     *
-     * <p>
-     *     It is safe for singleton services to unregister from the bus, however this is only ever called when the
-     *     app is being shutdown so there is no real effect.  For request-scoped services meanwhile that (as
-     *     explained in {@link #register(Object)}'s documentation) actually register their proxy, it would be an error
-     *     to unregister the proxy; subsequent transactions (for this thread or others) must be routed through that
-     *     proxy.
-     * </p>
-     */
-    void unregister(Object domainService);
-
-    /**
-     * Post an event.
-     */
-    void post(Object event);
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusImplementation.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusImplementation.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusImplementation.java
new file mode 100644
index 0000000..cfaa661
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/EventBusImplementation.java
@@ -0,0 +1,33 @@
+package org.apache.isis.applib.services.eventbus;
+
+
+/**
+ * Common interface for all Event Bus implementations.
+ *
+ * <p>
+ *     Defines an SPI to the {@link org.apache.isis.applib.services.eventbus.EventBusService}, to allow alternative
+ *     implementations of in-memory event bus to be used. Currently, there are implementations based on Guava and on
+ *     the Axon framework.
+ * </p>
+ */
+public interface EventBusImplementation {
+
+    /**
+     * For {@link org.apache.isis.applib.services.eventbus.EventBusService} to call on
+     * {@link org.apache.isis.applib.services.eventbus.EventBusService#register(Object)}.
+     */
+    void register(Object domainService);
+
+    /**
+     * For {@link org.apache.isis.applib.services.eventbus.EventBusService} to call on
+     * {@link org.apache.isis.applib.services.eventbus.EventBusService#unregister(Object)}.
+     */
+    void unregister(Object domainService);
+
+    /**
+     * For {@link org.apache.isis.applib.services.eventbus.EventBusService} to call on
+     * {@link org.apache.isis.applib.services.eventbus.EventBusService#post(Object)}.
+     */
+    void post(Object event);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/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 db450d3..4582a8b 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
@@ -24,10 +24,6 @@ import javax.annotation.PreDestroy;
 
 import com.google.common.collect.Sets;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.isis.applib.annotation.Hidden;
 import org.apache.isis.applib.annotation.Programmatic;
 
 /**
@@ -60,11 +56,11 @@ public abstract class EventBusService {
         @Override
         public void post(Object event) {}
         @Override
-        protected EventBus getEventBus() {
+        protected EventBusImplementation getEventBusImplementation() {
             return null;
         }
         @Override
-        protected EventBus newEventBus() { return null; }
+        protected EventBusImplementation newEventBus() { return null; }
     }
 
     public static final EventBusService NOOP = new Noop();
@@ -76,7 +72,7 @@ public abstract class EventBusService {
      * no guarantee of the order in which <code>@PostConstruct</code> is called on any request-scoped services.  We
      * therefore allow all services (singleton or request-scoped) to {@link #register(Object) register} themselves
      * with this service 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()}.
+     * {@link com.google.common.eventbus.EventBus} and registering of subscribers lazily, in {@link #getEventBusImplementation()}.
      * This lifecycle method ({@link #init()}) is therefore a no-op.
      *
      * <p>
@@ -203,7 +199,7 @@ public abstract class EventBusService {
         if(skip(event)) {
             return;
         }
-        getEventBus().post(event);
+        getEventBusImplementation().post(event);
     }
 
     //endregion
@@ -212,17 +208,17 @@ public abstract class EventBusService {
     //region > getEventBus
 
     /**
-     * Lazily populated in {@link #getEventBus()}.
+     * Lazily populated in {@link #getEventBusImplementation()}.
      */
-    protected EventBus eventBus;
+    protected EventBusImplementation eventBusImplementation;
 
     /**
      * Lazily populates the event bus for the current {@link #getSubscribers() subscribers}.
      */
     @Programmatic
-    protected EventBus getEventBus() {
+    protected EventBusImplementation getEventBusImplementation() {
         setupEventBus();
-        return eventBus;
+        return eventBusImplementation;
     }
 
     /**
@@ -235,7 +231,7 @@ public abstract class EventBusService {
     private Set<Object> registeredSubscribers;
 
     /**
-     * Populates {@link #eventBus} with the {@link #registeredSubscribers currently registered subscribers}.
+     * Populates {@link #eventBusImplementation} with the {@link #registeredSubscribers currently registered subscribers}.
      *
      * <p>
      *     Guava event bus will throw an exception if attempt to unsubscribe any subscribers that were not subscribed.
@@ -251,26 +247,26 @@ public abstract class EventBusService {
      * </p>
      */
     protected void setupEventBus() {
-        if(eventBus != null) {
+        if(eventBusImplementation != null) {
             return;
         }
-        this.eventBus = newEventBus();
+        this.eventBusImplementation = newEventBus();
 
         registeredSubscribers = getSubscribers();
 
         for (Object subscriber : this.registeredSubscribers) {
-            eventBus.register(subscriber);
+            eventBusImplementation.register(subscriber);
         }
     }
 
     protected void teardownEventBus() {
         if(registeredSubscribers != null) {
             for (Object subscriber : this.registeredSubscribers) {
-                eventBus.unregister(subscriber);
+                eventBusImplementation.unregister(subscriber);
             }
         }
 
-        this.eventBus = null;
+        this.eventBusImplementation = null;
     }
 
     //endregion
@@ -280,7 +276,7 @@ public abstract class EventBusService {
     /**
      * Mandatory hook method for subclass to instantiate an appropriately configured Guava event bus.
      */
-    protected abstract EventBus newEventBus();
+    protected abstract EventBusImplementation newEventBus();
 
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/DefaultSubscriberExceptionHandler.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/DefaultSubscriberExceptionHandler.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/DefaultSubscriberExceptionHandler.java
deleted file mode 100644
index ca4d4f2..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/DefaultSubscriberExceptionHandler.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- *  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 org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.isis.applib.services.eventbus.AbstractDomainEvent;
-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;
-
-/**
- * Default logic for handling Exceptions thrown while processing Events on an
- * {@link org.apache.isis.applib.services.eventbus.EventBusService}.
- */
-public class DefaultSubscriberExceptionHandler {
-
-    private static final Logger LOG = LoggerFactory.getLogger(DefaultSubscriberExceptionHandler.class);
-
-    // region > exception handling
-
-    public static void processException(Throwable exception,
-            Object event) {
-        if (!(event instanceof AbstractDomainEvent)) {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Ignoring exception '%s' (%s), not a subclass of AbstractDomainEvent", exception.getMessage(), exception.getClass().getName());
-            }
-            return;
-        }
-        final AbstractDomainEvent<?> interactionEvent = (AbstractDomainEvent<?>) event;
-        final AbstractDomainEvent.Phase phase = interactionEvent.getEventPhase();
-        switch (phase) {
-        case HIDE:
-            LOG.warn("Exception thrown during HIDE phase, to be safe will veto (hide) the interaction event, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
-            interactionEvent.hide();
-            break;
-        case DISABLE:
-            LOG.warn("Exception thrown during DISABLE phase, to be safe will veto (disable) the interaction event, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
-            interactionEvent.disable(exception.getMessage() != null ? exception.getMessage() : exception.getClass().getName() + " thrown.");
-            break;
-        case VALIDATE:
-            LOG.warn("Exception thrown during VALIDATE phase, to be safe will veto (invalidate) the interaction event, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
-            interactionEvent.invalidate(exception.getMessage() != null ? exception.getMessage() : exception.getClass().getName() + " thrown.");
-            break;
-        case EXECUTING:
-            LOG.warn("Exception thrown during EXECUTING phase, to be safe will abort the transaction, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
-            abortTransaction(exception);
-            break;
-        case EXECUTED:
-            LOG.warn("Exception thrown during EXECUTED phase, to be safe will abort the transaction, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
-            abortTransaction(exception);
-            break;
-        }
-    }
-
-    private static void abortTransaction(Throwable exception) {
-        getTransactionManager().getTransaction().setAbortCause(new IsisApplicationException(exception));
-        return;
-    }
-
-    protected static IsisTransactionManager getTransactionManager() {
-        return IsisContext.getTransactionManager();
-    }
-
-    // endregion
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusImplementationAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusImplementationAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusImplementationAbstract.java
new file mode 100644
index 0000000..938c51a
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/EventBusImplementationAbstract.java
@@ -0,0 +1,81 @@
+/**
+ *  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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.isis.applib.services.eventbus.AbstractDomainEvent;
+import org.apache.isis.applib.services.eventbus.EventBusImplementation;
+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;
+
+public abstract class EventBusImplementationAbstract implements EventBusImplementation {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EventBusImplementationAbstract.class);
+
+    protected static void processException(
+            final Throwable exception,
+            final Object event) {
+        if (!(event instanceof AbstractDomainEvent)) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Ignoring exception '%s' (%s), not a subclass of AbstractDomainEvent", exception.getMessage(), exception.getClass().getName());
+            }
+            return;
+        }
+
+        final AbstractDomainEvent<?> interactionEvent = (AbstractDomainEvent<?>) event;
+        final AbstractDomainEvent.Phase phase = interactionEvent.getEventPhase();
+        switch (phase) {
+        case HIDE:
+            LOG.warn("Exception thrown during HIDE phase, to be safe will veto (hide) the interaction event, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
+            interactionEvent.hide();
+            break;
+        case DISABLE:
+            LOG.warn("Exception thrown during DISABLE phase, to be safe will veto (disable) the interaction event, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
+            interactionEvent.disable(exception.getMessage() != null ? exception.getMessage() : exception.getClass().getName() + " thrown.");
+            break;
+        case VALIDATE:
+            LOG.warn("Exception thrown during VALIDATE phase, to be safe will veto (invalidate) the interaction event, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
+            interactionEvent.invalidate(exception.getMessage() != null ? exception.getMessage() : exception.getClass().getName() + " thrown.");
+            break;
+        case EXECUTING:
+            LOG.warn("Exception thrown during EXECUTING phase, to be safe will abort the transaction, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
+            abortTransaction(exception);
+            break;
+        case EXECUTED:
+            LOG.warn("Exception thrown during EXECUTED phase, to be safe will abort the transaction, msg='{}', class='{}'", exception.getMessage(), exception.getClass().getName());
+            abortTransaction(exception);
+            break;
+        }
+    }
+
+
+    // region > exception handling
+
+    private static void abortTransaction(final Throwable exception) {
+        getTransactionManager().getTransaction().setAbortCause(new IsisApplicationException(exception));
+        return;
+    }
+
+    private static IsisTransactionManager getTransactionManager() {
+        return IsisContext.getTransactionManager();
+    }
+
+    // endregion
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/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 88d0342..33b0097 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
@@ -19,13 +19,16 @@ package org.apache.isis.core.runtime.services.eventbus;
 import java.util.Map;
 import javax.annotation.PostConstruct;
 import javax.enterprise.context.RequestScoped;
+import com.google.common.base.Strings;
+import org.apache.isis.applib.NonRecoverableException;
 import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.eventbus.EventBus;
+import org.apache.isis.applib.services.eventbus.EventBusImplementation;
 import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.core.commons.lang.ClassUtil;
 import org.apache.isis.core.metamodel.facets.Annotations;
 import org.apache.isis.core.runtime.services.RequestScopedService;
-import org.apache.isis.core.runtime.services.eventbus.adapter.EventBusAdapterForAxonSimple;
-import org.apache.isis.core.runtime.services.eventbus.adapter.EventBusAdapterForGuava;
+import org.apache.isis.core.runtime.services.eventbus.adapter.EventBusImplementationForAxonSimple;
+import org.apache.isis.core.runtime.services.eventbus.adapter.EventBusImplementationForGuava;
 
 /**
  * Holds common runtime logic for EventBusService implementations.
@@ -55,7 +58,7 @@ public abstract class EventBusServiceDefault extends EventBusService {
                 throw new IllegalArgumentException("Request-scoped services must register their proxy, not themselves");
             }
             // a singleton
-            if(this.eventBus != null) {
+            if(this.eventBusImplementation != null) {
                 // ... coming too late to the party.
                 throw new IllegalStateException("Event bus has already been created; too late to register any further (singleton) subscribers");
             }
@@ -69,37 +72,44 @@ public abstract class EventBusServiceDefault extends EventBusService {
     @Programmatic
     @PostConstruct
     public void init(final Map<String, String> properties) {
-        final String implementation = properties.get("org.apache.isis.eventbus.implementation");
+        final String implementation = properties.get("isis.services.eventbus.implementation");
 
-        this.implementation =
-                "axon".equalsIgnoreCase(implementation)
-                        ? EventBusImplementation.AXON
-                        : EventBusImplementation.GUAVA;
+        if(Strings.isNullOrEmpty(implementation) || "guava".equalsIgnoreCase(implementation)) {
+            this.implementation = "guava";
+            return;
+        }
+        if("axon".equalsIgnoreCase(implementation)) {
+            this.implementation = "axon";
+        }
+        this.implementation = implementation;
     }
     //endregion
 
-    //region > newEventBus
-    enum EventBusImplementation {
-        GUAVA {
-            @Override
-            public EventBus create() {
-                return new EventBusAdapterForGuava();
-            }
-        },
-        AXON {
-            @Override
-            public EventBus create() {
-                return new EventBusAdapterForAxonSimple();
-            }
-        };
-
-        public abstract EventBus create();
-    }
-    private EventBusImplementation implementation;
+    /**
+     * Either &lt;guava&gt; or &lt;axon&gt;, or else the fully qualified class name of an
+     * implementation of {@link org.apache.isis.applib.services.eventbus.EventBusImplementation}.
+     */
+    private String implementation;
 
     @Override
-    protected org.apache.isis.applib.services.eventbus.EventBus newEventBus() {
-        return implementation.create();
+    protected org.apache.isis.applib.services.eventbus.EventBusImplementation newEventBus() {
+        if("guava".equals(implementation)) {
+            return new EventBusImplementationForGuava();
+        }
+        if("axon".equals(implementation)) {
+            return new EventBusImplementationForAxonSimple();
+        }
+
+        final Class<?> aClass = ClassUtil.forName(implementation);
+        if(EventBusImplementation.class.isAssignableFrom(aClass)) {
+            try {
+                return (EventBusImplementation) aClass.newInstance();
+            } catch (InstantiationException | IllegalAccessException e) {
+                throw new NonRecoverableException(e);
+            }
+        }
+        throw new NonRecoverableException(
+                "Could not instantiate event bus implementation '" + implementation + "'");
     }
     //endregion
 

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapter.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapter.java
deleted file mode 100644
index a29e2dd..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapter.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- *  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.adapter;
-
-import org.apache.isis.applib.services.eventbus.EventBus;
-
-public abstract class EventBusAdapter implements EventBus {
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForAxonSimple.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForAxonSimple.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForAxonSimple.java
deleted file mode 100644
index b8403f7..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForAxonSimple.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- *  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.adapter;
-
-import java.util.Map;
-
-import com.google.common.collect.Maps;
-
-import org.axonframework.domain.EventMessage;
-import org.axonframework.domain.GenericEventMessage;
-import org.axonframework.eventhandling.SimpleEventBus;
-import org.axonframework.eventhandling.annotation.AnnotationEventListenerAdapter;
-import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.core.runtime.services.eventbus.DefaultSubscriberExceptionHandler;
-
-/**
- * A wrapper for an Axon {@link org.axonframework.eventhandling.SimpleEventBus},
- * allowing arbitrary events to be posted and subscribed to.
- */
-public class EventBusAdapterForAxonSimple extends EventBusAdapter {
-
-    private static SimpleEventBus simpleEventBus = new SimpleEventBus();
-
-    private static Map<Object, AxonEventListenerAdapter> adapters = Maps.newConcurrentMap();
-
-    private static AxonEventListenerAdapter adapterFor(final Object domainService) {
-        AxonEventListenerAdapter annotationEventListenerAdapter = adapters.get(domainService);
-        if (annotationEventListenerAdapter == null) {
-            annotationEventListenerAdapter = new AxonEventListenerAdapter(domainService);
-            adapters.put(domainService, annotationEventListenerAdapter);
-        }
-        return annotationEventListenerAdapter;
-    }
-
-    @Override
-    public void register(final Object domainService) {
-        EventBusAdapterForAxonSimple.simpleEventBus.subscribe(EventBusAdapterForAxonSimple.adapterFor(domainService));
-
-    }
-
-    @Override
-    public void unregister(final Object domainService) {
-        // Seems it's needed to be a no-op (See EventBusService).
-        // AxonSimpleEventBusAdapter.simpleEventBus.unsubscribe(AxonSimpleEventBusAdapter.adapterFor(domainService));
-
-    }
-
-    /*
-     * Logic equivalent to Guava Event Bus.
-     *
-     * <p>
-     *     Despite that, event processing cannot be followed after an Exception is thrown.
-     * </p>
-     */
-    @Override
-    @Programmatic
-    public void post(final Object event) {
-        EventBusAdapterForAxonSimple.simpleEventBus.publish(GenericEventMessage.asEventMessage(event));
-    }
-
-
-    static class AxonEventListenerAdapter extends AnnotationEventListenerAdapter {
-
-        public AxonEventListenerAdapter(final Object annotatedEventListener) {
-            super(annotatedEventListener);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public void handle(@SuppressWarnings("rawtypes") final EventMessage event) {
-            try {
-                super.handle(event);
-            } catch (final Exception exception) {
-                DefaultSubscriberExceptionHandler.processException(exception, event);
-            }
-        }
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForGuava.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForGuava.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForGuava.java
deleted file mode 100644
index f8e97c9..0000000
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusAdapterForGuava.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- *  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.adapter;
-
-import com.google.common.eventbus.SubscriberExceptionContext;
-import com.google.common.eventbus.SubscriberExceptionHandler;
-import org.apache.isis.core.runtime.services.eventbus.DefaultSubscriberExceptionHandler;
-
-/**
- * A wrapper for a Guava {@link com.google.common.eventbus.EventBus},
- * allowing arbitrary events to be posted and subscribed to.
- */
-public class EventBusAdapterForGuava extends EventBusAdapter {
-
-    private static final com.google.common.eventbus.EventBus eventBus = new com.google.common.eventbus.EventBus(newEventBusSubscriberExceptionHandler());
-
-    protected static SubscriberExceptionHandler newEventBusSubscriberExceptionHandler() {
-        return new SubscriberExceptionHandler() {
-            @Override
-            public void handleException(final Throwable exception,
-                    final SubscriberExceptionContext context) {
-                final Object event = context.getEvent();
-                DefaultSubscriberExceptionHandler.processException(exception, event);
-            }
-
-        };
-    }
-
-    @Override
-    public void register(final Object domainService) {
-        eventBus.register(domainService);
-    }
-
-    @Override
-    public void unregister(final Object domainService) {
-        // Intentionally no-op.
-        // this.eventBus.unregister(domainService);
-    }
-
-    @Override
-    public void post(final Object event) {
-        EventBusAdapterForGuava.eventBus.post(event);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForAxonSimple.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForAxonSimple.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForAxonSimple.java
new file mode 100644
index 0000000..8739c0d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForAxonSimple.java
@@ -0,0 +1,92 @@
+/**
+ *  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.adapter;
+
+import java.util.Map;
+import com.google.common.collect.Maps;
+import org.axonframework.domain.EventMessage;
+import org.axonframework.domain.GenericEventMessage;
+import org.axonframework.eventhandling.SimpleEventBus;
+import org.axonframework.eventhandling.annotation.AnnotationEventListenerAdapter;
+import org.apache.isis.core.runtime.services.eventbus.EventBusImplementationAbstract;
+
+/**
+ * A wrapper for an Axon {@link org.axonframework.eventhandling.SimpleEventBus},
+ * allowing arbitrary events to be posted and subscribed to.
+ */
+public class EventBusImplementationForAxonSimple extends EventBusImplementationAbstract {
+
+    // TODO: does this need to be static?
+    private static SimpleEventBus simpleEventBus = new SimpleEventBus();
+
+    // TODO: does this need to be static?
+    private static Map<Object, AxonEventListenerAdapter> adapters = Maps.newConcurrentMap();
+
+    private static AxonEventListenerAdapter adapterFor(final Object domainService) {
+        AxonEventListenerAdapter annotationEventListenerAdapter = adapters.get(domainService);
+        if (annotationEventListenerAdapter == null) {
+            annotationEventListenerAdapter = new AxonEventListenerAdapter(domainService);
+            adapters.put(domainService, annotationEventListenerAdapter);
+        }
+        return annotationEventListenerAdapter;
+    }
+
+    @Override
+    public void register(final Object domainService) {
+        simpleEventBus.subscribe(EventBusImplementationForAxonSimple.adapterFor(domainService));
+    }
+
+    @Override
+    public void unregister(final Object domainService) {
+        // Seems it's needed to be a no-op (See EventBusService).
+        // AxonSimpleEventBusAdapter.simpleEventBus.unsubscribe(AxonSimpleEventBusAdapter.adapterFor(domainService));
+
+    }
+
+    /*
+     * Logic equivalent to Guava Event Bus.
+     *
+     * <p>
+     *     Despite that, event processing cannot be followed after an Exception is thrown.
+     * </p>
+     */
+    @Override
+    public void post(final Object event) {
+        simpleEventBus.publish(GenericEventMessage.asEventMessage(event));
+    }
+
+
+    static class AxonEventListenerAdapter extends AnnotationEventListenerAdapter {
+
+        public AxonEventListenerAdapter(final Object annotatedEventListener) {
+            super(annotatedEventListener);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void handle(@SuppressWarnings("rawtypes") final EventMessage event) {
+            try {
+                super.handle(event);
+            } catch (final Exception exception) {
+                processException(exception, event);
+            }
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e95494ff/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForGuava.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForGuava.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForGuava.java
new file mode 100644
index 0000000..6801561
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/eventbus/adapter/EventBusImplementationForGuava.java
@@ -0,0 +1,61 @@
+/**
+ *  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.adapter;
+
+import com.google.common.eventbus.SubscriberExceptionContext;
+import com.google.common.eventbus.SubscriberExceptionHandler;
+import org.apache.isis.core.runtime.services.eventbus.EventBusImplementationAbstract;
+
+/**
+ * A wrapper for a Guava {@link com.google.common.eventbus.EventBus},
+ * allowing arbitrary events to be posted and subscribed to.
+ */
+public class EventBusImplementationForGuava extends EventBusImplementationAbstract {
+
+    // TODO: does this need to be static?
+    private static final com.google.common.eventbus.EventBus eventBus = new com.google.common.eventbus.EventBus(newEventBusSubscriberExceptionHandler());
+
+    // TODO: does this need to be static?
+    protected static SubscriberExceptionHandler newEventBusSubscriberExceptionHandler() {
+        return new SubscriberExceptionHandler() {
+            @Override
+            public void handleException(final Throwable exception,
+                    final SubscriberExceptionContext context) {
+                final Object event = context.getEvent();
+                processException(exception, event);
+            }
+
+        };
+    }
+
+    @Override
+    public void register(final Object domainService) {
+        eventBus.register(domainService);
+    }
+
+    @Override
+    public void unregister(final Object domainService) {
+        // Intentionally no-op.
+        // this.eventBus.unregister(domainService);
+    }
+
+    @Override
+    public void post(final Object event) {
+        eventBus.post(event);
+    }
+
+}