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 2014/12/09 00:47:39 UTC

[8/9] isis git commit: ISIS-966: exceptions in RO viewer should be serialized as JSON, not HTML.

ISIS-966: exceptions in RO viewer should be serialized as JSON, not HTML.

Also: better support for "causedBy", and include the className also in the JSON.


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

Branch: refs/heads/master
Commit: 807c6ccf9944f34a6e91282b99c3b781574d1be1
Parents: 30b8f01
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Dec 8 20:23:35 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Dec 8 23:22:36 2014 +0000

----------------------------------------------------------------------
 .../transaction/IsisTransactionManager.java     |  2 +-
 ...estfulObjectsApplicationExceptionMapper.java | 65 +-------------
 .../RestfulObjectsApplicationExceptionPojo.java | 88 +++++++++++++++++++
 .../server/RuntimeExceptionMapper.java          | 67 +++------------
 .../server/RuntimeExceptionPojo.java            | 89 ++++++++++++++++++++
 5 files changed, 193 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/807c6ccf/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 b36e330..bdb56e8 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
@@ -213,7 +213,7 @@ public class IsisTransactionManager implements SessionScopedComponent {
             if (!initiallyInTransaction) {
                 abortTransaction();
             } else {
-                // ensure that this xactn cannot be committed
+                // ensure that this xactn cannot be committed (sets state to MUST_ABORT), and capture the cause so can be rendered appropriately by some higher level in the call stack
                 getTransaction().setAbortCause(new IsisException(ex));
             }
             throw ex;

http://git-wip-us.apache.org/repos/asf/isis/blob/807c6ccf/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
index 4236704..92049ae 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionMapper.java
@@ -18,22 +18,17 @@
  */
 package org.apache.isis.viewer.restfulobjects.server;
 
-import java.util.List;
-
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
 
-import com.google.common.collect.Lists;
-
 import org.apache.isis.core.commons.exceptions.ExceptionUtils;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
 import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
-import org.apache.isis.viewer.restfulobjects.rendering.HasHttpStatusCode;
 import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
 //@Path("/") // FIXME: workaround for TomEE ... but breaks the RestEasy TCK tests so commented out:-(
@@ -56,7 +51,7 @@ public class RestfulObjectsApplicationExceptionMapper implements ExceptionMapper
         } else { 
             String body;
             try {
-                body = JsonMapper.instance().write(ExceptionPojo.create(cause));
+                body = JsonMapper.instance().write(RestfulObjectsApplicationExceptionPojo.create(cause));
             } catch (final Exception e) {
                 // fallback
                 body = "{ \"exception\": \"" + ExceptionUtils.getFullStackTrace(cause) + "\" }";
@@ -72,63 +67,5 @@ public class RestfulObjectsApplicationExceptionMapper implements ExceptionMapper
         return builder.build();
     }
 
-    private static class ExceptionPojo {
-
-        public static ExceptionPojo create(final Throwable ex) {
-            return new ExceptionPojo(ex);
-        }
-
-        private static String format(final StackTraceElement stackTraceElement) {
-            return stackTraceElement.toString();
-        }
-
-        private final int httpStatusCode;
-        private final String message;
-        private final List<String> stackTrace = Lists.newArrayList();
-        private ExceptionPojo causedBy;
-
-        public ExceptionPojo(final Throwable ex) {
-            httpStatusCode = getHttpStatusCodeIfAny(ex);
-            this.message = ex.getMessage();
-            final StackTraceElement[] stackTraceElements = ex.getStackTrace();
-            for (final StackTraceElement stackTraceElement : stackTraceElements) {
-                this.stackTrace.add(format(stackTraceElement));
-            }
-            final Throwable cause = ex.getCause();
-            if (cause != null && cause != ex) {
-                this.causedBy = new ExceptionPojo(cause);
-            }
-        }
-
-        private int getHttpStatusCodeIfAny(final Throwable ex) {
-            if (!(ex instanceof HasHttpStatusCode)) {
-                return 0;
-            }
-            final HasHttpStatusCode hasHttpStatusCode = (HasHttpStatusCode) ex;
-            return hasHttpStatusCode.getHttpStatusCode().getStatusCode();
-        }
-
-        @SuppressWarnings("unused")
-        public int getHttpStatusCode() {
-            return httpStatusCode;
-        }
-
-        @SuppressWarnings("unused")
-        public String getMessage() {
-            return message;
-        }
-
-        @SuppressWarnings("unused")
-        public List<String> getStackTrace() {
-            return stackTrace;
-        }
-
-        @SuppressWarnings("unused")
-        public ExceptionPojo getCausedBy() {
-            return causedBy;
-        }
-
-    }
-
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/807c6ccf/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionPojo.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionPojo.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionPojo.java
new file mode 100644
index 0000000..194344e
--- /dev/null
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RestfulObjectsApplicationExceptionPojo.java
@@ -0,0 +1,88 @@
+/*
+ *  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.restfulobjects.server;
+
+import java.util.List;
+import com.google.common.collect.Lists;
+import org.apache.isis.viewer.restfulobjects.rendering.HasHttpStatusCode;
+
+class RestfulObjectsApplicationExceptionPojo {
+
+    public static RestfulObjectsApplicationExceptionPojo create(final Throwable ex) {
+        return new RestfulObjectsApplicationExceptionPojo(ex);
+    }
+
+    private static String format(final StackTraceElement stackTraceElement) {
+        return stackTraceElement.toString();
+    }
+
+    private final String className;
+    private final int httpStatusCode;
+    private final String message;
+    private final List<String> stackTrace = Lists.newArrayList();
+    private RestfulObjectsApplicationExceptionPojo causedBy;
+
+    public RestfulObjectsApplicationExceptionPojo(final Throwable ex) {
+        this.className = ex.getClass().getName();
+        this.httpStatusCode = getHttpStatusCodeIfAny(ex);
+        this.message = ex.getMessage();
+        final StackTraceElement[] stackTraceElements = ex.getStackTrace();
+        for (final StackTraceElement stackTraceElement : stackTraceElements) {
+            this.stackTrace.add(format(stackTraceElement));
+        }
+        final Throwable cause = ex.getCause();
+        if (cause != null && cause != ex) {
+            this.causedBy = new RestfulObjectsApplicationExceptionPojo(cause);
+        }
+    }
+
+    private int getHttpStatusCodeIfAny(final Throwable ex) {
+        if (!(ex instanceof HasHttpStatusCode)) {
+            return 0;
+        }
+        final HasHttpStatusCode hasHttpStatusCode = (HasHttpStatusCode) ex;
+        return hasHttpStatusCode.getHttpStatusCode().getStatusCode();
+    }
+
+    @SuppressWarnings("unused")
+    public String getClassName() {
+        return className;
+    }
+
+    @SuppressWarnings("unused")
+    public int getHttpStatusCode() {
+        return httpStatusCode;
+    }
+
+    @SuppressWarnings("unused")
+    public String getMessage() {
+        return message;
+    }
+
+    @SuppressWarnings("unused")
+    public List<String> getStackTrace() {
+        return stackTrace;
+    }
+
+    @SuppressWarnings("unused")
+    public RestfulObjectsApplicationExceptionPojo getCausedBy() {
+        return causedBy;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/807c6ccf/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionMapper.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionMapper.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionMapper.java
index 315451c..9e3f062 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionMapper.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionMapper.java
@@ -19,17 +19,15 @@
 package org.apache.isis.viewer.restfulobjects.server;
 
 import java.util.List;
-
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
 import javax.ws.rs.ext.ExceptionMapper;
 import javax.ws.rs.ext.Provider;
-
-import com.google.common.collect.Lists;
-
+import com.google.common.base.Throwables;
 import org.jboss.resteasy.spi.Failure;
-
 import org.apache.isis.core.commons.exceptions.ExceptionUtils;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
 import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
 import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse.HttpStatusCode;
 import org.apache.isis.viewer.restfulobjects.applib.util.JsonMapper;
@@ -39,6 +37,16 @@ public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException>
 
     @Override
     public Response toResponse(final RuntimeException ex) {
+        // since have rendered...
+        final IsisTransaction currentTransaction = IsisContext.getTransactionManager().getTransaction();
+
+        final Throwable rootCause = Throwables.getRootCause(ex);
+        final List<Throwable> causalChain = Throwables.getCausalChain(ex);
+        for (Throwable throwable : causalChain) {
+            if(throwable == rootCause) {
+                currentTransaction.clearAbortCause();
+            }
+        }
         HttpStatusCode statusCode = HttpStatusCode.INTERNAL_SERVER_ERROR;
         if(ex instanceof Failure) {
             Failure failure = (Failure) ex;
@@ -48,56 +56,9 @@ public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException>
         return builder.build();
     }
 
-    private static class ExceptionPojo {
-
-        public static ExceptionPojo create(final Exception ex) {
-            return new ExceptionPojo(ex);
-        }
-
-        private static String format(final StackTraceElement stackTraceElement) {
-            return stackTraceElement.toString();
-        }
-
-        private final String message;
-        private final List<String> stackTrace = Lists.newArrayList();
-        private ExceptionPojo causedBy;
-
-        public ExceptionPojo(final Throwable ex) {
-            this.message = messageFor(ex);
-            final StackTraceElement[] stackTraceElements = ex.getStackTrace();
-            for (final StackTraceElement stackTraceElement : stackTraceElements) {
-                this.stackTrace.add(format(stackTraceElement));
-            }
-            final Throwable cause = ex.getCause();
-            if (cause != null && cause != ex) {
-                this.causedBy = new ExceptionPojo(cause);
-            }
-        }
-
-        private static String messageFor(final Throwable ex) {
-            final String message = ex.getMessage();
-            return message != null ? message : ex.getClass().getName();
-        }
-
-        @SuppressWarnings("unused")
-        public String getMessage() {
-            return message;
-        }
-
-        @SuppressWarnings("unused")
-        public List<String> getStackTrace() {
-            return stackTrace;
-        }
-
-        @SuppressWarnings("unused")
-        public ExceptionPojo getCausedBy() {
-            return causedBy;
-        }
-    }
-
     static String jsonFor(final Exception ex) {
         try {
-            return JsonMapper.instance().write(ExceptionPojo.create(ex));
+            return JsonMapper.instance().write(RuntimeExceptionPojo.create(ex));
         } catch (final Exception e) {
             // fallback
             return "{ \"exception\": \"" + ExceptionUtils.getFullStackTrace(ex) + "\" }";

http://git-wip-us.apache.org/repos/asf/isis/blob/807c6ccf/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionPojo.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionPojo.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionPojo.java
new file mode 100644
index 0000000..f86e4d6
--- /dev/null
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/RuntimeExceptionPojo.java
@@ -0,0 +1,89 @@
+/*
+ *  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.restfulobjects.server;
+
+import java.util.List;
+import javax.jdo.JDOException;
+import com.google.common.collect.Lists;
+
+class RuntimeExceptionPojo {
+
+    public static RuntimeExceptionPojo create(final Exception ex) {
+        return new RuntimeExceptionPojo(ex);
+    }
+
+    private static String format(final StackTraceElement stackTraceElement) {
+        return stackTraceElement.toString();
+    }
+
+    private final String className;
+    private final String message;
+    private final List<String> stackTrace = Lists.newArrayList();
+    private RuntimeExceptionPojo causedBy;
+
+    public RuntimeExceptionPojo(final Throwable ex) {
+        this.className = ex.getClass().getName();
+        this.message = messageFor(ex);
+        final StackTraceElement[] stackTraceElements = ex.getStackTrace();
+        for (final StackTraceElement stackTraceElement : stackTraceElements) {
+            this.stackTrace.add(format(stackTraceElement));
+        }
+
+        final Throwable cause = causeOf(ex);
+        if (cause != null && cause != ex) {
+            this.causedBy = new RuntimeExceptionPojo(cause);
+        }
+    }
+
+    private static Throwable causeOf(Throwable ex) {
+        if (ex instanceof JDOException) {
+            final JDOException jdoException = (JDOException) ex;
+            final Throwable[] nestedExceptions = jdoException.getNestedExceptions();
+            return nestedExceptions.length > 0? nestedExceptions[0]: null;
+        }
+        else {
+            return ex.getCause();
+        }
+    }
+
+    private static String messageFor(final Throwable ex) {
+        final String message = ex.getMessage();
+        return message != null ? message : ex.getClass().getName();
+    }
+
+    @SuppressWarnings("unused")
+    public String getClassName() {
+        return className;
+    }
+
+    @SuppressWarnings("unused")
+    public String getMessage() {
+        return message;
+    }
+
+    @SuppressWarnings("unused")
+    public List<String> getStackTrace() {
+        return stackTrace;
+    }
+
+    @SuppressWarnings("unused")
+    public RuntimeExceptionPojo getCausedBy() {
+        return causedBy;
+    }
+}