MARMOTTA-562: impemented basic json message for http errors

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

Branch: refs/heads/develop
Commit: 3ecce0469f88e48ae0e0649f6e866323f33a48f1
Parents: 0965f73
Author: Sergio Fernández <[email protected]>
Authored: Wed Nov 5 14:29:43 2014 +0100
Committer: Sergio Fernández <[email protected]>
Committed: Wed Nov 5 15:30:50 2014 +0100

----------------------------------------------------------------------
 .../commons/http/MarmottaHttpUtils.java         |  2 +
 .../core/exception/HttpErrorException.java      |  6 +-
 .../platform/core/jaxrs/ErrorMessage.java       | 50 ++++++++++++++
 .../HttpErrorExceptionMapper.java               | 69 ++++++++++++------
 .../core/test/jaxrs/ExceptionHandlingTest.java  | 73 ++++++++++++++++++++
 5 files changed, 176 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/marmotta/blob/3ecce046/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/http/MarmottaHttpUtils.java
----------------------------------------------------------------------
diff --git 
a/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/http/MarmottaHttpUtils.java
 
b/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/http/MarmottaHttpUtils.java
index d1e070c..c0d7ce4 100644
--- 
a/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/http/MarmottaHttpUtils.java
+++ 
b/commons/marmotta-commons/src/main/java/org/apache/marmotta/commons/http/MarmottaHttpUtils.java
@@ -23,6 +23,8 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
 import org.apache.commons.lang3.StringUtils;
 import org.openrdf.query.resultio.QueryResultFormat;
 

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3ecce046/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/exception/HttpErrorException.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/exception/HttpErrorException.java
 
b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/exception/HttpErrorException.java
index 381e9da..aba26cd 100644
--- 
a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/exception/HttpErrorException.java
+++ 
b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/exception/HttpErrorException.java
@@ -24,14 +24,16 @@ import java.util.HashMap;
 import java.util.Map;
 
 /**
- * Resource Not Found Exception
+ * HTTP Error Exception
  *
  * @author Sergio Fernández
  */
 public class HttpErrorException extends Exception {
 
     private final int status;
+
     private final String reason;
+
     private final String uri;
 
     private final Map<String, String> headers;
@@ -80,7 +82,7 @@ public class HttpErrorException extends Exception {
      * @param msg message
      * @param headers custom headers
      */
-    public HttpErrorException(int status, String reason, String uri, String 
msg, Map<String,String> headers) {
+    public HttpErrorException(int status, String reason, String uri, String 
msg, Map<String, String> headers) {
         super(msg);
         this.status = status;
         this.reason = reason;

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3ecce046/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/ErrorMessage.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/ErrorMessage.java
 
b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/ErrorMessage.java
new file mode 100644
index 0000000..b80560f
--- /dev/null
+++ 
b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/ErrorMessage.java
@@ -0,0 +1,50 @@
+/**
+ * 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.marmotta.platform.core.jaxrs;
+
+import org.apache.marmotta.platform.core.exception.HttpErrorException;
+
+/**
+ * Error Message for serialization purposes
+ *
+ * @author Sergio Fernández
+ */
+public class ErrorMessage {
+
+    public String uri;
+
+    public int status;
+
+    public String reason;
+
+    public String message;
+
+    public ErrorMessage(String uri, int status, String reason, String message) 
{
+        this.status = status;
+        this.reason = reason;
+        this.message = message;
+    }
+
+    public ErrorMessage(HttpErrorException exception) {
+        this.uri = exception.getUri();
+        this.status = exception.getStatus();
+        this.reason = exception.getReason();
+        this.message = exception.getMessage();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3ecce046/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/exceptionmappers/HttpErrorExceptionMapper.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/exceptionmappers/HttpErrorExceptionMapper.java
 
b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/exceptionmappers/HttpErrorExceptionMapper.java
index 69aabfe..d91cc43 100644
--- 
a/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/exceptionmappers/HttpErrorExceptionMapper.java
+++ 
b/platform/marmotta-core/src/main/java/org/apache/marmotta/platform/core/jaxrs/exceptionmappers/HttpErrorExceptionMapper.java
@@ -18,9 +18,12 @@ package 
org.apache.marmotta.platform.core.jaxrs.exceptionmappers;
 
 import freemarker.template.TemplateException;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.marmotta.commons.http.ContentType;
+import org.apache.marmotta.commons.http.MarmottaHttpUtils;
 import org.apache.marmotta.platform.core.api.config.ConfigurationService;
 import org.apache.marmotta.platform.core.api.templating.TemplatingService;
 import org.apache.marmotta.platform.core.exception.HttpErrorException;
+import org.apache.marmotta.platform.core.jaxrs.ErrorMessage;
 import org.slf4j.Logger;
 
 import javax.enterprise.context.Dependent;
@@ -30,6 +33,7 @@ import javax.ws.rs.ext.Provider;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -64,34 +68,55 @@ public class HttpErrorExceptionMapper implements 
CDIExceptionMapper<HttpErrorExc
      */
     @Override
     public Response toResponse(HttpErrorException exception) {
-        Map<String, Object> data = new HashMap<String, Object>();
-        data.put("status", exception.getStatus());
-        data.put("reason", exception.getReason());
 
-        data.put("message", exception.getMessage());
-        if (StringUtils.isNotBlank(exception.getUri())) {
-            data.put("uri", exception.getUri());
-            try {
-                data.put("encoded_uri", URLEncoder.encode(exception.getUri(), 
"UTF-8"));
-            } catch (UnsupportedEncodingException uee) {
-                data.put("encoded_uri", exception.getUri());
+        final Map<String, String> exceptionHeaders = exception.getHeaders();
+
+        boolean htmlError = true; //HTML still by default
+        if (exceptionHeaders.containsKey("Accept")) {
+            final String acceptHeader = exceptionHeaders.get("Accept");
+            final ContentType bestContentType = 
MarmottaHttpUtils.bestContentType(Arrays.asList(MarmottaHttpUtils.parseContentType("text/html"),
 MarmottaHttpUtils.parseContentType("application/json")),
+                    
Arrays.asList(MarmottaHttpUtils.parseContentType(acceptHeader)));
+            if 
(bestContentType.matches(MarmottaHttpUtils.parseContentType("application/json")))
 {
+                htmlError = false;
             }
-        } else {
-            data.put("uri", "");
-            data.put("encoded_uri", "");
         }
 
         Response.ResponseBuilder responseBuilder;
-        try {
-            responseBuilder = 
Response.status(exception.getStatus()).entity(templatingService.process(TEMPLATE,
 data));
-        } catch (IOException | TemplateException e) {
-            log.error("Error rendering template {}: {}", TEMPLATE, 
e.getMessage());
-            responseBuilder = 
Response.status(exception.getStatus()).entity(e.getMessage());
+        if (htmlError) {
+            //html rendering
+            Map<String, Object> data = new HashMap<>();
+            data.put("status", exception.getStatus());
+            data.put("reason", exception.getReason());
+
+            data.put("message", exception.getMessage());
+            if (StringUtils.isNotBlank(exception.getUri())) {
+                data.put("uri", exception.getUri());
+                try {
+                    data.put("encoded_uri", 
URLEncoder.encode(exception.getUri(), "UTF-8"));
+                } catch (UnsupportedEncodingException uee) {
+                    data.put("encoded_uri", exception.getUri());
+                }
+            } else {
+                data.put("uri", "");
+                data.put("encoded_uri", "");
+            }
+
+            try {
+                responseBuilder = 
Response.status(exception.getStatus()).entity(templatingService.process(TEMPLATE,
 data));
+            } catch (IOException | TemplateException e) {
+                log.error("Error rendering html error template {}: {}", 
TEMPLATE, e.getMessage());
+                responseBuilder = 
Response.status(exception.getStatus()).entity(e.getMessage());
+            }
+        } else {
+            //simple json error message
+            responseBuilder = 
Response.status(exception.getStatus()).entity(new ErrorMessage(exception));
         }
-        Response response = responseBuilder.build();
-        for (Map.Entry<String, String> entry : 
exception.getHeaders().entrySet()) {
-            response.getMetadata().add(entry.getKey(), entry.getValue());
+
+        //forward headers
+        for (Map.Entry<String, String> entry : exceptionHeaders.entrySet()) {
+            responseBuilder.header(entry.getKey(), entry.getValue());
         }
-        return response;
+
+        return responseBuilder.build();
     }
 }

http://git-wip-us.apache.org/repos/asf/marmotta/blob/3ecce046/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/jaxrs/ExceptionHandlingTest.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/jaxrs/ExceptionHandlingTest.java
 
b/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/jaxrs/ExceptionHandlingTest.java
new file mode 100644
index 0000000..61677c0
--- /dev/null
+++ 
b/platform/marmotta-core/src/test/java/org/apache/marmotta/platform/core/test/jaxrs/ExceptionHandlingTest.java
@@ -0,0 +1,73 @@
+package org.apache.marmotta.platform.core.test.jaxrs;
+
+import com.jayway.restassured.RestAssured;
+import com.jayway.restassured.response.ResponseBody;
+import org.apache.commons.io.IOUtils;
+import org.apache.marmotta.platform.core.api.config.ConfigurationService;
+import org.apache.marmotta.platform.core.exception.MarmottaException;
+import org.apache.marmotta.platform.core.test.base.JettyMarmotta;
+import 
org.apache.marmotta.platform.core.webservices.resource.ResourceWebService;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openrdf.repository.RepositoryException;
+import org.openrdf.rio.RDFParseException;
+
+import java.io.IOException;
+
+import static com.jayway.restassured.RestAssured.expect;
+
+/**
+ * Test for exceptions handling
+ *
+ * @author Sergio Fernández
+ */
+public class ExceptionHandlingTest {
+
+    private static JettyMarmotta marmotta;
+
+    @BeforeClass
+    public static void setUp() throws RepositoryException, IOException, 
RDFParseException {
+        marmotta = new JettyMarmotta("/marmotta", ResourceWebService.class);
+
+        RestAssured.baseURI = "http://localhost";;
+        RestAssured.port = marmotta.getPort();
+        RestAssured.basePath = marmotta.getContext();
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        marmotta.shutdown();
+    }
+
+    @Test
+    public void testNotFound() throws MarmottaException, IOException {
+
+        final ResponseBody response = expect().
+            log().ifError().
+            statusCode(404).
+            contentType("text/html").
+        given().
+            header("Accept", "text/html").
+        when().
+            get(ConfigurationService.RESOURCE_PATH + "/foo").
+            getBody();
+        response.print();
+
+        final ResponseBody responseJson = expect().
+            log().ifError().
+            statusCode(404).
+            contentType("application/json").
+        given().
+            header("Accept", "application/json").
+        when().
+            get(ConfigurationService.RESOURCE_PATH + "/foo").
+            getBody();
+        responseJson.print();
+        Assert.assertEquals(404, responseJson.jsonPath().get("status"));
+        Assert.assertEquals("Not Found", 
responseJson.jsonPath().get("reason"));
+
+    }
+
+}

Reply via email to