diff --git a/exception-handler/src/main/java/com/raychatter/common/annotation/AnnotationHandler.java b/exception-handler/src/main/java/com/raychatter/common/annotation/AnnotationHandler.java
index f88f3fd..353b05f 100644
--- a/exception-handler/src/main/java/com/raychatter/common/annotation/AnnotationHandler.java
+++ b/exception-handler/src/main/java/com/raychatter/common/annotation/AnnotationHandler.java
@@ -1,6 +1,8 @@
package com.raychatter.common.annotation;
import org.springframework.core.io.ClassPathResource;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
@@ -12,23 +14,28 @@ import java.util.Scanner;
public class AnnotationHandler implements HandlerExceptionResolver {
- protected static final String DEFAULT_ERROR_STRING = "Error: %s";
+ protected static final String DEFAULT_ERROR_STRING = "%s";
protected static final String USER_TEMPLATE = "error.template";
protected static final String DEFAULT_TEMPLATE = "defaults/default.template";
private static final String UTF_8 = "UTF-8";
@Override
public ModelAndView resolveException(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception thrownException) {
- final ExceptionHandler annotation = thrownException.getClass().getAnnotation(ExceptionHandler.class);
+ final ExceptionHandler annotation = getAnnotationFrom(thrownException);
- if (annotation == null) {
- return new ModelAndView();
+ if (annotation == null) return new ModelAndView();
+
+ try {
+ return handleException(annotation, thrownException, response);
+ } catch (IOException e) {
+ // potentially something went wrong in response itself
+ e.printStackTrace();
}
- return handleException(annotation, thrownException, response);
+ return new ModelAndView();
}
- protected ModelAndView handleException(final ExceptionHandler annotation, final Exception thrownException, final HttpServletResponse response) {
+ protected ModelAndView handleException(final ExceptionHandler annotation, final Exception thrownException, final HttpServletResponse response) throws IOException {
response.setContentType(annotation.contentType());
response.setStatus(annotation.httpStatus().value());
@@ -36,20 +43,18 @@ public class AnnotationHandler implements HandlerExceptionResolver {
final String message = formatMessage(thrownException);
response.getWriter().write(message);
} catch (IOException e) {
- //TODO: Potentially this can be handled differently than the template errors
-// response.setContentType(MediaType.APPLICATION_XML_VALUE);
-// response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
-//
-// try {
-// response.getWriter().write(formatDefaultMessage(thrownException));
-// } catch (IOException ex) {
-// ex.printStackTrace();
-// }
+ response.setContentType(MediaType.APPLICATION_XML_VALUE);
+ response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ response.getWriter().write(formatDefaultMessage(thrownException));
}
return new ModelAndView();
}
+ protected ExceptionHandler getAnnotationFrom(Exception thrownException) {
+ return thrownException.getClass().getAnnotation(ExceptionHandler.class);
+ }
+
protected String formatMessage(final Exception thrownException) throws IOException {
return String.format(readTemplate(), thrownException.getMessage());
}
diff --git a/exception-handler/src/main/java/com/raychatter/common/annotation/ExceptionHandler.java b/exception-handler/src/main/java/com/raychatter/common/annotation/ExceptionHandler.java
index 3461b94..9e7dda9 100644
--- a/exception-handler/src/main/java/com/raychatter/common/annotation/ExceptionHandler.java
+++ b/exception-handler/src/main/java/com/raychatter/common/annotation/ExceptionHandler.java
@@ -19,5 +19,5 @@ import java.lang.annotation.Target;
ElementType.TYPE})
public @interface ExceptionHandler {
HttpStatus httpStatus() default HttpStatus.INTERNAL_SERVER_ERROR;
- String contentType() default MediaType.TEXT_PLAIN_VALUE;
+ String contentType() default MediaType.APPLICATION_XML_VALUE;
}
diff --git a/exception-handler/src/test/java/com/raychatter/common/annotation/AnnotationHandlerTest.java b/exception-handler/src/test/java/com/raychatter/common/annotation/AnnotationHandlerTest.java
index 7815180..83e35f4 100644
--- a/exception-handler/src/test/java/com/raychatter/common/annotation/AnnotationHandlerTest.java
+++ b/exception-handler/src/test/java/com/raychatter/common/annotation/AnnotationHandlerTest.java
@@ -4,6 +4,7 @@ import junit.framework.Assert;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
@@ -12,12 +13,7 @@ import java.io.InputStream;
import java.io.PrintWriter;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
public class AnnotationHandlerTest {
@@ -93,7 +89,8 @@ public class AnnotationHandlerTest {
Assert.assertEquals(expectedDefaultTemplateString, actual);
}
- @Test public void handleException_ShouldRenderDefaultContentType_WhenNoAnnotationAttributesGiven() throws Exception {
+ @Test
+ public void handleException_ShouldRenderDefaultContentType_WhenNoAnnotationAttributesGiven() throws Exception {
final String emptyString = "";
final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
@@ -106,10 +103,11 @@ public class AnnotationHandlerTest {
sut.handleException(TestExceptionWithNoAnnotationAttributes.class.getAnnotation(ExceptionHandler.class), null, mockResponse);
- verify(mockResponse).setContentType(MediaType.TEXT_PLAIN_VALUE);
+ verify(mockResponse).setContentType(MediaType.APPLICATION_XML_VALUE);
}
- @Test public void handleException_ShouldRenderDefaultHttpStatusCode_WhenNoAnnotationAttributesGiven() throws Exception {
+ @Test
+ public void handleException_ShouldRenderDefaultHttpStatusCode_WhenNoAnnotationAttributesGiven() throws Exception {
final String emptyString = "";
final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
@@ -125,7 +123,8 @@ public class AnnotationHandlerTest {
verify(mockResponse).setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
}
- @Test public void handleException_ShouldRenderNotFoundHttpStatusCode_WhenNotFoundAnnotationAttributeIsGiven() throws Exception {
+ @Test
+ public void handleException_ShouldRenderNotFoundHttpStatusCode_WhenNotFoundAnnotationAttributeIsGiven() throws Exception {
final String emptyString = "";
final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
@@ -141,7 +140,8 @@ public class AnnotationHandlerTest {
verify(mockResponse).setStatus(HttpStatus.NOT_FOUND.value());
}
- @Test public void handleException_ShouldRenderXmlContentType_WhenXmlContentTypeAnnotationAttributeIsGiven() throws Exception {
+ @Test
+ public void handleException_ShouldRenderXmlContentType_WhenXmlContentTypeAnnotationAttributeIsGiven() throws Exception {
final String emptyString = "";
final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
@@ -157,7 +157,8 @@ public class AnnotationHandlerTest {
verify(mockResponse).setContentType(MediaType.APPLICATION_XML_VALUE);
}
- @Test public void handleException_ShouldRenderUserMessage_WhenUserTemplateIsGiven() throws Exception {
+ @Test
+ public void handleException_ShouldRenderUserMessage_WhenUserTemplateIsGiven() throws Exception {
final String expectedUserTemplate = "USER TEMPLATE: %s";
final String expectedErrorMessage = "ERROR MESSAGE";
final String expectedErrorBody = "USER TEMPLATE: ERROR MESSAGE";
@@ -175,6 +176,70 @@ public class AnnotationHandlerTest {
verify(mockPrinter).write(expectedErrorBody);
}
+ @Test
+ public void handleException_ShouldReturnXmlContentType_WhenNoUserTemplateGiven() throws Exception {
+ final String emptyString = "";
+ final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ final PrintWriter mockPrinter = mock(PrintWriter.class);
+ when(mockResponse.getWriter()).thenReturn(mockPrinter);
+
+ final AnnotationHandler sut = spy(new AnnotationHandler());
+ doThrow(IOException.class).when(sut).getResource(AnnotationHandler.USER_TEMPLATE);
+ doReturn(emptyString).when(sut).formatDefaultMessage(null);
+
+ sut.handleException(TestExceptionWithNoContentStatusCodeAndTextContentType.class.getAnnotation(ExceptionHandler.class), null, mockResponse);
+
+ verify(mockResponse).setContentType(MediaType.APPLICATION_XML_VALUE);
+ }
+
+ @Test
+ public void handleException_ShouldReturnInternalServerErrorStatusCode_WhenNoUserTemplateGiven() throws Exception {
+ final String emptyString = "";
+ final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ final PrintWriter mockPrinter = mock(PrintWriter.class);
+ when(mockResponse.getWriter()).thenReturn(mockPrinter);
+
+ final AnnotationHandler sut = spy(new AnnotationHandler());
+ doThrow(IOException.class).when(sut).getResource(AnnotationHandler.USER_TEMPLATE);
+ doReturn(emptyString).when(sut).formatDefaultMessage(null);
+
+ sut.handleException(TestExceptionWithNoContentStatusCodeAndTextContentType.class.getAnnotation(ExceptionHandler.class), null, mockResponse);
+
+ verify(mockResponse).setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ }
+
+ @Test
+ public void handleException_ShouldRenderDefaultTemplate_WhenNoUserTemplateGiven() throws Exception {
+ final String expectedDefaultTemplate = "DEFAULT TEMPLATE: %s";
+ final String expectedErrorMessage = "ERROR MESSAGE";
+ final String expectedErrorBody = "DEFAULT TEMPLATE: ERROR MESSAGE";
+ final TestExceptionWithNoContentStatusCodeAndTextContentType expectedException = new TestExceptionWithNoContentStatusCodeAndTextContentType(expectedErrorMessage);
+ final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ final PrintWriter mockPrinter = mock(PrintWriter.class);
+ when(mockResponse.getWriter()).thenReturn(mockPrinter);
+
+ final AnnotationHandler sut = spy(new AnnotationHandler());
+ doThrow(IOException.class).when(sut).getResource(AnnotationHandler.USER_TEMPLATE);
+ doReturn(new ByteArrayInputStream(expectedDefaultTemplate.getBytes())).when(sut).getResource(AnnotationHandler.DEFAULT_TEMPLATE);
+
+ sut.handleException(expectedException.getClass().getAnnotation(ExceptionHandler.class), expectedException, mockResponse);
+
+ verify(mockPrinter).write(expectedErrorBody);
+ }
+
+ @Test public void resolveException_ShouldReturnCustomErrorMessage_WhenValidExceptionWithAnnotationIsGiven() throws Exception {
+ final ExceptionHandler mockAnnotation = mock(ExceptionHandler.class);
+ final HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+ final TestExceptionWithNoAnnotationAttributes expectedException = new TestExceptionWithNoAnnotationAttributes("");
+
+ final AnnotationHandler sut = spy(new AnnotationHandler());
+ doReturn(new ModelAndView()).when(sut).handleException(mockAnnotation, expectedException, mockResponse);
+ doReturn(mockAnnotation).when(sut).getAnnotationFrom(expectedException);
+
+ final ModelAndView view = sut.resolveException(null, mockResponse, null, expectedException);
+
+ verify(sut).handleException(mockAnnotation, expectedException, mockResponse);
+ }
}
@ExceptionHandler()
@@ -185,8 +250,17 @@ class TestExceptionWithNoAnnotationAttributes extends Exception {
}
@ExceptionHandler(contentType = MediaType.APPLICATION_XML_VALUE)
-class TestExceptionWithXmlContentType extends Exception { }
+class TestExceptionWithXmlContentType extends Exception {
+}
@ExceptionHandler(httpStatus = HttpStatus.NOT_FOUND)
-class TestExceptionWithNotFoundStatusCode extends Exception { }
+class TestExceptionWithNotFoundStatusCode extends Exception {
+}
+
+@ExceptionHandler(contentType = MediaType.TEXT_PLAIN_VALUE, httpStatus = HttpStatus.NO_CONTENT)
+class TestExceptionWithNoContentStatusCodeAndTextContentType extends Exception {
+ public TestExceptionWithNoContentStatusCodeAndTextContentType(final String s) {
+ super(s);
+ }
+}
diff --git a/sample/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml b/sample/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
index c75b2d8..2ec066d 100755
--- a/sample/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
+++ b/sample/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
@@ -20,6 +20,6 @@
-
+
\ No newline at end of file