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/03/01 17:41:35 UTC

[1/2] git commit: ISIS-320: factoring out error stack trace component...

ISIS-320: factoring out error stack trace component...

... with view to making available on sign-on page also.


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

Branch: refs/heads/master
Commit: 51a12dc08127606d3bb23cda09cce56f1c8ce9b2
Parents: b1d7000
Author: Dan Haywood <da...@apache.org>
Authored: Fri Mar 1 16:40:35 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Mar 1 16:40:35 2013 +0000

----------------------------------------------------------------------
 .../wicket/ui/components/actions/ActionPanel.java  |    5 +-
 .../entity/properties/EntityPropertiesForm.java    |    2 +-
 .../viewer/wicket/ui/errors/JGrowlBehaviour.java   |   46 ++++++
 .../isis/viewer/wicket/ui/errors/JGrowlUtil.java   |   38 +++++
 .../viewer/wicket/ui/errors/StackTraceDetail.java  |   51 +++++++
 .../wicket/ui/errors/StackTraceListView.java       |   27 ++++
 .../wicket/ui/notifications/JGrowlBehaviour.java   |   46 ------
 .../viewer/wicket/ui/notifications/JGrowlUtil.java |   38 -----
 .../isis/viewer/wicket/ui/pages/PageAbstract.java  |    7 +-
 .../viewer/wicket/ui/pages/error/ErrorPage.css     |   83 -----------
 .../viewer/wicket/ui/pages/error/ErrorPage.html    |   21 +---
 .../viewer/wicket/ui/pages/error/ErrorPage.java    |  108 +--------------
 .../wicket/ui/pages/error/ExceptionModel.java      |   92 ++++++++++++
 .../ui/pages/error/ExceptionStackTracePanel.css    |  103 ++++++++++++++
 .../ui/pages/error/ExceptionStackTracePanel.html   |   58 ++++++++
 .../ui/pages/error/ExceptionStackTracePanel.java   |   83 +++++++++++
 16 files changed, 511 insertions(+), 297 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/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 7f1d30d..f5f9dfe 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
@@ -209,7 +209,6 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
             // not handled, so propagate
             throw ex;
         }
-
     }
 
     private String recognizeException(RuntimeException ex, Component feedbackComponent) {
@@ -227,7 +226,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
             if(feedbackComponent != null) {
                 feedbackComponent.error(recognizedErrorIfAny);
             }
-            getMessageBroker().setApplicationError(recognizedErrorIfAny);
+            getMessageBroker().addWarning(recognizedErrorIfAny);
 
             getTransactionManager().getTransaction().clearAbortCause();
             
@@ -257,7 +256,7 @@ public class ActionPanel extends PanelAbstract<ActionModel> implements ActionExe
             return resultAdapter;
 
         } catch (RuntimeException ex) {
-
+            
             // see if is an application-defined exception
             final ApplicationException appEx = getApplicationExceptionIfAny(ex);
             if (appEx != null) {

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
index 02d6c4f..784452b 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/properties/EntityPropertiesForm.java
@@ -46,7 +46,7 @@ import org.apache.isis.viewer.wicket.model.util.ObjectAssociations;
 import org.apache.isis.viewer.wicket.model.util.ObjectSpecifications;
 import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.CancelHintRequired;
-import org.apache.isis.viewer.wicket.ui.notifications.JGrowlBehaviour;
+import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
 import org.apache.isis.viewer.wicket.ui.panels.ButtonWithPreValidateHook;
 import org.apache.isis.viewer.wicket.ui.panels.FormAbstract;
 import org.apache.isis.viewer.wicket.ui.util.EvenOrOddCssClassAppenderFactory;

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
new file mode 100644
index 0000000..d6ae312
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlBehaviour.java
@@ -0,0 +1,46 @@
+package org.apache.isis.viewer.wicket.ui.errors;
+
+import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.core.commons.authentication.MessageBroker;
+import org.apache.isis.core.commons.lang.StringUtils;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+
+
+/**
+ * Attach to any Ajax button that might trigger a notification (ie calls
+ * {@link MessageBroker#addMessage(String)}, {@link MessageBroker#addWarning(String)},
+ * {@link MessageBroker#setApplicationError(String)} or throws an {@link ApplicationException}). 
+ * 
+ * <p>
+ * Attach using the standard Wicket code:
+ * <pre>
+ * Button editButton = new AjaxButton(ID_EDIT_BUTTON, Model.of("Edit")) { ... }
+ * editButton.add(new JGrowlBehaviour());
+ * </pre>
+ */
+public class JGrowlBehaviour extends AbstractDefaultAjaxBehavior {
+
+    private static final long serialVersionUID = 1L;
+
+    @Override
+    protected void respond(AjaxRequestTarget target) {
+        String feedbackMsg = JGrowlUtil.asJGrowlCalls(IsisContext.getMessageBroker());
+        if(!StringUtils.isNullOrEmpty(feedbackMsg)) {
+            target.appendJavaScript(feedbackMsg);
+        }
+    }
+    
+    @Override
+    public void renderHead(Component component, IHeaderResponse response) {
+        super.renderHead(component, response);
+        String feedbackMsg = JGrowlUtil.asJGrowlCalls(IsisContext.getMessageBroker());
+        if(!StringUtils.isNullOrEmpty(feedbackMsg)) {
+            response.render(OnDomReadyHeaderItem.forScript(feedbackMsg));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlUtil.java
new file mode 100644
index 0000000..eb3778f
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/JGrowlUtil.java
@@ -0,0 +1,38 @@
+package org.apache.isis.viewer.wicket.ui.errors;
+
+import org.apache.isis.core.commons.authentication.MessageBroker;
+
+public class JGrowlUtil {
+    
+    private JGrowlUtil(){}
+
+    public static String asJGrowlCalls(MessageBroker messageBroker) {
+        final StringBuilder buf = new StringBuilder();
+        
+        for (String info : messageBroker.getMessages()) {
+            addJGrowlCall(info, "INFO", false, buf);
+        }
+        for (String warning : messageBroker.getWarnings()) {
+            addJGrowlCall(warning, "WARNING", true, buf);
+        }
+        
+        final String error =  messageBroker.getApplicationError();
+        if(error!=null) {
+            addJGrowlCall(error, "ERROR", true, buf);
+        }
+        return buf.toString();
+    }
+
+    private static void addJGrowlCall(final String msg, final String cssClassSuffix, boolean sticky, final StringBuilder buf) {
+        buf.append("$.jGrowl(\"").append(msg).append('\"');
+        buf.append(", {");
+        buf.append("theme: \'jgrowl-").append(cssClassSuffix).append("\'");
+        if (sticky) {
+            buf.append(", sticky: true");
+        }
+        buf.append("}");
+        buf.append(");");
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceDetail.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceDetail.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceDetail.java
new file mode 100644
index 0000000..e4d9a1a
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceDetail.java
@@ -0,0 +1,51 @@
+package org.apache.isis.viewer.wicket.ui.errors;
+
+import java.io.Serializable;
+
+public class StackTraceDetail implements Serializable {
+    
+    private static final long serialVersionUID = 1L;
+
+    public static StackTraceDetail exceptionClassName(Throwable cause) {
+        return new StackTraceDetail(StackTraceDetail.Type.EXCEPTION_CLASS_NAME, cause.getClass().getName());
+    }
+
+    public static StackTraceDetail exceptionMessage(Throwable cause) {
+        return new StackTraceDetail(StackTraceDetail.Type.EXCEPTION_MESSAGE, cause.getMessage());
+    }
+
+    public static StackTraceDetail element(StackTraceElement el) {
+        StringBuilder buf = new StringBuilder();
+        buf .append("    ")
+            .append(el.getClassName())
+            .append("#")
+            .append(el.getMethodName())
+            .append("(")
+            .append(el.getFileName())
+            .append(":")
+            .append(el.getLineNumber())
+            .append(")\n")
+            ;
+        return new StackTraceDetail(StackTraceDetail.Type.STACKTRACE_ELEMENT, buf.toString());
+    }
+
+    enum Type {
+        EXCEPTION_CLASS_NAME,
+        EXCEPTION_MESSAGE,
+        STACKTRACE_ELEMENT
+    }
+    private final Type type;
+    private final String line;
+    
+    public StackTraceDetail(Type type, String line) {
+        this.type = type;
+        this.line = line;
+    }
+    public StackTraceDetail.Type getType() {
+        return type;
+    }
+    public String getLine() {
+        return line;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceListView.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceListView.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceListView.java
new file mode 100644
index 0000000..54c0ef4
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/StackTraceListView.java
@@ -0,0 +1,27 @@
+package org.apache.isis.viewer.wicket.ui.errors;
+
+import java.util.List;
+
+import org.apache.wicket.behavior.AttributeAppender;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+
+public final class StackTraceListView extends ListView<StackTraceDetail> {
+    
+    private static final long serialVersionUID = 1L;
+    private final String idLine;
+
+    public StackTraceListView(String id, String idLine, List<? extends org.apache.isis.viewer.wicket.ui.errors.StackTraceDetail> list) {
+        super(id, list);
+        this.idLine = idLine;
+    }
+
+    @Override
+    protected void populateItem(ListItem<StackTraceDetail> item) {
+        final StackTraceDetail detail = item.getModelObject();
+        Label label = new Label(idLine, detail.getLine());
+        item.add(new AttributeAppender("class", detail.getType().name().toLowerCase()));
+        item.add(label);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlBehaviour.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlBehaviour.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlBehaviour.java
deleted file mode 100644
index 09a4e23..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlBehaviour.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package org.apache.isis.viewer.wicket.ui.notifications;
-
-import org.apache.isis.applib.ApplicationException;
-import org.apache.isis.core.commons.authentication.MessageBroker;
-import org.apache.isis.core.commons.lang.StringUtils;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
-
-
-/**
- * Attach to any Ajax button that might trigger a notification (ie calls
- * {@link MessageBroker#addMessage(String)}, {@link MessageBroker#addWarning(String)},
- * {@link MessageBroker#setApplicationError(String)} or throws an {@link ApplicationException}). 
- * 
- * <p>
- * Attach using the standard Wicket code:
- * <pre>
- * Button editButton = new AjaxButton(ID_EDIT_BUTTON, Model.of("Edit")) { ... }
- * editButton.add(new JGrowlBehaviour());
- * </pre>
- */
-public class JGrowlBehaviour extends AbstractDefaultAjaxBehavior {
-
-    private static final long serialVersionUID = 1L;
-
-    @Override
-    protected void respond(AjaxRequestTarget target) {
-        String feedbackMsg = JGrowlUtil.asJGrowlCalls(IsisContext.getMessageBroker());
-        if(!StringUtils.isNullOrEmpty(feedbackMsg)) {
-            target.appendJavaScript(feedbackMsg);
-        }
-    }
-    
-    @Override
-    public void renderHead(Component component, IHeaderResponse response) {
-        super.renderHead(component, response);
-        String feedbackMsg = JGrowlUtil.asJGrowlCalls(IsisContext.getMessageBroker());
-        if(!StringUtils.isNullOrEmpty(feedbackMsg)) {
-            response.render(OnDomReadyHeaderItem.forScript(feedbackMsg));
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlUtil.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlUtil.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlUtil.java
deleted file mode 100644
index e8cef40..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/notifications/JGrowlUtil.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package org.apache.isis.viewer.wicket.ui.notifications;
-
-import org.apache.isis.core.commons.authentication.MessageBroker;
-
-public class JGrowlUtil {
-    
-    private JGrowlUtil(){}
-
-    public static String asJGrowlCalls(MessageBroker messageBroker) {
-        final StringBuilder buf = new StringBuilder();
-        
-        for (String info : messageBroker.getMessages()) {
-            addJGrowlCall(info, "INFO", false, buf);
-        }
-        for (String warning : messageBroker.getWarnings()) {
-            addJGrowlCall(warning, "WARNING", true, buf);
-        }
-        
-        final String error =  messageBroker.getApplicationError();
-        if(error!=null) {
-            addJGrowlCall(error, "ERROR", true, buf);
-        }
-        return buf.toString();
-    }
-
-    private static void addJGrowlCall(final String msg, final String cssClassSuffix, boolean sticky, final StringBuilder buf) {
-        buf.append("$.jGrowl(\"").append(msg).append('\"');
-        buf.append(", {");
-        buf.append("theme: \'jgrowl-").append(cssClassSuffix).append("\'");
-        if (sticky) {
-            buf.append(", sticky: true");
-        }
-        buf.append("}");
-        buf.append(");");
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/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 d261530..78176de 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
@@ -40,7 +40,7 @@ import org.apache.isis.viewer.wicket.ui.ComponentType;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
 import org.apache.isis.viewer.wicket.ui.components.actions.ActionPanel;
-import org.apache.isis.viewer.wicket.ui.notifications.JGrowlUtil;
+import org.apache.isis.viewer.wicket.ui.errors.JGrowlUtil;
 import org.apache.isis.viewer.wicket.ui.pages.about.AboutPage;
 import org.apache.isis.viewer.wicket.ui.pages.login.WicketSignInPage;
 import org.apache.log4j.Logger;
@@ -51,6 +51,7 @@ import org.apache.wicket.markup.head.IHeaderResponse;
 import org.apache.wicket.markup.head.JavaScriptHeaderItem;
 import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
+import org.apache.wicket.markup.head.PriorityHeaderItem;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.ExternalLink;
@@ -133,8 +134,8 @@ public abstract class PageAbstract extends WebPage {
     @Override
     public void renderHead(IHeaderResponse response) {
         super.renderHead(response);
-        response.render(JavaScriptHeaderItem.forReference(Application.get().getJavaScriptLibrarySettings().getJQueryReference()));
-        response.render(JavaScriptReferenceHeaderItem.forReference(JQUERY_JGROWL_JS));
+        response.render(new PriorityHeaderItem(JavaScriptHeaderItem.forReference(Application.get().getJavaScriptLibrarySettings().getJQueryReference())));
+        response.render(new PriorityHeaderItem(JavaScriptReferenceHeaderItem.forReference(JQUERY_JGROWL_JS)));
         
         final String feedbackMsg = JGrowlUtil.asJGrowlCalls(getMessageBroker());
         if (!StringUtils.isEmpty(feedbackMsg)) {

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
index b8d0b98..5412494 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.css
@@ -18,87 +18,4 @@
  */
 
 
-.errorPage .errorInfo {
-    margin-left: 50px;
-    margin-right: 50px;
-    padding-top: 50px;
-}
-
-
-.errorPage .mainMessage {
-    background:#FFFFFF;
-    border-radius:4px;
-    -moz-border-radius:4px;
-    -webkit-border-radius:4px;
-    padding: 15px;
-    display: block;
-    text-align:center;
-    font-size:1.2em;
-}
-
- .errorPage .errorDetail {
-    margin-top: 30px; 
-}
-
-.errorPage .heading {
-    border-radius:4px;
-    -moz-border-radius:4px;
-    -webkit-border-radius:4px;
-    background-color:#F0EFEA;
-
-    display:block;
-    font-style:normal !important;
-
-    padding:1px 6px 1px 6px;
-}
-
-.errorPage .heading span {
-    display:block;
-    font-style:normal !important;
-    padding:3px 3px 3px 3px;
-    font-size: 0.8em;
-    text-transform:uppercase;
-    font-weight:bold;
-}
-
-.errorPage .heading:hover {
-    background-color:#FFFFFF;
-    cursor: pointer;
-}
-
-.errorPage h3 {
-    font-size: larger;
-}
-
-.errorPage .exceptionMessage {
-    margin-top: 30px; 
-}
-
-.errorPage .exceptionStackTrace .caused_by_label {
-    margin-top: 30px;
-	font-style:normal !important;
-    font-size: 0.8em;
-    text-transform:uppercase;
-    font-weight:bold;
-    color: #46423C;
-}
-
-.errorPage .exceptionStackTrace .exception_class_name {
-    margin-top: 15px;
-    font-size: 1.2em;
-    font-weight:bold;
-    color: #46423C;
-}
-
-.errorPage .exceptionStackTrace .exception_message {
-    margin-top: 10px;
-    margin-bottom: 10px;
-    font-style: italic;
-    font-size: 1.0em;
-    color: #00477F;
-}
-
-.errorPage .exceptionStackTrace .stacktrace_element{
-    margin-left: 30px;
-}
 

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
index 6808ef1..80c4329 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.html
@@ -31,26 +31,7 @@
 		<wicket:extend>
 			<div class="errorPage">
                 <div wicket:id="breadcrumbs"/>
-                <div class="errorInfo clear">
-                    <span wicket:id="mainMessage" class="mainMessage">[main message text]</span>
-                    <div class="errorDetail" wicket:id="exceptionDetail">
-                        <div class="heading"><span>Show detail</span></div>
-                        <div class="content">
-                            <div class="exceptionMessage">
-                                <h3>Message:</h3>
-                                <p wicket:id="exceptionMessage">[exception message]</p>
-                            </div>
-                            <div class="exceptionStackTrace">
-                                <h3>Stack trace:</h3>
-                                <ul>
-                                    <li wicket:id="stackTraceElement">
-                                        <span wicket:id="stackTraceElementLine">[stack trace element line]</span>
-                                    </li>
-                                </ul>
-                            </div>
-                        </div>
-                    </div>
-                </div>
+                <div wicket:id="exceptionStackTrace"/>
 			</div>
 		</wicket:extend>
 	</body>

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
index d91891b..b224156 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
@@ -19,27 +19,9 @@
 
 package org.apache.isis.viewer.wicket.ui.pages.error;
 
-import java.io.Serializable;
-import java.util.List;
-
-import org.apache.isis.core.commons.lang.StringUtils;
 import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
-import org.apache.wicket.Component;
-import org.apache.wicket.MarkupContainer;
 import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
-import org.apache.wicket.behavior.AttributeAppender;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
-import org.apache.wicket.request.resource.JavaScriptResourceReference;
-
-import com.google.common.base.Strings;
-import com.google.common.base.Throwables;
-import com.google.common.collect.Lists;
 
 /**
  * Web page representing the home page (showing a welcome message).
@@ -49,108 +31,28 @@ public class ErrorPage extends PageAbstract {
 
     private static final long serialVersionUID = 1L;
 
-    private static final String MAIN_MESSAGE_IF_NOT_RECOGNIZED = "Sorry, an unexpected error occurred.";
-    
-    private static final String ID_MAIN_MESSAGE = "mainMessage";
-    
-    private static final String ID_EXCEPTION_DETAIL = "exceptionDetail";
-    private static final String ID_EXCEPTION_MESSAGE = "exceptionMessage";
-    
-    private static final String ID_STACK_TRACE_ELEMENT = "stackTraceElement";
-    private static final String ID_LINE = "stackTraceElementLine";
-
-    private static final JavaScriptResourceReference DIV_TOGGLE_JS = new JavaScriptResourceReference(ErrorPage.class, "div-toggle.js");
-
-    private static class Detail implements Serializable {
-        
-        private static final long serialVersionUID = 1L;
-        
-        enum Type {
-            EXCEPTION_CLASS_NAME,
-            EXCEPTION_MESSAGE,
-            STACKTRACE_ELEMENT
-        }
-        private Type type;
-        private String line;
-        Detail(Type type, String line) {
-            this.type = type;
-            this.line = line;
-        }
-    }
+    private static final String ID_EXCEPTION_STACK_TRACE = "exceptionStackTrace";
 
     /**
      * For recognized messages.
      */
     public ErrorPage(String message, Exception ex) {
-        this(message, null, asStackTrace(ex));
+        this(ExceptionModel.recognized(message, ex));
     }
 
-
     /**
      * For non-recognized messages.
      */
     public ErrorPage(Exception ex) {
-        this(MAIN_MESSAGE_IF_NOT_RECOGNIZED, ex.getMessage(), asStackTrace(ex));
+        this(ExceptionModel.notRecognized(ex));
     }
 
-    private ErrorPage(String mainMessage, String exceptionMessage, List<Detail> stackTraceDetail) {
+    private ErrorPage(ExceptionModel exceptionModel) {
         super(new PageParameters());
         
         addBookmarkedPages();
 
-        add(new Label(ID_MAIN_MESSAGE, mainMessage).setEscapeModelStrings(false));
-        MarkupContainer container = new WebMarkupContainer(ID_EXCEPTION_DETAIL);
-        add(container);
-        
-        container.add(
-                new Label(ID_EXCEPTION_MESSAGE, Strings.nullToEmpty(exceptionMessage)).setVisible(exceptionMessage != null));
-        
-        container.add(new ListView<Detail>(ID_STACK_TRACE_ELEMENT, stackTraceDetail) {
-            private static final long serialVersionUID = 1L;
-            
-            @Override
-            protected void populateItem(ListItem<Detail> item) {
-                final Detail detail = item.getModelObject();
-                Label label = new Label(ID_LINE, detail.line);
-                item.add(new AttributeAppender("class", detail.type.name().toLowerCase()));
-                item.add(label);
-            }
-        });
-    }
-
-    @Override
-    public void renderHead(IHeaderResponse response) {
-        super.renderHead(response);
-        response.render(JavaScriptReferenceHeaderItem.forReference(DIV_TOGGLE_JS));
+        add(new ExceptionStackTracePanel(ID_EXCEPTION_STACK_TRACE, exceptionModel));
     }
-    
 
-    private static List<Detail> asStackTrace(Throwable ex) {
-        List<Detail> stackTrace = Lists.newArrayList();
-        List<Throwable> causalChain = Throwables.getCausalChain(ex);
-        for(Throwable cause: causalChain) {
-            stackTrace.add(new Detail(Detail.Type.EXCEPTION_CLASS_NAME, cause.getClass().getName()));
-            stackTrace.add(new Detail(Detail.Type.EXCEPTION_MESSAGE, cause.getMessage()));
-            addStackTraceElements(cause, stackTrace);
-            cause = cause.getCause();
-        }
-        return stackTrace;
-    }
-
-    private static void addStackTraceElements(Throwable ex, List<Detail> stackTrace) {
-        for (StackTraceElement el : ex.getStackTrace()) {
-            StringBuilder buf = new StringBuilder();
-            buf .append("    ")
-                .append(el.getClassName())
-                .append("#")
-                .append(el.getMethodName())
-                .append("(")
-                .append(el.getFileName())
-                .append(":")
-                .append(el.getLineNumber())
-                .append(")\n")
-                ;
-            stackTrace.add(new Detail(Detail.Type.STACKTRACE_ELEMENT, buf.toString()));
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionModel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionModel.java
new file mode 100644
index 0000000..27221a9
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionModel.java
@@ -0,0 +1,92 @@
+package org.apache.isis.viewer.wicket.ui.pages.error;
+
+import java.util.List;
+
+import org.apache.isis.viewer.wicket.model.models.ModelAbstract;
+import org.apache.isis.viewer.wicket.ui.errors.StackTraceDetail;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+
+public class ExceptionModel extends ModelAbstract<Exception> {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String MAIN_MESSAGE_IF_NOT_RECOGNIZED = "Sorry, an unexpected error occurred.";
+    
+    private Exception exception;
+    private boolean recognized;
+
+    private final String mainMessage;
+
+    private final String exceptionMessage;
+    
+
+    public static ExceptionModel recognized(String message, Exception ex) {
+        return new ExceptionModel(message, null, ex);
+    }
+
+    public static ExceptionModel notRecognized(Exception ex) {
+        return new ExceptionModel(MAIN_MESSAGE_IF_NOT_RECOGNIZED, ex.getMessage(), ex);
+    }
+
+    private ExceptionModel(String mainMessage, String exceptionMessage, Exception ex) {
+        this.mainMessage = mainMessage;
+        this.exceptionMessage = exceptionMessage;
+        this.recognized = (exceptionMessage == null);
+        this.exception = ex;
+    }
+
+    @Override
+    protected Exception load() {
+        return exception;
+    }
+
+    @Override
+    public void setObject(Exception ex) {
+        if(ex == null) {
+            return;
+        }
+        this.exception = ex;
+    }
+
+    public boolean isRecognized() {
+        return recognized;
+    }
+
+    public String getMainMessage() {
+        return mainMessage;
+    }
+    
+    public String getExceptionMessage() {
+        return exceptionMessage;
+    }
+    
+    public List<StackTraceDetail> getStackTrace() {
+        return asStackTrace(exception);
+    }
+
+    
+    private static List<StackTraceDetail> asStackTrace(Throwable ex) {
+        List<StackTraceDetail> stackTrace = Lists.newArrayList();
+        List<Throwable> causalChain = Throwables.getCausalChain(ex);
+        for(Throwable cause: causalChain) {
+            stackTrace.add(StackTraceDetail.exceptionClassName(cause));
+            stackTrace.add(StackTraceDetail.exceptionMessage(cause));
+            addStackTraceElements(cause, stackTrace);
+            cause = cause.getCause();
+        }
+        return stackTrace;
+    }
+
+    private static void addStackTraceElements(Throwable ex, List<StackTraceDetail> stackTrace) {
+        for (StackTraceElement el : ex.getStackTrace()) {
+            stackTrace.add(StackTraceDetail.element(el));
+        }
+    }
+
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.css
new file mode 100644
index 0000000..e5b6f21
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.css
@@ -0,0 +1,103 @@
+/*
+ *  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.
+ */
+
+ .exceptionStackTracePanel .errorInfo {
+    margin-left: 50px;
+    margin-right: 50px;
+    padding-top: 50px;
+}
+
+
+.exceptionStackTracePanel .mainMessage {
+    background:#FFFFFF;
+    border-radius:4px;
+    -moz-border-radius:4px;
+    -webkit-border-radius:4px;
+    padding: 15px;
+    display: block;
+    text-align:center;
+    font-size:1.2em;
+}
+
+ .exceptionStackTracePanel .errorDetail {
+    margin-top: 30px; 
+}
+
+.exceptionStackTracePanel .heading {
+    border-radius:4px;
+    -moz-border-radius:4px;
+    -webkit-border-radius:4px;
+    background-color:#F0EFEA;
+
+    display:block;
+    font-style:normal !important;
+
+    padding:1px 6px 1px 6px;
+}
+
+.exceptionStackTracePanel .heading span {
+    display:block;
+    font-style:normal !important;
+    padding:3px 3px 3px 3px;
+    font-size: 0.8em;
+    text-transform:uppercase;
+    font-weight:bold;
+}
+
+.exceptionStackTracePanel .heading:hover {
+    background-color:#FFFFFF;
+    cursor: pointer;
+}
+
+.exceptionStackTracePanel h3 {
+    font-size: larger;
+}
+
+.exceptionStackTracePanel .exceptionMessage {
+    margin-top: 30px; 
+}
+
+.exceptionStackTracePanel .exceptionStackTrace .caused_by_label {
+    margin-top: 30px;
+    font-style:normal !important;
+    font-size: 0.8em;
+    text-transform:uppercase;
+    font-weight:bold;
+    color: #46423C;
+}
+
+.exceptionStackTracePanel .exceptionStackTrace .exception_class_name {
+    margin-top: 15px;
+    font-size: 1.2em;
+    font-weight:bold;
+    color: #46423C;
+}
+
+.exceptionStackTracePanel .exceptionStackTrace .exception_message {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    font-style: italic;
+    font-size: 1.0em;
+    color: #00477F;
+}
+
+.exceptionStackTracePanel .exceptionStackTrace .stacktrace_element{
+    margin-left: 30px;
+}
+ 
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.html
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.html b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.html
new file mode 100644
index 0000000..cfd2026
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.html
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<!--
+  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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml"  
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd"  
+      xml:lang="en"  
+      lang="en">
+    <head>
+        <wicket:link>
+            <link href="ExceptionStackTracePanel.css" rel="stylesheet" type="text/css"/>
+        </wicket:link>
+    </head>
+    <body>
+        <wicket:panel>
+            <div class="exceptionStackTracePanel">
+                <div class="errorInfo clear">
+                    <span wicket:id="mainMessage" class="mainMessage">[main message text]</span>
+                    <div class="errorDetail" wicket:id="exceptionDetail">
+                        <div class="heading"><span>Show detail</span></div>
+                        <div class="content">
+                            <div class="exceptionMessage">
+                                <h3>Message:</h3>
+                                <p wicket:id="exceptionMessage">[exception message]</p>
+                            </div>
+                            <div class="exceptionStackTrace">
+                                <h3>Stack trace:</h3>
+                                <ul>
+                                    <li wicket:id="stackTraceElement">
+                                        <span wicket:id="stackTraceElementLine">[stack trace element line]</span>
+                                    </li>
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </wicket:panel>
+    </body>
+</html>
+
+

http://git-wip-us.apache.org/repos/asf/isis/blob/51a12dc0/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.java
new file mode 100644
index 0000000..b115288
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ExceptionStackTracePanel.java
@@ -0,0 +1,83 @@
+/*
+ *  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.viewer.wicket.ui.pages.error;
+
+import org.apache.isis.viewer.wicket.ui.errors.StackTraceListView;
+import org.apache.isis.viewer.wicket.ui.panels.PanelUtil;
+import org.apache.wicket.MarkupContainer;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.JavaScriptReferenceHeaderItem;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.request.resource.JavaScriptResourceReference;
+
+import com.google.common.base.Strings;
+
+public class ExceptionStackTracePanel extends Panel {
+
+    private static final long serialVersionUID = 1L;
+
+    private static final String ID_MAIN_MESSAGE = "mainMessage";
+
+    private static final String ID_EXCEPTION_DETAIL = "exceptionDetail";
+    private static final String ID_EXCEPTION_MESSAGE = "exceptionMessage";
+
+    private static final String ID_STACK_TRACE_ELEMENT = "stackTraceElement";
+    private static final String ID_LINE = "stackTraceElementLine";
+
+    private static final JavaScriptResourceReference DIV_TOGGLE_JS = new JavaScriptResourceReference(ExceptionStackTracePanel.class, "div-toggle.js");
+
+    /**
+     * For recognized messages.
+     */
+    public ExceptionStackTracePanel(String id, String message, Exception ex) {
+        this(id, ExceptionModel.recognized(message, ex));
+    }
+
+    /**
+     * For non-recognized messages.
+     */
+    public ExceptionStackTracePanel(String id, Exception ex) {
+        this(id, ExceptionModel.notRecognized(ex));
+    }
+
+    public ExceptionStackTracePanel(String id, ExceptionModel exceptionModel) {
+        super(id, exceptionModel);
+        
+        add(new Label(ID_MAIN_MESSAGE, exceptionModel.getMainMessage()).setEscapeModelStrings(false));
+
+        MarkupContainer container = new WebMarkupContainer(ID_EXCEPTION_DETAIL) {
+            private static final long serialVersionUID = 1L;
+            @Override
+            public void renderHead(IHeaderResponse response) {
+                response.render(JavaScriptReferenceHeaderItem.forReference(DIV_TOGGLE_JS));
+            }
+        };
+        container.add(new Label(ID_EXCEPTION_MESSAGE, Strings.nullToEmpty(exceptionModel.getExceptionMessage())).setVisible(exceptionModel.isRecognized()));
+        container.add(new StackTraceListView(ID_STACK_TRACE_ELEMENT, ExceptionStackTracePanel.ID_LINE, exceptionModel.getStackTrace()));
+        add(container);
+    }
+
+    public void renderHead(final IHeaderResponse response) {
+        PanelUtil.renderHead(response, this.getClass());
+    }
+
+}