Repository: olingo-odata4 Updated Branches: refs/heads/master a9ec75991 -> c58109466
[OLINGO-348] Exceptionhandling on server side and message texts Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/984ca341 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/984ca341 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/984ca341 Branch: refs/heads/master Commit: 984ca3412b5fccc63c749b1a9f3fd8771e8342bf Parents: a9ec759 Author: Christian Amend <[email protected]> Authored: Tue Jul 22 14:13:58 2014 +0200 Committer: Christian Amend <[email protected]> Committed: Tue Jul 22 16:45:13 2014 +0200 ---------------------------------------------------------------------- .../apache/olingo/server/api/ODataResponse.java | 2 +- .../server/api/ODataTranslatedException.java | 10 ++++ .../src/main/resources/i18n.properties | 6 ++- .../apache/olingo/server/core/ODataHandler.java | 51 +++++++++++--------- .../server/core/ODataHttpHandlerImpl.java | 43 +++++++++++++---- .../server/core/ODataHttpHandlerImplTest.java | 22 ++++----- .../olingo/server/core/ODataHandlerTest.java | 5 +- 7 files changed, 93 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataResponse.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataResponse.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataResponse.java index c1a16c0..74d5c61 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataResponse.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataResponse.java @@ -28,7 +28,7 @@ import java.util.Map; */ public class ODataResponse { - private int statusCode; + private int statusCode = 0; private Map<String, String> headers = new HashMap<String, String>(); private InputStream content; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java index 621c38c..d980467 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataTranslatedException.java @@ -36,6 +36,12 @@ public class ODataTranslatedException extends ODataException { private static final String BUNDLE_NAME = "i18n"; private static final Locale DEFAULT_LOCALE = Locale.ENGLISH; + // MessageKeys + public static final String AMBIGUOUS_XHTTP_METHOD = "ODataTranslatedException.AMBIGUOUS_XHTTP_METHOD"; + public static final String HTTP_METHOD_NOT_IMPLEMENTED = "ODataTranslatedException.HTTP_METHOD_NOT_IMPLEMENTED"; + public static final String PROCESSOR_NOT_IMPLEMENTED = "ODataTranslatedException.PROCESSOR_NOT_IMPLEMENTED"; + public static final String ODATA_VERSION_NOT_SUPPORTED = "ODataTranslatedException.ODATA_VERSION_NOT_SUPPORTED"; + private String messageKey; private Object[] parameters; @@ -51,6 +57,10 @@ public class ODataTranslatedException extends ODataException { this.parameters = parameters; } + public String getMessageKey() { + return messageKey; + } + public String getTranslatedMessage(final Locale locale) { if (messageKey == null) { return getMessage(); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-api/src/main/resources/i18n.properties ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/resources/i18n.properties b/lib/server-api/src/main/resources/i18n.properties index cb6f2d3..9b2133c 100644 --- a/lib/server-api/src/main/resources/i18n.properties +++ b/lib/server-api/src/main/resources/i18n.properties @@ -17,4 +17,8 @@ # under the License. #------------------------------------------------------------------------------- # Basic Apache Olingo exception messages -# \ No newline at end of file +# +ODataTranslatedException.AMBIGUOUS_XHTTP_METHOD=x-http-method header '%1$s' and x-http-method-override header '%2$s' are not the same. +ODataTranslatedException.HTTP_METHOD_NOT_IMPLEMENTED=Invalid http method given: '%1$s'. +ODataTranslatedException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered. +ODataTranslatedException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported. \ No newline at end of file http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java index a1f1911..b2ef568 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java @@ -18,6 +18,9 @@ */ package org.apache.olingo.server.core; +import java.util.HashMap; +import java.util.Map; + import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; @@ -27,6 +30,7 @@ import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ODataTranslatedException; import org.apache.olingo.server.api.processor.CollectionProcessor; import org.apache.olingo.server.api.processor.DefaultProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; @@ -39,19 +43,14 @@ import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.core.uri.parser.Parser; import org.apache.olingo.server.core.uri.validator.UriValidator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; -import java.util.Map; public class ODataHandler { - private final static Logger LOG = LoggerFactory.getLogger(ODataHandler.class); - private final OData odata; private final Edm edm; - private Map<Class<? extends Processor>, Processor> processors = new HashMap<Class<? extends Processor>, Processor>(); + private final ODataResponse response; + private final Map<Class<? extends Processor>, Processor> processors = + new HashMap<Class<? extends Processor>, Processor>(); public ODataHandler(final OData server, final Edm edm) { odata = server; @@ -59,12 +58,13 @@ public class ODataHandler { register(new DefaultProcessor()); register(new DefaultRedirectProcessor()); + response = new ODataResponse(); } public ODataResponse process(final ODataRequest request) { - try { - ODataResponse response = new ODataResponse(); + ContentType requestedContentType = null; + try { validateODataVersion(request, response); Parser parser = new Parser(); @@ -75,7 +75,6 @@ public class ODataHandler { UriValidator validator = new UriValidator(); validator.validate(uriInfo, request.getMethod()); - ContentType requestedContentType = null; switch (uriInfo.getKind()) { case metadata: MetadataProcessor mp = selectProcessor(MetadataProcessor.class); @@ -105,16 +104,19 @@ public class ODataHandler { default: throw new ODataRuntimeException("not implemented"); } - - return response; } catch (Exception e) { - // TODO OData error message handling - throw new RuntimeException(e); + ODataExceptionHandler exceptionHandler = new ODataExceptionHandler(); + exceptionHandler.handle(response, e); +// exceptionHandler.setRequestedContentType(requestedContentType); +// exceptionHandler.setRequestedLocale(); +// exceptionHandler.setExceptionProcessor() or setExceptionCallback() } + return response; } private void - handleResourceDispatching(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo) { + handleResourceDispatching(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo) + throws ODataTranslatedException { int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1; UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex); ContentType requestedContentType = null; @@ -175,31 +177,34 @@ public class ODataHandler { } } - private void validateODataVersion(final ODataRequest request, final ODataResponse response) { + private void validateODataVersion(final ODataRequest request, final ODataResponse response) + throws ODataTranslatedException { String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION); + response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString()); if (maxVersion != null) { if (ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) { - throw new ODataRuntimeException("400 Bad Request - ODataVersion not supported: " + maxVersion); + response.setStatusCode(400); + throw new ODataTranslatedException("ODataVersion not supported: " + maxVersion, + ODataTranslatedException.ODATA_VERSION_NOT_SUPPORTED, maxVersion); } } - - response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString()); } - private <T extends Processor> T selectProcessor(final Class<T> cls) { + private <T extends Processor> T selectProcessor(final Class<T> cls) throws ODataTranslatedException { @SuppressWarnings("unchecked") T p = (T) processors.get(cls); if (p == null) { - throw new ODataRuntimeException("Not implemented"); + response.setStatusCode(501); + throw new ODataTranslatedException("Processor: " + cls.getName() + " not registered.", + ODataTranslatedException.PROCESSOR_NOT_IMPLEMENTED, cls.getName()); } return p; } public void register(final Processor processor) { - processor.init(odata, edm); for (Class<?> cls : processor.getClass().getInterfaces()) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java index 06f0559..891cb4c 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHttpHandlerImpl.java @@ -22,10 +22,12 @@ import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpMethod; +import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataHttpHandler; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ODataTranslatedException; import org.apache.olingo.server.api.processor.Processor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,13 +54,34 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler { @Override public void process(final HttpServletRequest request, final HttpServletResponse response) { - ODataRequest odRequest = createODataRequest(request, 0); - - ODataResponse odResponse = handler.process(odRequest); + ODataRequest odRequest = null; + ODataResponse odResponse = null; + try { + odRequest = createODataRequest(request, 0); + odResponse = handler.process(odRequest); + // ALL future methods after process must not throw exceptions! + } catch (Exception e) { + odResponse = handleException(e); + } convertToHttp(response, odResponse); } + private ODataResponse handleException(Exception e) { + ODataResponse resp = new ODataResponse(); + if (e instanceof ODataTranslatedException) { + ODataTranslatedException exp = (ODataTranslatedException) e; + if (exp.getMessageKey() == ODataTranslatedException.AMBIGUOUS_XHTTP_METHOD) { + resp.setStatusCode(HttpStatusCode.BAD_REQUEST.getStatusCode()); + } else if (exp.getMessageKey() == ODataTranslatedException.HTTP_METHOD_NOT_IMPLEMENTED) { + resp.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode()); + } + } + ODataExceptionHandler exceptionHandler = new ODataExceptionHandler(); + exceptionHandler.handle(resp, e); + return resp; + } + static void convertToHttp(final HttpServletResponse response, final ODataResponse odResponse) { response.setStatus(odResponse.getStatusCode()); @@ -91,7 +114,8 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler { } } - private ODataRequest createODataRequest(final HttpServletRequest httpRequest, final int split) { + private ODataRequest createODataRequest(final HttpServletRequest httpRequest, final int split) + throws ODataTranslatedException { try { ODataRequest odRequest = new ODataRequest(); @@ -106,9 +130,9 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler { } } - static void extractMethod(final ODataRequest odRequest, final HttpServletRequest httpRequest) { + static void extractMethod(final ODataRequest odRequest, final HttpServletRequest httpRequest) + throws ODataTranslatedException { try { - HttpMethod httpRequestMethod = HttpMethod.valueOf(httpRequest.getMethod()); if (httpRequestMethod == HttpMethod.POST) { @@ -123,7 +147,8 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler { odRequest.setMethod(HttpMethod.valueOf(xHttpMethod)); } else { if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) { - throw new ODataRuntimeException("!!! HTTP 400 !!! Ambiguous X-HTTP-Methods!"); + throw new ODataTranslatedException("Ambiguous X-HTTP-Methods", + ODataTranslatedException.AMBIGUOUS_XHTTP_METHOD, xHttpMethod, xHttpMethodOverride); } odRequest.setMethod(HttpMethod.valueOf(xHttpMethod)); } @@ -131,12 +156,12 @@ public class ODataHttpHandlerImpl implements ODataHttpHandler { odRequest.setMethod(httpRequestMethod); } } catch (IllegalArgumentException e) { - throw new ODataRuntimeException("!!! HTTP 501 !!!"); + throw new ODataTranslatedException("Invalid http method" + httpRequest.getMethod(), + ODataTranslatedException.HTTP_METHOD_NOT_IMPLEMENTED, httpRequest.getMethod()); } } static void extractUri(final ODataRequest odRequest, final HttpServletRequest httpRequest, final int split) { - String rawRequestUri = httpRequest.getRequestURL().toString(); String rawODataPath; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java index 9719a52..03fc0ea 100644 --- a/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/ODataHttpHandlerImplTest.java @@ -18,26 +18,26 @@ */ package org.apache.olingo.server.core; -import org.apache.olingo.commons.api.ODataRuntimeException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import javax.servlet.http.HttpServletRequest; + import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataTranslatedException; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.servlet.http.HttpServletRequest; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - public class ODataHttpHandlerImplTest { private final Logger LOG = LoggerFactory.getLogger(ODataHttpHandlerImplTest.class); @Test - public void extractMethod() { + public void extractMethod() throws Exception { String[][] mm = { { "GET", null, null, "GET" }, { "GET", "xxx", "yyy", "GET" }, @@ -72,7 +72,7 @@ public class ODataHttpHandlerImplTest { } @Test - public void extractMethodFail() { + public void extractMethodFail() throws Exception { String[][] mm = { { "POST", "bla", null }, { "POST", "MERGE", "PATCH" }, @@ -92,7 +92,7 @@ public class ODataHttpHandlerImplTest { try { ODataHttpHandlerImpl.extractMethod(odr, hr); fail(); - } catch (ODataRuntimeException e) {} + } catch (ODataTranslatedException e) {} } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/984ca341/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java index 2566c32..86366b5 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java @@ -34,6 +34,8 @@ import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Before; import org.junit.Test; +import com.sun.org.apache.bcel.internal.generic.GETSTATIC; + import java.util.Arrays; import static org.junit.Assert.assertEquals; @@ -172,7 +174,7 @@ public class ODataHandlerTest { assertEquals(ODataServiceVersion.V40.toString(), response.getHeaders().get(HttpHeader.ODATA_VERSION)); } - @Test(expected = Exception.class) + @Test public void testMaxVersionNotSupported() { ODataRequest request = new ODataRequest(); @@ -184,6 +186,7 @@ public class ODataHandlerTest { assertNotNull(response); assertEquals(ODataServiceVersion.V40.toString(), response.getHeaders().get(HttpHeader.ODATA_VERSION)); + assertEquals(400, response.getStatusCode()); } }
