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/10/23 17:20:59 UTC
isis git commit: ISIS-1210: implementation of ErrorReportingService
Repository: isis
Updated Branches:
refs/heads/master 7b8bae202 -> 714dd129e
ISIS-1210: implementation of ErrorReportingService
... with support in the Wicket UI viewer
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/714dd129
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/714dd129
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/714dd129
Branch: refs/heads/master
Commit: 714dd129e0ed6993fea6a57385a9f6396f3a1588
Parents: 7b8bae2
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Oct 23 16:10:49 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Oct 23 16:10:49 2015 +0100
----------------------------------------------------------------------
.../applib/services/error/ErrorDetails.java | 65 ++++++++++++++++
.../services/error/ErrorReportingService.java | 28 +++++++
.../isis/applib/services/error/Ticket.java | 80 ++++++++++++++++++++
.../viewer/wicket/ui/errors/ExceptionModel.java | 18 +++++
.../ui/errors/ExceptionStackTracePanel.html | 18 ++++-
.../ui/errors/ExceptionStackTracePanel.java | 27 ++++++-
.../viewer/wicket/ui/pages/error/ErrorPage.java | 38 ++++++++++
7 files changed, 269 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorDetails.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorDetails.java b/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorDetails.java
new file mode 100644
index 0000000..2ce4211
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorDetails.java
@@ -0,0 +1,65 @@
+/*
+ * 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.applib.services.error;
+
+import java.util.List;
+
+/**
+ * Details of the error (obtained from the thrown exception), passed as part of the request to the
+ * {@link ErrorReportingService}.
+ *
+ * <p>
+ * Implementation note: a class has been used here so that additional fields might be added in the future.
+ * </p>
+ */
+public class ErrorDetails {
+
+ private final String mainMessage;
+ private final boolean recognized;
+ private final boolean authorizationCause;
+ private final List<String> stackTraceDetailList;
+
+ public ErrorDetails(
+ final String mainMessage,
+ final boolean recognized,
+ final boolean authorizationCause,
+ final List<String> stackTraceDetailList) {
+ this.mainMessage = mainMessage;
+ this.recognized = recognized;
+ this.authorizationCause = authorizationCause;
+ this.stackTraceDetailList = stackTraceDetailList;
+ }
+
+ public String getMainMessage() {
+ return mainMessage;
+ }
+
+ public boolean isRecognized() {
+ return recognized;
+ }
+
+ public boolean isAuthorizationCause() {
+ return authorizationCause;
+ }
+
+ public List<String> getStackTraceDetailList() {
+ return stackTraceDetailList;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorReportingService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorReportingService.java b/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorReportingService.java
new file mode 100644
index 0000000..7198483
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/error/ErrorReportingService.java
@@ -0,0 +1,28 @@
+/*
+ * 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.applib.services.error;
+
+/**
+ * Optional SPI service.
+ */
+public interface ErrorReportingService {
+
+ Ticket reportError(final ErrorDetails errorDetails);
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/applib/src/main/java/org/apache/isis/applib/services/error/Ticket.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/error/Ticket.java b/core/applib/src/main/java/org/apache/isis/applib/services/error/Ticket.java
new file mode 100644
index 0000000..ec8d465
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/error/Ticket.java
@@ -0,0 +1,80 @@
+/*
+ * 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.applib.services.error;
+
+import java.io.Serializable;
+
+/**
+ * Response from the {@link ErrorReportingService}, containing information to show to the end-user.
+ *
+ * <p>
+ * Implementation notes:
+ * <ul>
+ * <li>a class has been used here so that additional fields might be added in the future.</li>
+ * <li>the class is {@link Serializable}</li> so that it can be stored by the Wicket viewer as a Wicket model.
+ * </ul>
+ * </p>
+ */
+public class Ticket implements Serializable {
+
+ private final String reference;
+ private final String userMessage;
+ private final String details;
+
+ public Ticket(final String reference, final String userMessage, final String details) {
+ this.reference = reference;
+ this.userMessage = userMessage;
+ this.details = details;
+ }
+
+ /**
+ * A unique identifier that the end-user can use to track any follow-up from this error.
+ *
+ * <p>
+ * For example, an implementation might automatically log an issue in a bug tracking system such as JIRA, in
+ * which case the {@link #getReference() reference} would be the JIRA issue number <tt>XXX-1234</tt>.
+ * </p>
+ */
+ public String getReference() {
+ return reference;
+ }
+
+ /**
+ * Message to display to the user.
+ *
+ * <p>
+ * Typically this message should be short, one line long.
+ * </p>
+ */
+ public String getUserMessage() {
+ return userMessage;
+ }
+
+ /**
+ * Optional additional details to show to the end-user.
+ *
+ * <p>
+ * For example, these might include text on how to recover from the error, or workarounds, or just further
+ * details on contacting the help desk if the issue is severe and requires immediate attention.
+ * </p>
+ */
+ public String getDetails() {
+ return details;
+ }
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionModel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionModel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionModel.java
index 936c3fd..e4e620f 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionModel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionModel.java
@@ -20,10 +20,14 @@ package org.apache.isis.viewer.wicket.ui.errors;
import java.util.Iterator;
import java.util.List;
+
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+
import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.services.error.ErrorReportingService;
+import org.apache.isis.applib.services.error.Ticket;
import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
import org.apache.isis.viewer.wicket.model.models.ModelAbstract;
@@ -98,6 +102,20 @@ public class ExceptionModel extends ModelAbstract<List<StackTraceDetail>> {
this.stackTraceDetailList = stackTraceDetail;
}
+
+ private Ticket ticket;
+ public Ticket getTicket() {
+ return ticket;
+ }
+
+ /**
+ * Optionally called if an {@link ErrorReportingService} has been configured and returns a <tt>non-null</tt> ticket
+ * to represent the fact that the error has been recorded.
+ */
+ public void setTicket(final Ticket ticket) {
+ this.ticket = ticket;
+ }
+
public boolean isRecognized() {
return recognized;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.html
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.html b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.html
index 2d61e32..4277658 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.html
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.html
@@ -31,9 +31,23 @@
<wicket:panel>
<div class="exceptionStackTracePanel">
<div class="errorInfo clear">
- <h4 wicket:id="mainMessage" class="mainMessage">[main message text]</h4>
+ <div class="panel">
+ <div class="panel-heading">
+ <h2 class="mainMessage">
+ <span class="fa fa-fw fa-warning fontAwesomeIcon" style="color:#C9302C;"></span>
+ <span wicket:id="mainMessage">[main message text]</span>
+ </h2>
+ </div>
+ <div class="panel-body" wicket:id="userDetail">
+ <h3><span wicket:id="details">details</span></h3>
+ </div>
+ </div>
+ <br/>
<div class="errorDetail panel panel-default" wicket:id="exceptionDetail">
- <div class="heading panel-heading"><span class="panel-title">Show detail</span></div>
+ <div class="heading panel-heading">
+ <a class="btn btn-primary" href="#" role="button">Exception details</a>
+ <span class="panel-title"></span>
+ </div>
<div class="content panel-body">
<div class="exceptionStackTrace">
<h3>Stack trace:</h3>
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.java
index 7504c47..fb81315 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/errors/ExceptionStackTracePanel.java
@@ -24,8 +24,12 @@ 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.basic.MultiLineLabel;
import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
+
+import org.apache.isis.applib.services.error.Ticket;
import org.apache.isis.viewer.wicket.ui.util.Components;
public class ExceptionStackTracePanel extends Panel {
@@ -34,6 +38,8 @@ public class ExceptionStackTracePanel extends Panel {
private static final String ID_MAIN_MESSAGE = "mainMessage";
+ private static final String ID_USER_DETAIL = "userDetail";
+ private static final String ID_DETAILS = "details";
private static final String ID_EXCEPTION_DETAIL = "exceptionDetail";
private static final String ID_STACK_TRACE_ELEMENT = "stackTraceElement";
@@ -44,7 +50,12 @@ public class ExceptionStackTracePanel extends Panel {
public ExceptionStackTracePanel(String id, ExceptionModel exceptionModel) {
super(id, exceptionModel);
- final String mainMessage = exceptionModel.getMainMessage();
+ final Ticket ticket = exceptionModel.getTicket();
+ final String mainMessage =
+ ticket != null && ticket.getUserMessage() != null
+ ? ticket.getUserMessage()
+ : exceptionModel.getMainMessage();
+
final Label label = new Label(ID_MAIN_MESSAGE, mainMessage);
// to avoid potential XSS attacks, no longer escape model strings
@@ -53,8 +64,18 @@ public class ExceptionStackTracePanel extends Panel {
add(label);
- final boolean suppressDetail = exceptionModel.isAuthorizationException() || exceptionModel.isRecognized();
- if(suppressDetail) {
+ final String ticketDetail = ticket != null ? ticket.getDetails(): null;
+ if(ticketDetail == null) {
+ Components.permanentlyHide(this, ID_USER_DETAIL);
+ } else {
+ final WebMarkupContainer panel = new WebMarkupContainer(ID_USER_DETAIL);
+ final MultiLineLabel details = new MultiLineLabel(ID_DETAILS, Model.of(ticketDetail));
+ panel.add(details);
+ add(panel);
+ }
+
+ final boolean suppressExceptionDetail = exceptionModel.isAuthorizationException() || exceptionModel.isRecognized();
+ if(suppressExceptionDetail) {
Components.permanentlyHide(this, ID_EXCEPTION_DETAIL);
} else {
http://git-wip-us.apache.org/repos/asf/isis/blob/714dd129/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
----------------------------------------------------------------------
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
index ef22601..6824c8b 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/error/ErrorPage.java
@@ -19,10 +19,22 @@
package org.apache.isis.viewer.wicket.ui.pages.error;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+
import org.apache.wicket.authroles.authorization.strategies.role.annotations.AuthorizeInstantiation;
+
+import org.apache.isis.applib.services.error.ErrorDetails;
+import org.apache.isis.applib.services.error.ErrorReportingService;
+import org.apache.isis.applib.services.error.Ticket;
import org.apache.isis.viewer.wicket.model.common.PageParametersUtils;
import org.apache.isis.viewer.wicket.ui.errors.ExceptionModel;
import org.apache.isis.viewer.wicket.ui.errors.ExceptionStackTracePanel;
+import org.apache.isis.viewer.wicket.ui.errors.StackTraceDetail;
import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
/**
@@ -41,6 +53,32 @@ public class ErrorPage extends PageAbstract {
addBookmarkedPages(themeDiv);
+ final ErrorReportingService errorReportingService = getServicesInjector()
+ .lookupService(ErrorReportingService.class);
+ if(errorReportingService != null) {
+
+ final String mainMessage = exceptionModel.getMainMessage();
+ final boolean recognized = exceptionModel.isRecognized();
+ final boolean authorizationException = exceptionModel.isAuthorizationException();
+
+ final List<StackTraceDetail> stackTrace = exceptionModel.getStackTrace();
+ final List<String> stackDetails = Lists.transform(stackTrace, new Function<StackTraceDetail, String>() {
+ @Nullable @Override public String apply(final StackTraceDetail stackTraceDetail) {
+ return stackTraceDetail.getLine();
+ }
+ });
+
+ final ErrorDetails errorDetails = new ErrorDetails(mainMessage, recognized, authorizationException,
+ stackDetails);
+
+ final Ticket ticket = errorReportingService.reportError(errorDetails);
+
+ if (ticket != null) {
+ exceptionModel.setTicket(ticket);
+ }
+
+ }
+
themeDiv.add(new ExceptionStackTracePanel(ID_EXCEPTION_STACK_TRACE, exceptionModel));
}