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 2013/02/26 00:28:30 UTC

[8/24] git commit: ISIS-350: making raised messages persistent across interactions.

ISIS-350: making raised messages persistent across interactions.

* ... by associating MessageBroker with AuthenticationSession rather than IsisTransaction
  (this means in effect moving it from core-runtime to core-metamodel)

also:
* got rid of the hacky thread local for application errors (in Wicket viewer),
  and instead have extended MessageBroker to hold the app error along with the info and warning messages.
* got rid of unnecessary abortTran calls in wicket's ActionPanel
* added missing logging bootstrapping for wicket viewer.


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

Branch: refs/heads/dan/ISIS-233-ro
Commit: 70111da9b6b3d4d4bd980f23895c62eed51b0208
Parents: eef7356
Author: Dan Haywood <da...@apache.org>
Authored: Fri Feb 22 18:08:55 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Feb 22 18:08:55 2013 +0000

----------------------------------------------------------------------
 .../wicket/viewer/IsisWicketApplication.java       |   10 +++
 .../integration/wicket/WebRequestCycleForIsis.java |   17 +++--
 .../wicket/ui/components/actions/ActionPanel.java  |   28 ++++-----
 .../isis/viewer/wicket/ui/pages/PageAbstract.java  |   26 +++++----
 .../apache/isis/applib/ApplicationException.java   |   11 +---
 .../commons/authentication/AnonymousSession.java   |    2 +
 .../authentication/AuthenticationSession.java      |   12 ++++
 .../AuthenticationSessionAbstract.java             |   15 +++++
 .../core/commons/authentication/MessageBroker.java |   44 +++++++++++++++
 .../core/runtime/system/context/IsisContext.java   |    2 +-
 .../system/transaction/IsisTransaction.java        |   13 +++--
 .../system/transaction/IsisTransactionManager.java |   15 ++---
 .../runtime/system/transaction/MessageBroker.java  |   22 ++------
 .../system/transaction/MessageBrokerDefault.java   |   38 +++++++++++++
 .../PersistenceSessionObjectStoreTest.java         |    7 ++
 ...StoreTransactionManager_EndTransactionTest.java |    9 ++-
 ...oreTransactionManager_StartTransactionTest.java |   19 ++++++-
 .../dom/src/main/java/dom/todo/ToDoItems.java      |    2 +-
 .../src/main/webapp/WEB-INF/logging.properties     |    2 -
 19 files changed, 211 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
index d75fee7..f62e71d 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/IsisWicketApplication.java
@@ -58,6 +58,7 @@ import org.apache.isis.core.commons.resource.ResourceStreamSourceContextLoaderCl
 import org.apache.isis.core.commons.resource.ResourceStreamSourceCurrentClassClassPath;
 import org.apache.isis.core.commons.resource.ResourceStreamSourceFileSystem;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.logging.IsisLoggingConfigurer;
 import org.apache.isis.core.runtime.runner.IsisInjectModule;
 import org.apache.isis.core.runtime.system.DeploymentType;
 import org.apache.isis.core.runtime.system.IsisSystem;
@@ -128,8 +129,11 @@ import org.apache.isis.viewer.wicket.viewer.integration.wicket.WebRequestCycleFo
 public class IsisWicketApplication extends AuthenticatedWebApplication implements ComponentFactoryRegistryAccessor, PageClassRegistryAccessor, AuthenticationSessionProvider, BookmarkedPagesModelProvider {
 
     private static final long serialVersionUID = 1L;
+    
     private static final Logger LOG = Logger.getLogger(IsisWicketApplication.class);
 
+    private final IsisLoggingConfigurer loggingConfigurer = new IsisLoggingConfigurer();
+
     /**
      * Convenience locator, downcasts inherited functionality.
      */
@@ -146,12 +150,14 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
     /**
      * {@link Inject}ed when {@link #init() initialized}.
      */
+    @SuppressWarnings("unused")
     @Inject
     private ImageResourceCache imageCache;
 
     /**
      * {@link Inject}ed when {@link #init() initialized}.
      */
+    @SuppressWarnings("unused")
     @Inject
     private WicketViewerSettings wicketViewerSettings;
 
@@ -165,6 +171,7 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
     /**
      * {@link Inject}ed when {@link #init() initialized}.
      */
+    @SuppressWarnings("unused")
     @Inject
     private IsisSystem system;
 
@@ -187,6 +194,9 @@ public class IsisWicketApplication extends AuthenticatedWebApplication implement
     protected void init() {
         super.init();
 
+        final String webInfDir = getServletContext().getRealPath("/WEB-INF");
+        loggingConfigurer.configureLogging(webInfDir, new String[0]);
+
         getRequestCycleSettings().setRenderStrategy(RenderStrategy.REDIRECT_TO_RENDER);
 
         getRequestCycleListeners().add(new WebRequestCycleForIsis());

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
index e0aabb3..8c0d808 100644
--- a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
+++ b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/WebRequestCycleForIsis.java
@@ -30,8 +30,11 @@ import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.session.IsisSession;
 import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.core.runtime.system.transaction.MessageBroker;
+import org.apache.isis.core.runtime.system.transaction.MessageBrokerDefault;
 import org.apache.isis.viewer.wicket.ui.pages.error.ErrorPage;
 import org.apache.log4j.Logger;
+import org.apache.wicket.Session;
 import org.apache.wicket.core.request.handler.PageProvider;
 import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
 import org.apache.wicket.protocol.http.WebSession;
@@ -54,7 +57,6 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract
 
     @Override
     public synchronized void onBeginRequest(RequestCycle requestCycle) {
-        //super.onBeginRequest();
         final AuthenticatedWebSessionForIsis wicketSession = getWebSession();
         if (wicketSession == null) {
             return;
@@ -83,12 +85,13 @@ public class WebRequestCycleForIsis /*extends WebRequestCycle*/ extends Abstract
 
     private void commitTransactionIfAny() {
         final IsisTransaction transaction = getTransactionManager().getTransaction();
-        if (transaction != null) {
-            if (transaction.getState() == IsisTransaction.State.MUST_ABORT) {
-                getTransactionManager().abortTransaction();
-            } else if (transaction.getState() == IsisTransaction.State.IN_PROGRESS) {
-                getTransactionManager().endTransaction();
-            }
+        if (transaction == null) {
+            return;
+        }
+        if (transaction.getState() == IsisTransaction.State.MUST_ABORT) {
+            getTransactionManager().abortTransaction();
+        } else if (transaction.getState() == IsisTransaction.State.IN_PROGRESS) {
+            getTransactionManager().endTransaction();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
index 367a469..e6be696 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionPanel.java
@@ -31,6 +31,7 @@ import org.apache.isis.applib.ApplicationException;
 import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizerComposite;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
@@ -193,7 +194,9 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
             if(message != null) {
                 // recognized
                 feedbackOwner.error(message);
-                getTransactionManager().abortTransaction();
+                
+                // there's no need to abort the transaction, it will have already been done
+                // (in IsisTransactionManager#executeWithinTransaction(...)). 
                 return false;
             }
 
@@ -209,18 +212,6 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
     }
 
     /**
-     * The executeAction method will set a value on the thread if an
-     * {@link ApplicationException} is thrown.  This will allow the exception
-     * to be rendered in the usual way (using jGrowl).  Once rendered,
-     * this {@link ThreadLocal} will be cleared (see {@link PageAbstract}).
-     * 
-     * <p>
-     * Using a {@link ThreadLocal} is always a  bit hacky, but will do, I think.
-     */
-    public static ThreadLocal<String> applicationError = new ThreadLocal<String>();
-
-
-    /**
      * Executes the action, handling any {@link ApplicationException}s that
      * might be encountered.
      * 
@@ -244,8 +235,10 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
             // see if is an application-defined exception
             final ApplicationException appEx = getApplicationExceptionIfAny(ex);
             if (appEx != null) {
-                applicationError.set(appEx.getMessage());
-                getTransactionManager().abortTransaction();
+                getMessageBroker().setApplicationError(appEx.getMessage());
+
+                // there's no need to abort the transaction, it will have already been done
+                // (in IsisTransactionManager#executeWithinTransaction(...)). 
                 return null;
             } 
 
@@ -254,6 +247,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         }
     }
 
+
     private ApplicationException getApplicationExceptionIfAny(Exception ex) {
         Iterable<ApplicationException> appEx = Iterables.filter(Throwables.getCausalChain(ex), ApplicationException.class);
         Iterator<ApplicationException> iterator = appEx.iterator();
@@ -440,4 +434,8 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
         return IsisContext.getPersistenceSession().getServicesInjector();
     }
 
+    protected MessageBroker getMessageBroker() {
+        return getAuthenticationSession().getMessageBroker();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
index 7b36cff..8810d2e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/PageAbstract.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.runtime.system.context.IsisContext;
@@ -134,11 +135,10 @@ public abstract class PageAbstract extends WebPage {
         response.render(JavaScriptHeaderItem.forReference(Application.get().getJavaScriptLibrarySettings().getJQueryReference()));
         response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_JGROWL_JS));
         
-        final String feedbackMsg = renderFeedback();
+        final String feedbackMsg = asJGrowlCalls(getMessageBroker());
         if (!StringUtils.isEmpty(feedbackMsg)) {
             response.render(OnDomReadyHeaderItem.forScript(feedbackMsg));
         }
-
         
         if(applicationCss != null) {
             response.render(CssReferenceHeaderItem.forUrl(applicationCss));
@@ -148,27 +148,24 @@ public abstract class PageAbstract extends WebPage {
         }
     }
 
-    private String renderFeedback() {
+    private String asJGrowlCalls(MessageBroker messageBroker) {
         final StringBuilder buf = new StringBuilder();
         
-        for (String info : IsisContext.getMessageBroker().getMessages()) {
+        for (String info : messageBroker.getMessages()) {
             addJGrowlCall(info, "INFO", false, buf);
         }
-        for (String warning : IsisContext.getMessageBroker().getWarnings()) {
+        for (String warning : getMessageBroker().getWarnings()) {
             addJGrowlCall(warning, "WARNING", true, buf);
         }
         
-        try {
-            final String error = ActionPanel.applicationError.get();
-            if(error!=null) {
-                addJGrowlCall(error, "ERROR", true, buf);
-            }
-        } finally {
-            ActionPanel.applicationError.remove();
+        final String error =  getMessageBroker().getApplicationError();
+        if(error!=null) {
+            addJGrowlCall(error, "ERROR", true, buf);
         }
         return buf.toString();
     }
 
+
     void addJGrowlCall(final String msg, final String cssClassSuffix, boolean sticky, final StringBuilder buf) {
         buf.append("$.jGrowl(\"").append(msg).append('\"');
         buf.append(", {");
@@ -310,4 +307,9 @@ public abstract class PageAbstract extends WebPage {
     protected AuthenticationSession getAuthenticationSession() {
         return IsisContext.getAuthenticationSession();
     }
+    
+    protected MessageBroker getMessageBroker() {
+        return IsisContext.getMessageBroker();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java b/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
index 2945c71..36bcbd3 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/ApplicationException.java
@@ -25,24 +25,17 @@ package org.apache.isis.applib;
  */
 public class ApplicationException extends RuntimeException {
     private static final long serialVersionUID = 1L;
-    private Throwable cause;
 
     public ApplicationException(final String msg) {
         super(msg);
     }
 
     public ApplicationException(final Throwable cause) {
-        this(cause.getMessage());
-        this.cause = cause;
+        this(cause.getMessage(), cause);
     }
 
     public ApplicationException(final String msg, final Throwable cause) {
-        this(msg);
-        this.cause = cause;
+        super(msg, cause);
     }
 
-    @Override
-    public Throwable getCause() {
-        return cause;
-    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AnonymousSession.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AnonymousSession.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AnonymousSession.java
index 1c4001c..89eb9a8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AnonymousSession.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AnonymousSession.java
@@ -40,6 +40,7 @@ public class AnonymousSession extends AuthenticationSessionAbstract {
     private static final String ROLE = "not-logged-in";
     private static final String CODE = "";
 
+
     public AnonymousSession() {
         super(USER_NAME, Arrays.asList(ROLE), CODE);
     }
@@ -48,4 +49,5 @@ public class AnonymousSession extends AuthenticationSessionAbstract {
         super(input);
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSession.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSession.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSession.java
index efeb9d3..3a5e81b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSession.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSession.java
@@ -62,4 +62,16 @@ public interface AuthenticationSession extends Encodable, Serializable {
      * @see #getAttribute(String)
      */
     public void setAttribute(String attributeName, Object attribute);
+
+    /**
+     * The {@link MessageBroker} that holds messages for this user.
+     */
+    public MessageBroker getMessageBroker();
+    /**
+     * Providing the ability for a {@link MessageBroker} to be set on this
+     * {@link AuthenticationSession} (is lazily created by the runtime).
+     */
+    public void setMessageBroker(MessageBroker messageBroker);
+    
+    
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSessionAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSessionAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSessionAbstract.java
index b2acff9..736f7e9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSessionAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/AuthenticationSessionAbstract.java
@@ -125,6 +125,21 @@ public abstract class AuthenticationSessionAbstract implements AuthenticationSes
         attributeByName.put(attributeName, attribute);
     }
 
+
+    // ///////////////////////////////////////////////////////
+    // MessageBroker
+    // ///////////////////////////////////////////////////////
+
+    private MessageBroker messageBroker;
+    @Override
+    public MessageBroker getMessageBroker() {
+        return messageBroker;
+    }
+    @Override
+    public void setMessageBroker(MessageBroker messageBroker) {
+        this.messageBroker = messageBroker;
+    }
+
     // ///////////////////////////////////////////////////////
     // toString
     // ///////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/MessageBroker.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/MessageBroker.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/MessageBroker.java
new file mode 100644
index 0000000..f5552f2
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/authentication/MessageBroker.java
@@ -0,0 +1,44 @@
+/*
+ *  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.commons.authentication;
+
+import java.util.List;
+
+/**
+ * Moving from runtime, so that can preserve messages between interactions that
+ * correspond to the same session.
+ */
+public interface MessageBroker {
+
+    void addMessage(String message);
+    List<String> getMessages();
+    String getMessagesCombined();
+
+    void addWarning(String message);
+    List<String> getWarnings();
+    String getWarningsCombined();
+
+
+    void setApplicationError(String message);
+    String getApplicationError();
+
+    void ensureEmpty();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
index 640d7ad..d6fd60c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
@@ -510,7 +510,7 @@ public abstract class IsisContext implements DebuggableWithTitle {
      * {@link #getCurrentTransaction() current transaction}.
      */
     public static MessageBroker getMessageBroker() {
-        return getCurrentTransaction().getMessageBroker();
+        return (MessageBroker) getCurrentTransaction().getMessageBroker();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/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 c1d58f8..da14ed9 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
@@ -187,7 +187,7 @@ public class IsisTransaction implements TransactionScopedComponent {
     private final TransactionalResource objectStore;
     private final List<PersistenceCommand> commands = Lists.newArrayList();
     private final IsisTransactionManager transactionManager;
-    private final MessageBroker messageBroker;
+    private final org.apache.isis.core.commons.authentication.MessageBroker messageBroker;
     private final UpdateNotifier updateNotifier;
     private final List<IsisException> exceptions = Lists.newArrayList();
 
@@ -206,14 +206,14 @@ public class IsisTransaction implements TransactionScopedComponent {
     
     private final UUID guid;
 
-    public IsisTransaction(final IsisTransactionManager transactionManager, final MessageBroker messageBroker, final UpdateNotifier updateNotifier, final TransactionalResource objectStore, final AuditingService auditingService, PublishingServiceWithDefaultPayloadFactories publishingService) {
+    public IsisTransaction(final IsisTransactionManager transactionManager, final org.apache.isis.core.commons.authentication.MessageBroker messageBroker2, final UpdateNotifier updateNotifier, final TransactionalResource objectStore, final AuditingService auditingService, PublishingServiceWithDefaultPayloadFactories publishingService) {
         
         ensureThatArg(transactionManager, is(not(nullValue())), "transaction manager is required");
-        ensureThatArg(messageBroker, is(not(nullValue())), "message broker is required");
+        ensureThatArg(messageBroker2, is(not(nullValue())), "message broker is required");
         ensureThatArg(updateNotifier, is(not(nullValue())), "update notifier is required");
 
         this.transactionManager = transactionManager;
-        this.messageBroker = messageBroker;
+        this.messageBroker = messageBroker2;
         this.updateNotifier = updateNotifier;
         this.auditingService = auditingService;
         this.publishingService = publishingService;
@@ -637,9 +637,12 @@ public class IsisTransaction implements TransactionScopedComponent {
      * 
      * <p>
      * Injected in constructor
+     *
+     * @deprecated - obtain the {@link org.apache.isis.core.commons.authentication.MessageBroker} instead from the {@link AuthenticationSession}.
      */
+    @Deprecated
     public MessageBroker getMessageBroker() {
-        return messageBroker;
+        return (MessageBroker) messageBroker;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/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 34b8834..c83dd25 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
@@ -36,8 +36,8 @@ import org.apache.isis.applib.services.publish.EventPayload;
 import org.apache.isis.applib.services.publish.EventPayloadForActionInvocation;
 import org.apache.isis.applib.services.publish.EventPayloadForChangedObject;
 import org.apache.isis.applib.services.publish.EventSerializer;
-import org.apache.isis.applib.services.publish.PublishingService;
 import org.apache.isis.applib.services.publish.ObjectStringifier;
+import org.apache.isis.applib.services.publish.PublishingService;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.components.SessionScopedComponent;
 import org.apache.isis.core.commons.debug.DebugBuilder;
@@ -54,9 +54,6 @@ import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.session.IsisSession;
 import org.apache.log4j.Logger;
 
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-
 public class IsisTransactionManager implements SessionScopedComponent {
 
 
@@ -151,7 +148,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
      * Convenience method returning the {@link MessageBroker} of the
      * {@link #getTransaction() current transaction}.
      */
-    protected MessageBroker getMessageBroker() {
+    protected org.apache.isis.core.commons.authentication.MessageBroker getMessageBroker() {
         return getTransaction().getMessageBroker();
     }
 
@@ -260,7 +257,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
      * @see #createMessageBroker()
      * @see #createUpdateNotifier()
      */
-    protected IsisTransaction createTransaction(final MessageBroker messageBroker, final UpdateNotifier updateNotifier) {
+    protected IsisTransaction createTransaction(final org.apache.isis.core.commons.authentication.MessageBroker messageBroker, final UpdateNotifier updateNotifier) {
         ensureThatArg(messageBroker, is(not(nullValue())));
         ensureThatArg(updateNotifier, is(not(nullValue())));
 
@@ -475,16 +472,14 @@ public class IsisTransactionManager implements SessionScopedComponent {
     // //////////////////////////////////////////////////////////////
 
 
-
-    
     /**
      * Overridable hook, used in
      * {@link #createTransaction(MessageBroker, UpdateNotifier)
      * 
      * <p> Called when a new {@link IsisTransaction} is created.
      */
-    protected MessageBroker createMessageBroker() {
-        return new MessageBrokerDefault();
+    protected org.apache.isis.core.commons.authentication.MessageBroker createMessageBroker() {
+        return MessageBrokerDefault.acquire(getAuthenticationSession());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBroker.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBroker.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBroker.java
index 1814891..282b8f3 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBroker.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBroker.java
@@ -19,22 +19,10 @@
 
 package org.apache.isis.core.runtime.system.transaction;
 
-import java.util.List;
-
-public interface MessageBroker {
-
-    List<String> getMessages();
-
-    String getMessagesCombined();
-
-    List<String> getWarnings();
-
-    String getWarningsCombined();
-
-    void addWarning(String message);
-
-    void addMessage(String message);
-
-    void ensureEmpty();
+/**
+ * @deprecated - replace with {@link org.apache.isis.core.commons.authentication.MessageBroker} in the core.
+ */
+@Deprecated
+public interface MessageBroker extends org.apache.isis.core.commons.authentication.MessageBroker {
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBrokerDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBrokerDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBrokerDefault.java
index ee9cd2e..8a4a682 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBrokerDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/transaction/MessageBrokerDefault.java
@@ -25,16 +25,35 @@ import java.util.List;
 
 import com.google.common.collect.Lists;
 
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.debug.DebugBuilder;
 import org.apache.isis.core.commons.debug.DebuggableWithTitle;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.runtime.system.context.IsisContext;
 
 public class MessageBrokerDefault implements MessageBroker, DebuggableWithTitle {
 
     private final List<String> messages = Lists.newArrayList();
     private final List<String> warnings = Lists.newArrayList();
+    private String applicationError;
+
+    public static org.apache.isis.core.commons.authentication.MessageBroker acquire(final AuthenticationSession authenticationSession) {
+        org.apache.isis.core.commons.authentication.MessageBroker messageBroker;
+        synchronized (authenticationSession) {
+            messageBroker = authenticationSession.getMessageBroker();
+            if(messageBroker == null) {
+                messageBroker = new MessageBrokerDefault();
+                authenticationSession.setMessageBroker(messageBroker);
+            }
+        }
+        return messageBroker;
+    }
 
+    /**
+     * @deprecated - use {@link #acquire()}
+     */
+    @Deprecated
     public MessageBrokerDefault() {
     }
 
@@ -99,6 +118,24 @@ public class MessageBrokerDefault implements MessageBroker, DebuggableWithTitle
         return string;
     }
 
+
+    // //////////////////////////////////////////////////
+    // Application error
+    // //////////////////////////////////////////////////
+
+    @Override
+    public void setApplicationError(String error) {
+        this.applicationError = error;
+        
+    }
+
+    @Override
+    public String getApplicationError() {
+        String error = applicationError;
+        setApplicationError(null);
+        return error;
+    }
+
     // //////////////////////////////////////////////////
     // Debugging
     // //////////////////////////////////////////////////
@@ -137,4 +174,5 @@ public class MessageBrokerDefault implements MessageBroker, DebuggableWithTitle
         return copy;
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
index bd01c72..9142db2 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/PersistenceSessionObjectStoreTest.java
@@ -36,6 +36,7 @@ import org.junit.Test;
 import org.apache.isis.applib.services.audit.AuditingService;
 import org.apache.isis.applib.services.publish.PublishingService;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.matchers.IsisMatchers;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -121,6 +122,9 @@ public class PersistenceSessionObjectStoreTest {
     @Mock
     private IsisConfiguration mockConfiguration;
     
+    @Mock
+    private MessageBroker mockMessageBroker;
+    
     
     private IsisMetaModel isisMetaModel;
 
@@ -155,6 +159,9 @@ public class PersistenceSessionObjectStoreTest {
                 ignoring(saveObjectCommand);
                 ignoring(destroyObjectCommand);
                 ignoring(mockVersion);
+                
+                allowing(mockAuthenticationSession).getMessageBroker();
+                will(returnValue(mockMessageBroker));
             }
         });
 

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
index 0f33d80..8ff2200 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_EndTransactionTest.java
@@ -25,11 +25,9 @@ import static org.junit.Assert.assertThat;
 
 import java.util.Collections;
 
-import org.apache.isis.applib.services.audit.AuditingService;
-import org.apache.isis.applib.services.publish.PublishingService;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
-import org.apache.isis.core.metamodel.services.ServicesInjectorSpi;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 import org.apache.isis.core.unittestsupport.jmock.auto.Mock;
@@ -55,6 +53,8 @@ public class ObjectStoreTransactionManager_EndTransactionTest {
     @Mock
     private PersistenceSession mockPersistenceSession;
     @Mock
+    private MessageBroker mockMessageBroker;
+    @Mock
     private TransactionalResource mockObjectStore;
 
     private IsisTransactionManager transactionManager;
@@ -64,6 +64,9 @@ public class ObjectStoreTransactionManager_EndTransactionTest {
         context.checking(new Expectations(){{
             allowing(mockAuthenticationSession).getUserName();
             will(returnValue("sven"));
+
+            allowing(mockAuthenticationSession).getMessageBroker();
+            will(returnValue(mockMessageBroker));
         }});
 
         transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault()) {

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
index 8f975cf..9ed0fe0 100644
--- a/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
+++ b/core/runtime/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/ObjectStoreTransactionManager_StartTransactionTest.java
@@ -25,6 +25,8 @@ import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.CoreMatchers.sameInstance;
 import static org.junit.Assert.assertThat;
 
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.MessageBroker;
 import org.apache.isis.core.metamodel.services.ServicesInjectorDefault;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
@@ -47,18 +49,33 @@ public class ObjectStoreTransactionManager_StartTransactionTest {
     private PersistenceSession mockPersistenceSession;
     @Mock
     private TransactionalResource mockObjectStore;
+    @Mock
+    private MessageBroker mockMessageBroker;
+    @Mock
+    private AuthenticationSession mockAuthenticationSession;
 
 
     private IsisTransactionManager transactionManager;
 
     @Before
     public void setUpTransactionManager() throws Exception {
-        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault());
+        transactionManager = new IsisTransactionManager(mockPersistenceSession, mockObjectStore, new ServicesInjectorDefault()) {
+            @Override
+            protected AuthenticationSession getAuthenticationSession() {
+                return mockAuthenticationSession;
+            }
+        };
     }
 
     @Before
     public void setUpExpectations() throws Exception {
         context.ignoring(mockPersistenceSession);
+        context.checking(new Expectations() {
+            {
+                allowing(mockAuthenticationSession).getMessageBroker();
+                will(returnValue(mockMessageBroker));
+            }
+        });
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
index 356ea1d..4d9b302 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
@@ -106,7 +106,7 @@ public class ToDoItems extends AbstractFactoryAndRepository {
     }
     // }}
 
-    
+
     // {{ AllToDos (action)
     @ActionSemantics(Of.SAFE)
     @MemberOrder(sequence = "4")

http://git-wip-us.apache.org/repos/asf/isis/blob/70111da9/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/logging.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/logging.properties b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/logging.properties
index e3038de..dc0c685 100644
--- a/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/logging.properties
+++ b/example/application/quickstart_wicket_restful_jdo/viewer-webapp/src/main/webapp/WEB-INF/logging.properties
@@ -36,8 +36,6 @@ log4j.appender.File.layout.ConversionPattern=%d [%-20c{1} %-10t %-5p]  %m%n
 
 
 
-
-
 ! turn on the internal log4j debugging flag so we can see what it is doing
 #log4j.debug=true