You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/08/14 14:32:33 UTC

git commit: [OLINGO-348] Improved server exception handling

Repository: olingo-odata4
Updated Branches:
  refs/heads/master 977905919 -> cb7a8620c


[OLINGO-348] Improved server exception handling


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/cb7a8620
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/cb7a8620
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/cb7a8620

Branch: refs/heads/master
Commit: cb7a8620c263ed4195a6f6926592c131ac6aa585
Parents: 9779059
Author: Michael Bolz <mi...@sap.com>
Authored: Thu Aug 14 13:43:24 2014 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Thu Aug 14 14:08:08 2014 +0200

----------------------------------------------------------------------
 .../olingo/fit/tecsvc/client/BasicITCase.java   |  33 ++++--
 .../server/api/ODataTranslatedException.java    |  25 +++--
 .../serializer/ODataSerializerException.java    |  12 ++-
 .../server/api/TranslatedExceptionsTest.java    |  10 +-
 .../server/core/ContentNegotiatorException.java |  12 ++-
 .../apache/olingo/server/core/ODataHandler.java |   6 +-
 .../server/core/ODataHandlerException.java      |  13 ++-
 .../core/uri/parser/UriParserException.java     |   5 +
 .../uri/parser/UriParserSemanticException.java  |   7 +-
 .../uri/parser/UriParserSyntaxException.java    |   7 +-
 .../uri/validator/UriValidationException.java   |  12 ++-
 .../server/core/uri/validator/UriValidator.java |  92 ++++++++---------
 .../src/main/resources/i18n.properties          |  87 ----------------
 .../server-core-exceptions-i18n.properties      |  87 ++++++++++++++++
 .../core/TranslatedExceptionSubclassesTest.java | 100 +++++++++++++++++++
 15 files changed, 349 insertions(+), 159 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
index 51be0c8..07d0159 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
@@ -24,13 +24,14 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
-import java.net.URI;
 import java.util.Collections;
 import java.util.List;
 
 import org.apache.olingo.client.api.CommonODataClient;
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
 import org.apache.olingo.client.api.communication.request.retrieve.EdmMetadataRequest;
 import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
 import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
@@ -38,6 +39,7 @@ import org.apache.olingo.client.api.communication.request.retrieve.ODataServiceD
 import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
 import org.apache.olingo.client.api.v4.ODataClient;
 import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.domain.ODataError;
 import org.apache.olingo.commons.api.domain.ODataServiceDocument;
 import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
 import org.apache.olingo.commons.api.domain.v4.ODataEntity;
@@ -47,8 +49,8 @@ import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.format.ODataFormat;
-import org.apache.olingo.fit.AbstractBaseTestITCase;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
 import org.apache.olingo.fit.server.StringHelper;
 import org.apache.olingo.fit.tecsvc.TecSvcConst;
 import org.junit.Before;
@@ -103,7 +105,8 @@ public class BasicITCase extends AbstractBaseTestITCase {
   @Test
   public void readEntitySet() {
     final ODataEntitySetRequest<ODataEntitySet> request = odata.getRetrieveRequestFactory()
-        .getEntitySetRequest(URI.create(SERVICE_URI + "/ESMixPrimCollComp"));
+        .getEntitySetRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESMixPrimCollComp").build());
     assertNotNull(request);
 
     final ODataRetrieveResponse<ODataEntitySet> response = request.execute();
@@ -130,9 +133,27 @@ public class BasicITCase extends AbstractBaseTestITCase {
   }
 
   @Test
+  public void readException() throws Exception {
+    final ODataEntityRequest<ODataEntity> request = odata.getRetrieveRequestFactory()
+        .getEntityRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESMixPrimCollComp").appendKeySegment("42").build());
+    assertNotNull(request);
+
+    try {
+      request.execute();
+      fail("Expected Exception not thrown!");
+    } catch (final ODataClientErrorException e) {
+      assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), e.getStatusLine().getStatusCode());
+      final ODataError error = e.getODataError();
+      assertThat(error.getMessage(), containsString("key property"));
+    }
+  }
+
+  @Test
   public void readEntityRawResult() throws IOException {
     final ODataEntityRequest<ODataEntity> request = odata.getRetrieveRequestFactory()
-        .getEntityRequest(URI.create(SERVICE_URI + "/ESCollAllPrim(1)"));
+        .getEntityRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESCollAllPrim").appendKeySegment(1).build());
     assertNotNull(request);
 
     final ODataRetrieveResponse<ODataEntity> response = request.execute();
@@ -167,7 +188,7 @@ public class BasicITCase extends AbstractBaseTestITCase {
     assertEquals(expectedResult, s.asString());
   }
 
-  @Override protected CommonODataClient getClient() {
-    return null;
+  @Override protected CommonODataClient<?> getClient() {
+    return ODataClientFactory.getV4();
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/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 b7477b9..bb3bf72 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
@@ -29,15 +29,18 @@ import org.apache.olingo.commons.api.ODataException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Abstract superclass of all translatable server exceptions.
+ */
 public abstract class ODataTranslatedException extends ODataException {
 
   private static final long serialVersionUID = -1210541002198287561L;
   private static final Logger log = LoggerFactory.getLogger(ODataTranslatedException.class);
-  private static final String BUNDLE_NAME = "i18n";
-
-  public static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
+  private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
 
-  protected static interface MessageKey {}
+  public static interface MessageKey {
+    public String getKey();
+  }
 
   private MessageKey messageKey;
   private Object[] parameters;
@@ -81,9 +84,17 @@ public abstract class ODataTranslatedException extends ODataException {
     return buildMessage(bundle, locale);
   }
 
+  /**
+   * <p>Gets the name of the {@link ResourceBundle} containing the exception texts.</p>
+   * <p>The key for an exception text is the concatenation of the exception-class name and
+   * the {@link MessageKey}, separated by a dot.</p>
+   * @return the name of the resource bundle
+   */
+  protected abstract String getBundleName();
+
   private ResourceBundle createResourceBundle(final Locale locale) {
     try {
-      return ResourceBundle.getBundle(BUNDLE_NAME, locale == null ? DEFAULT_LOCALE : locale);
+      return ResourceBundle.getBundle(getBundleName(), locale == null ? DEFAULT_LOCALE : locale);
     } catch (final MissingResourceException e) {
       log.error(e.getMessage(), e);
       return null;
@@ -94,7 +105,7 @@ public abstract class ODataTranslatedException extends ODataException {
     String message = null;
 
     try {
-      message = bundle.getString(getClass().getSimpleName() + '.' + messageKey);
+      message = bundle.getString(getClass().getSimpleName() + '.' + messageKey.getKey());
       StringBuilder builder = new StringBuilder();
       Formatter f = new Formatter(builder, locale);
       f.format(message, parameters);
@@ -105,7 +116,7 @@ public abstract class ODataTranslatedException extends ODataException {
       }
       return new ODataErrorMessage(builder.toString(), usedLocale);
     } catch (MissingResourceException e) {
-      return new ODataErrorMessage("Missing message for key '" + messageKey + "'!", DEFAULT_LOCALE);
+      return new ODataErrorMessage("Missing message for key '" + messageKey.getKey() + "'!", DEFAULT_LOCALE);
     } catch (MissingFormatArgumentException e) {
       return new ODataErrorMessage("Missing replacement for place holder in message '" + message +
           "' for following arguments '" + Arrays.toString(parameters) + "'!", DEFAULT_LOCALE);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerException.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerException.java
index b347238..b4fcd19 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerException.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerException.java
@@ -34,7 +34,12 @@ public class ODataSerializerException extends ODataTranslatedException {
     /** parameter: property name */ UNSUPPORTED_PROPERTY_TYPE,
     /** parameter: property name */ INCONSISTENT_PROPERTY_TYPE,
     /** parameter: property name */ MISSING_PROPERTY,
-    /** parameters: property name, property value */ WRONG_PROPERTY_VALUE
+    /** parameters: property name, property value */ WRONG_PROPERTY_VALUE;
+
+    @Override
+    public String getKey() {
+      return name();
+    }
   }
 
   public ODataSerializerException(final String developmentMessage,
@@ -46,4 +51,9 @@ public class ODataSerializerException extends ODataTranslatedException {
       final MessageKey messageKey, final String... parameters) {
     super(developmentMessage, cause, messageKey, parameters);
   }
+
+  @Override
+  protected String getBundleName() {
+    return "server-core-exceptions-i18n";
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-api/src/test/java/org/apache/olingo/server/api/TranslatedExceptionsTest.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/test/java/org/apache/olingo/server/api/TranslatedExceptionsTest.java b/lib/server-api/src/test/java/org/apache/olingo/server/api/TranslatedExceptionsTest.java
index 5047f3e..c22546b 100644
--- a/lib/server-api/src/test/java/org/apache/olingo/server/api/TranslatedExceptionsTest.java
+++ b/lib/server-api/src/test/java/org/apache/olingo/server/api/TranslatedExceptionsTest.java
@@ -35,11 +35,19 @@ public class TranslatedExceptionsTest {
   private static class TestException extends ODataTranslatedException {
     private static final long serialVersionUID = -7199975861656921724L;
     public static enum Keys implements MessageKey {
-      BASIC, ONEPARAM, TWOPARAM, NOMESSAGE, ONLY_ROOT, ONLY_GERMAN
+      BASIC, ONEPARAM, TWOPARAM, NOMESSAGE, ONLY_ROOT, ONLY_GERMAN;
+      @Override
+      public String getKey() {
+        return name();
+      }
     }
     protected TestException(final MessageKey messageKey, final String... parameters) {
       super(DEV, messageKey, parameters);
     }
+    @Override
+    protected String getBundleName() {
+      return "i18n";
+    }
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
index 6e0d823..0b1eb60 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java
@@ -31,7 +31,12 @@ public class ContentNegotiatorException extends ODataTranslatedException {
     /** parameter: content type */
     UNSUPPORTED_CONTENT_TYPE,
     /** parameter: format string */
-    UNSUPPORTED_FORMAT_OPTION
+    UNSUPPORTED_FORMAT_OPTION;
+
+    @Override
+    public String getKey() {
+      return name();
+    }
   }
 
   public ContentNegotiatorException(String developmentMessage, MessageKey messageKey, String... parameters) {
@@ -42,4 +47,9 @@ public class ContentNegotiatorException extends ODataTranslatedException {
       String... parameters) {
     super(developmentMessage, cause, messageKey, parameters);
   }
+
+  @Override
+  protected String getBundleName() {
+    return "server-core-exceptions-i18n";
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/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 71a69b8..de4851f 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
@@ -75,7 +75,11 @@ public class ODataHandler {
 
     } catch (final UriParserException e) {
       handleException(request, response,
-          ODataExceptionHelper.createServerErrorObject(e, HttpStatusCode.BAD_REQUEST.getStatusCode()),
+          ODataExceptionHelper.createServerErrorObject(e, HttpStatusCode.BAD_REQUEST.getStatusCode(), null),
+          requestedContentType);      
+    } catch (final UriValidationException e) {
+      handleException(request, response,
+          ODataExceptionHelper.createServerErrorObject(e, HttpStatusCode.BAD_REQUEST.getStatusCode(), null),
           requestedContentType);      
     } catch (ContentNegotiatorException e) {
       Locale requestedLocale = null;

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
index 589504c..8c92ce0 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java
@@ -29,7 +29,12 @@ public class ODataHandlerException extends ODataTranslatedException {
     /** parameter: HTTP method */ HTTP_METHOD_NOT_IMPLEMENTED,
     /** parameter: processor interface */ PROCESSOR_NOT_IMPLEMENTED,
     FUNCTIONALITY_NOT_IMPLEMENTED,
-    /** parameter: version */ ODATA_VERSION_NOT_SUPPORTED
+    /** parameter: version */ ODATA_VERSION_NOT_SUPPORTED;
+
+    @Override
+    public String getKey() {
+      return name();
+    }
   }
 
   public ODataHandlerException(final String developmentMessage, final MessageKey messageKey,
@@ -37,8 +42,8 @@ public class ODataHandlerException extends ODataTranslatedException {
     super(developmentMessage, messageKey, parameters);
   }
 
-  public ODataHandlerException(final String developmentMessage, final Throwable cause, final MessageKey messageKey,
-      final String... parameters) {
-    super(developmentMessage, cause, messageKey, parameters);
+  @Override
+  protected String getBundleName() {
+    return "server-core-exceptions-i18n";
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserException.java
index 5f509ce..5981722 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserException.java
@@ -32,4 +32,9 @@ abstract public class UriParserException extends ODataTranslatedException {
       String... parameters) {
     super(developmentMessage, cause, messageKey, parameters);
   }
+
+  @Override
+  protected String getBundleName() {
+    return "server-core-exceptions-i18n";
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
index 7d742bc..48e8647 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
@@ -49,7 +49,12 @@ public class UriParserSemanticException extends UriParserException {
     ONLY_SIMPLE_AND_COMPLEX_PROPERTIES_IN_SELECT,
     COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED,
     NOT_FOR_ENTITY_TYPE,
-    PREVIOUS_PART_TYPED
+    PREVIOUS_PART_TYPED;
+
+    @Override
+    public String getKey() {
+      return name();
+    }
   }
 
   public UriParserSemanticException(String developmentMessage, MessageKey messageKey, String... parameters) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSyntaxException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSyntaxException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSyntaxException.java
index 393855b..dd73236 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSyntaxException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSyntaxException.java
@@ -27,7 +27,12 @@ public class UriParserSyntaxException extends UriParserException {
     /** parameter: query-option name */ UNKNOWN_SYSTEM_QUERY_OPTION,
     /** parameters: query-option name, query-option value */ WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION,
     SYNTAX,
-    SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE
+    SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE;
+
+    @Override
+    public String getKey() {
+      return name();
+    }
   }
 
   public UriParserSyntaxException(String developmentMessage, MessageKey messageKey, String... parameters) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
index d5c7c0a..e70c6aa 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidationException.java
@@ -50,7 +50,12 @@ public class UriValidationException extends ODataTranslatedException {
     /** parameter: unallowed kind before $value */
     UNALLOWED_KIND_BEFORE_VALUE,
     /** parameter: unallowed kind before $count */
-    UNALLOWED_KIND_BEFORE_COUNT
+    UNALLOWED_KIND_BEFORE_COUNT;
+
+    @Override
+    public String getKey() {
+      return name();
+    }
   }
   
   public UriValidationException(String developmentMessage, MessageKey messageKey, String... parameters) {
@@ -61,4 +66,9 @@ public class UriValidationException extends ODataTranslatedException {
       String... parameters) {
     super(developmentMessage, cause, messageKey, parameters);
   }
+
+  @Override
+  protected String getBundleName() {
+    return "server-core-exceptions-i18n";
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index 24c9462..a164894 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -18,6 +18,9 @@
  */
 package org.apache.olingo.server.core.uri.validator;
 
+import java.util.HashMap;
+import java.util.List;
+
 import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmActionImport;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
@@ -26,9 +29,9 @@ import org.apache.olingo.commons.api.edm.EdmFunctionImport;
 import org.apache.olingo.commons.api.edm.EdmKeyPropertyRef;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmProperty;
 import org.apache.olingo.commons.api.edm.EdmReturnType;
 import org.apache.olingo.commons.api.edm.EdmSingleton;
-import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.apache.olingo.server.api.uri.UriInfo;
@@ -44,9 +47,6 @@ import org.apache.olingo.server.api.uri.UriResourceSingleton;
 import org.apache.olingo.server.api.uri.queryoption.SystemQueryOption;
 import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
 
-import java.util.HashMap;
-import java.util.List;
-
 public class UriValidator {
 
   //@formatter:off (Eclipse formatter)
@@ -613,61 +613,57 @@ public class UriValidator {
   }
 
   private void validateKeyPredicateTypes(final UriInfo uriInfo) throws UriValidationException {
-    try {
-      for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
-        if (pathSegment.getKind() == UriResourceKind.entitySet) {
-          UriResourceEntitySet pathEntitySet = (UriResourceEntitySet) pathSegment;
-
-          EdmEntityType type = pathEntitySet.getEntityType();
-          List<EdmKeyPropertyRef> keys = type.getKeyPropertyRefs();
-          List<UriParameter> keyPredicates = pathEntitySet.getKeyPredicates();
-
-          if (null != keyPredicates) {
-
-            HashMap<String, EdmKeyPropertyRef> edmKeys = new HashMap<String, EdmKeyPropertyRef>();
-            for (EdmKeyPropertyRef key : keys) {
-              edmKeys.put(key.getKeyPropertyName(), key);
-              String alias = key.getAlias();
-              if (null != alias) {
-                edmKeys.put(alias, key);
-              }
+    for (UriResource pathSegment : uriInfo.getUriResourceParts()) {
+      if (pathSegment.getKind() == UriResourceKind.entitySet) {
+        UriResourceEntitySet pathEntitySet = (UriResourceEntitySet) pathSegment;
+
+        EdmEntityType type = pathEntitySet.getEntityType();
+        List<EdmKeyPropertyRef> keys = type.getKeyPropertyRefs();
+        List<UriParameter> keyPredicates = pathEntitySet.getKeyPredicates();
+
+        if (null != keyPredicates) {
+
+          HashMap<String, EdmKeyPropertyRef> edmKeys = new HashMap<String, EdmKeyPropertyRef>();
+          for (EdmKeyPropertyRef key : keys) {
+            edmKeys.put(key.getKeyPropertyName(), key);
+            String alias = key.getAlias();
+            if (null != alias) {
+              edmKeys.put(alias, key);
             }
+          }
 
-            for (UriParameter keyPredicate : keyPredicates) {
-              String name = keyPredicate.getName();
-              String alias = keyPredicate.getAlias();
-              String value = keyPredicate.getText();
-              if (alias != null) {
-                value = uriInfo.getValueForAlias(alias);
-              }
-              EdmKeyPropertyRef edmKey = edmKeys.get(name);
-
-              if (edmKey == null) {
-                throw new UriValidationException("Unknown key property: " + name,
-                    UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
-              }
+          for (UriParameter keyPredicate : keyPredicates) {
+            String name = keyPredicate.getName();
+            String alias = keyPredicate.getAlias();
+            String value = keyPredicate.getText();
+            if (alias != null) {
+              value = uriInfo.getValueForAlias(alias);
+            }
+            EdmKeyPropertyRef edmKey = edmKeys.get(name);
 
-              EdmType edmType = edmKey.getProperty().getType();
-              EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmType;
+            if (edmKey == null) {
+              throw new UriValidationException("Unknown key property: " + name,
+                  UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
+            }
 
-              String edmLiteral = edmPrimitiveType.fromUriLiteral(value);
-              boolean isValid =
-                  edmPrimitiveType.validate(edmLiteral, edmKey.getProperty().isNullable(), edmKey.getProperty()
-                      .getMaxLength(), edmKey.getProperty().getPrecision(), edmKey.getProperty().getScale(), edmKey
-                      .getProperty().isUnicode());
-              if (!isValid) {
+            final EdmProperty property = edmKey.getProperty();
+            final EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) property.getType();
+            try {
+              if (!edmPrimitiveType.validate(edmPrimitiveType.fromUriLiteral(value),
+                  property.isNullable(), property.getMaxLength(),
+                  property.getPrecision(), property.getScale(), property.isUnicode())) {
                 // TODO: Check exception here
                 throw new UriValidationException("PrimitiveTypeException",
-                    UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
+                    UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
               }
+            } catch (EdmPrimitiveTypeException e) {
+              // TODO: Check exception here
+              throw new UriValidationException("PrimitiveTypeException", e,
+                  UriValidationException.MessageKeys.INVALID_KEY_PROPERTY, name);
             }
           }
         }
       }
-    } catch (EdmPrimitiveTypeException e) {
-      // TODO: Check exception here
-      throw new UriValidationException("PrimitiveTypeException", e,
-          UriValidationException.MessageKeys.INVALID_KEY_PROPERTY);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/resources/i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/i18n.properties b/lib/server-core/src/main/resources/i18n.properties
deleted file mode 100644
index 1b603f4..0000000
--- a/lib/server-core/src/main/resources/i18n.properties
+++ /dev/null
@@ -1,87 +0,0 @@
-#-------------------------------------------------------------------------------
-# 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.
-#-------------------------------------------------------------------------------
-# Basic Apache Olingo exception messages
-#
-ODataHandlerException.AMBIGUOUS_XHTTP_METHOD=x-http-method header '%1$s' and x-http-method-override header '%2$s' are not the same.
-ODataHandlerException.HTTP_METHOD_NOT_IMPLEMENTED=Invalid HTTP method given: '%1$s'.
-ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered.
-ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet).
-ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported.
-
-UriParserSyntaxException.UNKNOWN_SYSTEM_QUERY_OPTION=The system query option '%1$s' is not defined.
-UriParserSyntaxException.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION=The system query option '%1$s' has the not-allowed value '%2$s'.
-UriParserSyntaxException.SYNTAX=The URI is malformed.
-UriParserSyntaxException.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE=The system query option '$levels' is not allowed here.
-
-UriParserSemanticException.FUNCTION_NOT_FOUND=The function import '%1$s' has no function with parameters '%2$s'.
-UriParserSemanticException.RESOURCE_PART_ONLY_FOR_TYPED_PARTS='%1%s' is only allowed for typed parts.
-UriParserSemanticException.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE=The resource part '%1$s' must be preceded by a structural type.
-UriParserSemanticException.PROPERTY_NOT_IN_TYPE=The type '%1$s' has no property '%2$s'.
-UriParserSemanticException.UNKNOWN_PROPERTY_TYPE=The type of the property '%1$s' is unknown.
-UriParserSemanticException.INCOMPATIBLE_TYPE_FILTER=The type filter '%1$s' is incompatible.
-UriParserSemanticException.TYPE_FILTER_NOT_CHAINABLE=The type filter '%2$s' can not be chained with '%1$s'.
-UriParserSemanticException.PREVIOUS_PART_NOT_TYPED=The previous part of the type filter '%1$s' is not typed.
-UriParserSemanticException.FUNCTION_PARAMETERS_EXPECTED=Function parameters expected for type '%1$s'.
-UriParserSemanticException.UNKNOWN_PART=The part '%1%s' is not defined.
-UriParserSemanticException.ONLY_FOR_TYPED_PARTS='%1%s' is only allowed for typed parts.
-UriParserSemanticException.UNKNOWN_ENTITY_TYPE=The entity type '%1%s' is not defined.
-UriParserSemanticException.ONLY_FOR_COLLECTIONS='%1%s' is only allowed for collections.
-UriParserSemanticException.ONLY_FOR_ENTITY_TYPES='%1%s' is only allowed for entity types.
-UriParserSemanticException.ONLY_FOR_STRUCTURAL_TYPES='%1%s' is only allowed for structural types.
-UriParserSemanticException.ONLY_FOR_TYPED_PROPERTIES='%1%s' is only allowed for typed properties.
-UriParserSemanticException.INVALID_KEY_VALUE=The key value '%1$s' is invalid.
-UriParserSemanticException.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS=A list of parameters is only allowed for typed parts.
-UriParserSemanticException.NOT_ENOUGH_KEY_PROPERTIES=There are not enough key properties.
-UriParserSemanticException.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS=There are not enough referential constraints.
-UriParserSemanticException.KEY_NOT_ALLOWED=A key is not allowed.
-UriParserSemanticException.RESOURCE_PATH_NOT_TYPED=The resource path is not typed.
-UriParserSemanticException.ONLY_SIMPLE_AND_COMPLEX_PROPERTIES_IN_SELECT=Only simple and complex properties are allowed in selection.
-UriParserSemanticException.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED=A complex property of an entity type is expected.
-UriParserSemanticException.NOT_FOR_ENTITY_TYPE=Not allowed for entity type.
-UriParserSemanticException.PREVIOUS_PART_TYPED=The previous part is typed.
-
-UriValidationException.UNSUPPORTED_QUERY_OPTION=The query option '%1$s' is not supported.
-UriValidationException.UNSUPPORTED_URI_KIND=The URI kind '%1$s' is not supported.
-UriValidationException.UNSUPPORTED_URI_RESOURCE_KIND=The URI resource kind '%1$s' is not supported.
-UriValidationException.UNSUPPORTED_FUNCTION_RETURN_TYPE=The function return type '%1$s' is not supported.
-UriValidationException.UNSUPPORTED_ACTION_RETURN_TYPE=The action return type '%1$s' is not supported.
-UriValidationException.UNSUPPORTED_HTTP_METHOD=The HTTP method '%1$s' is not supported.
-UriValidationException.SYSTEM_QUERY_OPTION_NOT_ALLOWED=The system query option '%1$s' is not allowed.
-UriValidationException.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD=The system query option '%1$s' is not allowed for HTTP method '%2$s'.
-UriValidationException.INVALID_KEY_PROPERTY=The key property '%1$s' is invalid.
-UriValidationException.LAST_SEGMENT_NOT_TYPED=The last segment '%1$s' is not typed.
-UriValidationException.SECOND_LAST_SEGMENT_NOT_TYPED=The second last segment '%1$s' is not typed.
-UriValidationException.UNALLOWED_KIND_BEFORE_VALUE=The kind '%1$s' is not allowed before '$value'.
-UriValidationException.UNALLOWED_KIND_BEFORE_COUNT=The kind '%1$s' is not allowed before '$count'.
-
-ContentNegotiatorException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with value '%2$s' contains an invalid character-set specification.
-ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPES=The content-type range '%1$s' is not supported.
-ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported.
-ContentNegotiatorException.UNSUPPORTED_FORMAT_OPTION=The $format option '%1$s' is not supported.
-
-ODataSerializerException.NOT_IMPLEMENTED=The requested serialization method has not been implemented yet.
-ODataSerializerException.UNSUPPORTED_FORMAT=The format '%1$s' is not supported.
-ODataSerializerException.JSON_METADATA=The metadata document cannot be provided in JSON format.
-ODataSerializerException.IO_EXCEPTION=An I/O exception occurred.
-ODataSerializerException.NULL_INPUT=The input 'null' is not allowed here.
-ODataSerializerException.NO_CONTEXT_URL=No context URL has been provided.
-ODataSerializerException.UNSUPPORTED_PROPERTY_TYPE=The type of the property '%1$s' is not yet supported.
-ODataSerializerException.INCONSISTENT_PROPERTY_TYPE=An inconsistency has been detected in the type definition of property '%1$s'.
-ODataSerializerException.MISSING_PROPERTY=The non-nullable property '%1$s' is missing.
-ODataSerializerException.WRONG_PROPERTY_VALUE=The value '%2$s' is not valid for property '%1$s'.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
new file mode 100644
index 0000000..93f433f
--- /dev/null
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -0,0 +1,87 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# Basic Apache Olingo exception messages
+#
+ODataHandlerException.AMBIGUOUS_XHTTP_METHOD=x-http-method header '%1$s' and x-http-method-override header '%2$s' are not the same.
+ODataHandlerException.HTTP_METHOD_NOT_IMPLEMENTED=Invalid HTTP method given: '%1$s'.
+ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered.
+ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet).
+ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported.
+
+UriParserSyntaxException.UNKNOWN_SYSTEM_QUERY_OPTION=The system query option '%1$s' is not defined.
+UriParserSyntaxException.WRONG_VALUE_FOR_SYSTEM_QUERY_OPTION=The system query option '%1$s' has the not-allowed value '%2$s'.
+UriParserSyntaxException.SYNTAX=The URI is malformed.
+UriParserSyntaxException.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE=The system query option '$levels' is not allowed here.
+
+UriParserSemanticException.FUNCTION_NOT_FOUND=The function import '%1$s' has no function with parameters '%2$s'.
+UriParserSemanticException.RESOURCE_PART_ONLY_FOR_TYPED_PARTS='%1$s' is only allowed for typed parts.
+UriParserSemanticException.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE=The resource part '%1$s' must be preceded by a structural type.
+UriParserSemanticException.PROPERTY_NOT_IN_TYPE=The type '%1$s' has no property '%2$s'.
+UriParserSemanticException.UNKNOWN_PROPERTY_TYPE=The type of the property '%1$s' is unknown.
+UriParserSemanticException.INCOMPATIBLE_TYPE_FILTER=The type filter '%1$s' is incompatible.
+UriParserSemanticException.TYPE_FILTER_NOT_CHAINABLE=The type filter '%2$s' can not be chained with '%1$s'.
+UriParserSemanticException.PREVIOUS_PART_NOT_TYPED=The previous part of the type filter '%1$s' is not typed.
+UriParserSemanticException.FUNCTION_PARAMETERS_EXPECTED=Function parameters expected for type '%1$s'.
+UriParserSemanticException.UNKNOWN_PART=The part '%1$s' is not defined.
+UriParserSemanticException.ONLY_FOR_TYPED_PARTS='%1$s' is only allowed for typed parts.
+UriParserSemanticException.UNKNOWN_ENTITY_TYPE=The entity type '%1$s' is not defined.
+UriParserSemanticException.ONLY_FOR_COLLECTIONS='%1$s' is only allowed for collections.
+UriParserSemanticException.ONLY_FOR_ENTITY_TYPES='%1$s' is only allowed for entity types.
+UriParserSemanticException.ONLY_FOR_STRUCTURAL_TYPES='%1$s' is only allowed for structural types.
+UriParserSemanticException.ONLY_FOR_TYPED_PROPERTIES='%1$s' is only allowed for typed properties.
+UriParserSemanticException.INVALID_KEY_VALUE=The key value '%1$s' is invalid.
+UriParserSemanticException.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS=A list of parameters is only allowed for typed parts.
+UriParserSemanticException.NOT_ENOUGH_KEY_PROPERTIES=There are not enough key properties.
+UriParserSemanticException.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS=There are not enough referential constraints.
+UriParserSemanticException.KEY_NOT_ALLOWED=A key is not allowed.
+UriParserSemanticException.RESOURCE_PATH_NOT_TYPED=The resource path is not typed.
+UriParserSemanticException.ONLY_SIMPLE_AND_COMPLEX_PROPERTIES_IN_SELECT=Only simple and complex properties are allowed in selection.
+UriParserSemanticException.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED=A complex property of an entity type is expected.
+UriParserSemanticException.NOT_FOR_ENTITY_TYPE=Not allowed for entity type.
+UriParserSemanticException.PREVIOUS_PART_TYPED=The previous part is typed.
+
+UriValidationException.UNSUPPORTED_QUERY_OPTION=The query option '%1$s' is not supported.
+UriValidationException.UNSUPPORTED_URI_KIND=The URI kind '%1$s' is not supported.
+UriValidationException.UNSUPPORTED_URI_RESOURCE_KIND=The URI resource kind '%1$s' is not supported.
+UriValidationException.UNSUPPORTED_FUNCTION_RETURN_TYPE=The function return type '%1$s' is not supported.
+UriValidationException.UNSUPPORTED_ACTION_RETURN_TYPE=The action return type '%1$s' is not supported.
+UriValidationException.UNSUPPORTED_HTTP_METHOD=The HTTP method '%1$s' is not supported.
+UriValidationException.SYSTEM_QUERY_OPTION_NOT_ALLOWED=The system query option '%1$s' is not allowed.
+UriValidationException.SYSTEM_QUERY_OPTION_NOT_ALLOWED_FOR_HTTP_METHOD=The system query option '%1$s' is not allowed for HTTP method '%2$s'.
+UriValidationException.INVALID_KEY_PROPERTY=The key property '%1$s' is invalid.
+UriValidationException.LAST_SEGMENT_NOT_TYPED=The last segment '%1$s' is not typed.
+UriValidationException.SECOND_LAST_SEGMENT_NOT_TYPED=The second last segment '%1$s' is not typed.
+UriValidationException.UNALLOWED_KIND_BEFORE_VALUE=The kind '%1$s' is not allowed before '$value'.
+UriValidationException.UNALLOWED_KIND_BEFORE_COUNT=The kind '%1$s' is not allowed before '$count'.
+
+ContentNegotiatorException.WRONG_CHARSET_IN_HEADER=The HTTP header '%1$s' with value '%2$s' contains an invalid character-set specification.
+ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPES=The content-type range '%1$s' is not supported.
+ContentNegotiatorException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported.
+ContentNegotiatorException.UNSUPPORTED_FORMAT_OPTION=The $format option '%1$s' is not supported.
+
+ODataSerializerException.NOT_IMPLEMENTED=The requested serialization method has not been implemented yet.
+ODataSerializerException.UNSUPPORTED_FORMAT=The format '%1$s' is not supported.
+ODataSerializerException.JSON_METADATA=The metadata document cannot be provided in JSON format.
+ODataSerializerException.IO_EXCEPTION=An I/O exception occurred.
+ODataSerializerException.NULL_INPUT=The input 'null' is not allowed here.
+ODataSerializerException.NO_CONTEXT_URL=No context URL has been provided.
+ODataSerializerException.UNSUPPORTED_PROPERTY_TYPE=The type of the property '%1$s' is not yet supported.
+ODataSerializerException.INCONSISTENT_PROPERTY_TYPE=An inconsistency has been detected in the type definition of property '%1$s'.
+ODataSerializerException.MISSING_PROPERTY=The non-nullable property '%1$s' is missing.
+ODataSerializerException.WRONG_PROPERTY_VALUE=The value '%2$s' is not valid for property '%1$s'.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/cb7a8620/lib/server-core/src/test/java/org/apache/olingo/server/core/TranslatedExceptionSubclassesTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/TranslatedExceptionSubclassesTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/TranslatedExceptionSubclassesTest.java
new file mode 100644
index 0000000..19a02e5
--- /dev/null
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/TranslatedExceptionSubclassesTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.olingo.server.core;
+
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.serializer.ODataSerializerException;
+import org.apache.olingo.server.core.uri.parser.UriParserSemanticException;
+import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException;
+import org.apache.olingo.server.core.uri.validator.UriValidationException;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.Formatter;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.UUID;
+
+/**
+ * Generic test for all exceptions which inherit from ODataTranslatedException
+ * if their MessageKeys are available in the resource bundle and the parameters are replaced.
+ */
+public class TranslatedExceptionSubclassesTest {
+
+  private final Properties properties;
+
+  public TranslatedExceptionSubclassesTest() throws IOException {
+    properties = new Properties();
+    properties.load(Thread.currentThread().getContextClassLoader()
+        .getResourceAsStream("server-core-exceptions-i18n.properties"));
+    Locale.setDefault(Locale.ENGLISH);
+  }
+
+  @Test
+  public void messageKeysValid() throws Exception {
+    testException(ODataHandlerException.class, ODataHandlerException.MessageKeys.values());
+    testException(UriParserSemanticException.class, UriParserSemanticException.MessageKeys.values());
+    testException(UriParserSyntaxException.class, UriParserSyntaxException.MessageKeys.values());
+    testException(ContentNegotiatorException.class, ContentNegotiatorException.MessageKeys.values());
+    testException(ODataSerializerException.class, ODataSerializerException.MessageKeys.values());
+    testException(UriValidationException.class, UriValidationException.MessageKeys.values());
+    testException(UriParserSyntaxException.class, UriParserSyntaxException.MessageKeys.values());
+  }
+
+  private void testException(final Class<? extends ODataTranslatedException> clazz,
+      final ODataTranslatedException.MessageKey[] messageKeys) throws Exception {
+
+    for (ODataTranslatedException.MessageKey messageKey : messageKeys) {
+      String propKey = clazz.getSimpleName() + "." + messageKey.toString();
+      String value = properties.getProperty(propKey);
+      Assert.assertNotNull("No value found for message key '" + propKey + "'", value);
+      //
+      int paraCount = countParameters(value);
+      Constructor ctor = clazz.getConstructor(String.class, ODataTranslatedException.MessageKey.class, String[].class);
+      String[] paras = new String[paraCount];
+      for (int i = 0; i < paras.length; i++) {
+          paras[i] = "470" + i;
+      }
+      String developerMessage = UUID.randomUUID().toString();
+      ODataTranslatedException e = (ODataTranslatedException) ctor.newInstance(developerMessage, messageKey, paras);
+      try {
+        throw e;
+      } catch (ODataTranslatedException translatedException) {
+        String formattedValue = new Formatter().format(value, paras).toString();
+        Assert.assertEquals(formattedValue, translatedException.getTranslatedMessage(null).getMessage());
+        Assert.assertEquals(formattedValue, translatedException.getLocalizedMessage());
+        Assert.assertEquals(developerMessage, translatedException.getMessage());
+      }
+    }
+  }
+
+
+  private int countParameters(String value) {
+    char[] chars = value.toCharArray();
+    int count = 0;
+    for (char aChar : chars) {
+      if(aChar == '%') {
+        count++;
+      }
+    }
+    return count;
+  }
+}