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 2015/10/05 08:02:03 UTC

[06/11] olingo-odata4 git commit: [OLINGO-789] server support for action parameters of all types

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
index c5c842c..9b9de1d 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
@@ -50,8 +50,8 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.edm.EdmProperty;
 import org.apache.olingo.commons.api.edm.EdmType;
 import org.apache.olingo.commons.api.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.format.ContentType;
-import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.DeserializerException.MessageKeys;
 import org.apache.olingo.server.api.deserializer.DeserializerResult;
@@ -72,13 +72,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 
 public class ODataJsonDeserializer implements ODataDeserializer {
 
-  private static final String AN_IO_EXCEPTION_OCCURRED_MSG = "An IOException occurred";
-  private static final String DUPLICATE_JSON_PROPERTY_DETECTED_MSG = "Duplicate json property detected";
-  private static final String AN_JSON_PARSE_EXCEPTION_OCCURRED_MSG = "A JsonParseException occurred";
   private static final String ODATA_ANNOTATION_MARKER = "@";
   private static final String ODATA_CONTROL_INFORMATION_PREFIX = "@odata.";
-  private static final EdmPrimitiveType EDM_INT64 = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64);
-  private static final EdmPrimitiveType EDM_DECIMAL = EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal);
+
   private final boolean isIEEE754Compatible;
 
   public ODataJsonDeserializer(final ContentType contentType) {
@@ -89,33 +85,21 @@ public class ODataJsonDeserializer implements ODataDeserializer {
   public DeserializerResult entityCollection(final InputStream stream, final EdmEntityType edmEntityType)
       throws DeserializerException {
     try {
-      final ObjectNode tree = parseJsonTree(stream);
-
-      return DeserializerResultImpl.with().entityCollection(consumeEntitySetNode(edmEntityType, tree, null))
+      return DeserializerResultImpl.with().entityCollection(
+          consumeEntityCollectionNode(edmEntityType, parseJsonTree(stream), null))
           .build();
-    } catch (JsonParseException e) {
-      throw new DeserializerException(AN_JSON_PARSE_EXCEPTION_OCCURRED_MSG, e,
-          DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
-    } catch (JsonMappingException e) {
-      throw new DeserializerException(DUPLICATE_JSON_PROPERTY_DETECTED_MSG, e,
-          DeserializerException.MessageKeys.DUPLICATE_JSON_PROPERTY);
-    } catch (IOException e) {
-      throw new DeserializerException(AN_IO_EXCEPTION_OCCURRED_MSG, e, DeserializerException.MessageKeys.IO_EXCEPTION);
+    } catch (final IOException e) {
+      throw wrapParseException(e);
     }
   }
 
-  private EntityCollection consumeEntitySetNode(final EdmEntityType edmEntityType, final ObjectNode tree,
+  private EntityCollection consumeEntityCollectionNode(final EdmEntityType edmEntityType, ObjectNode tree,
       final ExpandTreeBuilder expandBuilder) throws DeserializerException {
     EntityCollection entitySet = new EntityCollection();
 
     // Consume entities
     JsonNode jsonNode = tree.get(Constants.VALUE);
     if (jsonNode != null) {
-      if (!jsonNode.isArray()) {
-        throw new DeserializerException("The content of the value tag must be an Array but is not. ",
-            DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY);
-      }
-
       entitySet.getEntities().addAll(consumeEntitySetArray(edmEntityType, jsonNode, expandBuilder));
       tree.remove(Constants.VALUE);
     } else {
@@ -145,16 +129,20 @@ public class ODataJsonDeserializer implements ODataDeserializer {
 
   private List<Entity> consumeEntitySetArray(final EdmEntityType edmEntityType, final JsonNode jsonNode,
       final ExpandTreeBuilder expandBuilder) throws DeserializerException {
-    List<Entity> entities = new ArrayList<Entity>();
-    for (JsonNode arrayElement : jsonNode) {
-      if (arrayElement.isArray() || arrayElement.isValueNode()) {
-        throw new DeserializerException("Nested Arrays and primitive values are not allowed for an entity value.",
-            DeserializerException.MessageKeys.INVALID_ENTITY);
+    if (jsonNode.isArray()) {
+      List<Entity> entities = new ArrayList<Entity>();
+      for (JsonNode arrayElement : jsonNode) {
+        if (arrayElement.isArray() || arrayElement.isValueNode()) {
+          throw new DeserializerException("Nested Arrays and primitive values are not allowed for an entity value.",
+              DeserializerException.MessageKeys.INVALID_ENTITY);
+        }
+        entities.add(consumeEntityNode(edmEntityType, (ObjectNode) arrayElement, expandBuilder));
       }
-
-      entities.add(consumeEntityNode(edmEntityType, (ObjectNode) arrayElement, expandBuilder));
+      return entities;
+    } else {
+      throw new DeserializerException("The content of the value tag must be an Array but is not.",
+          DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY);
     }
-    return entities;
   }
 
   @Override
@@ -167,17 +155,9 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       return DeserializerResultImpl.with().entity(consumeEntityNode(edmEntityType, tree, expandBuilder))
           .expandOption(expandBuilder.build())
           .build();
-
-    } catch (JsonParseException e) {
-      throw new DeserializerException(AN_JSON_PARSE_EXCEPTION_OCCURRED_MSG, e,
-          DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
-    } catch (JsonMappingException e) {
-      throw new DeserializerException(DUPLICATE_JSON_PROPERTY_DETECTED_MSG, e,
-          DeserializerException.MessageKeys.DUPLICATE_PROPERTY);
-    } catch (IOException e) {
-      throw new DeserializerException(AN_IO_EXCEPTION_OCCURRED_MSG, e, DeserializerException.MessageKeys.IO_EXCEPTION);
+    } catch (final IOException e) {
+      throw wrapParseException(e);
     }
-
   }
 
   private Entity consumeEntityNode(final EdmEntityType edmEntityType, final ObjectNode tree,
@@ -224,15 +204,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       assertJsonNodeIsEmpty(tree);
       return DeserializerResultImpl.with().actionParameters(parameters).build();
 
-    } catch (final JsonParseException e) {
-      throw new DeserializerException(AN_JSON_PARSE_EXCEPTION_OCCURRED_MSG, e,
-          DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
-    } catch (final JsonMappingException e) {
-      throw new DeserializerException(DUPLICATE_JSON_PROPERTY_DETECTED_MSG, e,
-          DeserializerException.MessageKeys.DUPLICATE_PROPERTY);
     } catch (final IOException e) {
-      throw new DeserializerException(AN_IO_EXCEPTION_OCCURRED_MSG, e,
-          DeserializerException.MessageKeys.IO_EXCEPTION);
+      throw wrapParseException(e);
     }
   }
 
@@ -264,17 +237,15 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       case DEFINITION:
       case ENUM:
       case COMPLEX:
+      case ENTITY:
         Parameter parameter = createParameter(node.get(paramName), paramName, edmParameter);
         parameters.put(paramName, parameter);
         node.remove(paramName);
         break;
-      case ENTITY:
-        throw new DeserializerException("Entity parameters are not allowed",
-            DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE);
       default:
-        throw new DeserializerException("Invalid type kind " + edmParameter.getType().getKind().toString()
-            + " for action parameter: " + paramName, DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE,
-            paramName);
+        throw new DeserializerException(
+            "Invalid type kind " + edmParameter.getType().getKind() + " for action parameter: " + paramName,
+            DeserializerException.MessageKeys.INVALID_ACTION_PARAMETER_TYPE, paramName);
       }
     }
     return parameters;
@@ -286,7 +257,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     parameter.setName(paramName);
     if (node == null || node.isNull()) {
       if (!edmParameter.isNullable()) {
-        throw new DeserializerException("Non-nullable parameter not present or null",
+        throw new DeserializerException("Non-nullable parameter not present or null: " + paramName,
             MessageKeys.INVALID_NULL_PARAMETER, paramName);
       }
       if (edmParameter.isCollection()) {
@@ -294,24 +265,34 @@ public class ODataJsonDeserializer implements ODataDeserializer {
             MessageKeys.INVALID_NULL_PARAMETER, paramName);
       }
       parameter.setValue(ValueType.PRIMITIVE, null);
+    } else if (edmParameter.getType().getKind() == EdmTypeKind.ENTITY) {
+      if (edmParameter.isCollection()) {
+        EntityCollection entityCollection = new EntityCollection();
+        entityCollection.getEntities().addAll(
+            consumeEntitySetArray((EdmEntityType) edmParameter.getType(), node, null));
+        parameter.setValue(ValueType.COLLECTION_ENTITY, entityCollection);
+      } else {
+        final Entity entity = consumeEntityNode((EdmEntityType) edmParameter.getType(), (ObjectNode) node, null);
+        parameter.setValue(ValueType.ENTITY, entity);
+      }
     } else {
-      Property consumePropertyNode =
+      final Property property =
           consumePropertyNode(edmParameter.getName(), edmParameter.getType(), edmParameter.isCollection(),
-              edmParameter.isNullable(), edmParameter.getMaxLength(), edmParameter.getPrecision(), edmParameter
-                  .getScale(), true, edmParameter.getMapping(), node);
-      parameter.setValue(consumePropertyNode.getValueType(), consumePropertyNode.getValue());
+              edmParameter.isNullable(), edmParameter.getMaxLength(),
+              edmParameter.getPrecision(), edmParameter.getScale(), true, edmParameter.getMapping(), node);
+      parameter.setValue(property.getValueType(), property.getValue());
     }
     return parameter;
   }
 
   /**
-   * Consume all remaining fields of Json ObjectNode and try to map found values
-   * to according Entity fields and omit to be ignored OData fields (e.g. control information).
+   * Consumes all remaining fields of Json ObjectNode and tries to map found values
+   * to according Entity fields and omits OData fields to be ignored (e.g., control information).
    *
    * @param edmEntityType edm entity type which for which the json node is consumed
    * @param node json node which is consumed
    * @param entity entity instance which is filled
-   * @throws DeserializerException if an exception during consummation occurs
+   * @throws DeserializerException if an exception during consumation occurs
    */
   private void consumeRemainingJsonNodeFields(final EdmEntityType edmEntityType, final ObjectNode node,
       final Entity entity) throws DeserializerException {
@@ -420,7 +401,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
 
   private Link consumeBindingLink(final String key, final JsonNode jsonNode, final EdmEntityType edmEntityType)
       throws DeserializerException {
-    String[] splitKey = key.split("@");
+    String[] splitKey = key.split(ODATA_ANNOTATION_MARKER);
     String navigationPropertyName = splitKey[0];
     EdmNavigationProperty edmNavigationProperty = edmEntityType.getNavigationProperty(navigationPropertyName);
     if (edmNavigationProperty == null) {
@@ -488,23 +469,16 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       throws DeserializerException {
     switch (type.getKind()) {
     case PRIMITIVE:
-      Object value = readPrimitiveValue(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping,
-          jsonNode);
-      property.setValue(ValueType.PRIMITIVE, value);
-      break;
     case DEFINITION:
-      value = readTypeDefinitionValue(name, type, isNullable, mapping, jsonNode);
-      property.setValue(ValueType.PRIMITIVE, value);
-      break;
     case ENUM:
-      value = readEnumValue(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping,
-          jsonNode);
-      property.setValue(ValueType.ENUM, value);
+      Object value = readPrimitiveValue(name, (EdmPrimitiveType) type,
+          isNullable, maxLength, precision, scale, isUnicode, mapping, jsonNode);
+      property.setValue(type.getKind() == EdmTypeKind.ENUM ? ValueType.ENUM : ValueType.PRIMITIVE,
+          value);
       break;
     case COMPLEX:
       value = readComplexNode(name, type, isNullable, jsonNode);
       property.setValue(ValueType.COMPLEX, value);
-
       break;
     default:
       throw new DeserializerException("Invalid Type Kind for a property found: " + type.getKind(),
@@ -553,30 +527,18 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     Iterator<JsonNode> iterator = jsonNode.iterator();
     switch (type.getKind()) {
     case PRIMITIVE:
-      while (iterator.hasNext()) {
-        JsonNode arrayElement = iterator.next();
-        Object value = readPrimitiveValue(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping,
-            arrayElement);
-        valueArray.add(value);
-      }
-      property.setValue(ValueType.COLLECTION_PRIMITIVE, valueArray);
-      break;
     case DEFINITION:
-      while (iterator.hasNext()) {
-        JsonNode arrayElement = iterator.next();
-        Object value = readTypeDefinitionValue(name, type, isNullable, mapping, arrayElement);
-        valueArray.add(value);
-      }
-      property.setValue(ValueType.COLLECTION_PRIMITIVE, valueArray);
-      break;
     case ENUM:
       while (iterator.hasNext()) {
         JsonNode arrayElement = iterator.next();
-        Object value = readEnumValue(name, type, isNullable, maxLength, precision, scale, isUnicode, mapping,
-            arrayElement);
+        Object value = readPrimitiveValue(name, (EdmPrimitiveType) type,
+            isNullable, maxLength, precision, scale, isUnicode, mapping, arrayElement);
         valueArray.add(value);
       }
-      property.setValue(ValueType.COLLECTION_ENUM, valueArray);
+      property.setValue(type.getKind() == EdmTypeKind.ENUM ?
+              ValueType.COLLECTION_ENUM :
+              ValueType.COLLECTION_PRIMITIVE,
+          valueArray);
       break;
     case COMPLEX:
       while (iterator.hasNext()) {
@@ -626,22 +588,20 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     return complexValue;
   }
 
-  private Object readTypeDefinitionValue(final String name, final EdmType type,
-      final boolean isNullable, final EdmMapping mapping, final JsonNode jsonNode) throws DeserializerException {
+  private Object readPrimitiveValue(final String name, final EdmPrimitiveType type,
+      final boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
+      final boolean isUnicode, final EdmMapping mapping, final JsonNode jsonNode) throws DeserializerException {
     checkForValueNode(name, jsonNode);
     if (isValidNull(name, isNullable, jsonNode)) {
       return null;
     }
+    checkJsonTypeBasedOnPrimitiveType(name, type, jsonNode);
+    Class<?> javaClass = getJavaClassForPrimitiveType(mapping, type);
     try {
-      EdmTypeDefinition edmTypeDefinition = (EdmTypeDefinition) type;
-      checkJsonTypeBasedOnPrimitiveType(name, edmTypeDefinition.getUnderlyingType().getName(),
-          jsonNode);
-      Class<?> javaClass = getJavaClassForPrimitiveType(mapping, edmTypeDefinition.getUnderlyingType());
-      return edmTypeDefinition.valueOfString(jsonNode.asText(), isNullable,
-          edmTypeDefinition.getMaxLength(),
-          edmTypeDefinition.getPrecision(), edmTypeDefinition.getScale(), edmTypeDefinition.isUnicode(),
+      return type.valueOfString(jsonNode.asText(),
+          isNullable, maxLength, precision, scale, isUnicode,
           javaClass);
-    } catch (EdmPrimitiveTypeException e) {
+    } catch (final EdmPrimitiveTypeException e) {
       throw new DeserializerException(
           "Invalid value: " + jsonNode.asText() + " for property: " + name, e,
           DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
@@ -657,72 +617,23 @@ public class ODataJsonDeserializer implements ODataDeserializer {
         throw new DeserializerException("Property: " + name + " must not be null.",
             DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, name);
       }
-
     }
     return false;
   }
 
-  private Object readEnumValue(final String name, final EdmType type,
-      final boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
-      final boolean isUnicode, final EdmMapping mapping, final JsonNode jsonNode) throws DeserializerException {
-    checkForValueNode(name, jsonNode);
-    if (isValidNull(name, isNullable, jsonNode)) {
-      return null;
-    }
-    try {
-      EdmEnumType edmEnumType = (EdmEnumType) type;
-      // Enum values must be strings
-      if (!jsonNode.isTextual()) {
-        throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for enum property: " + name,
-            DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
-      }
-
-      Class<?> javaClass = getJavaClassForPrimitiveType(mapping, edmEnumType.getUnderlyingType());
-      return edmEnumType.valueOfString(jsonNode.asText(),
-          isNullable, maxLength, precision, scale, isUnicode, javaClass);
-    } catch (EdmPrimitiveTypeException e) {
-      throw new DeserializerException(
-          "Invalid value: " + jsonNode.asText() + " for property: " + name, e,
-          DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
-    }
-  }
-
-  private Object readPrimitiveValue(final String name, final EdmType type,
-      final boolean isNullable, final Integer maxLength, final Integer precision, final Integer scale,
-      final boolean isUnicode, final EdmMapping mapping, final JsonNode jsonNode) throws DeserializerException {
-    checkForValueNode(name, jsonNode);
-    if (isValidNull(name, isNullable, jsonNode)) {
-      return null;
-    }
-    try {
-      EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) type;
-      checkJsonTypeBasedOnPrimitiveType(name, edmPrimitiveType.getName(), jsonNode);
-      Class<?> javaClass = getJavaClassForPrimitiveType(mapping, edmPrimitiveType);
-      String jsonNodeAsText = jsonNode.asText();
-
-      if (isIEEE754Compatible
-          && (edmPrimitiveType.equals(EDM_INT64) || edmPrimitiveType.equals(EDM_DECIMAL))
-              && jsonNodeAsText.length() == 0) {
-        throw new DeserializerException("IEEE754Compatible values must not be of length 0",
-            MessageKeys.INVALID_NULL_PROPERTY, name);
-      }
-
-      return edmPrimitiveType.valueOfString(jsonNodeAsText, isNullable, maxLength, precision, scale, isUnicode,
-          javaClass);
-    } catch (EdmPrimitiveTypeException e) {
-      throw new DeserializerException(
-          "Invalid value: " + jsonNode.asText() + " for property: " + name, e,
-          DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, name);
-    }
-  }
-
   /**
-   * This method either returns the primitive types default class or the manually mapped class if present.
+   * Returns the primitive type's default class or the manually mapped class if present.
    * @param mapping
    * @param edmPrimitiveType
    * @return the java class to be used during deserialization
    */
-  private Class<?> getJavaClassForPrimitiveType(final EdmMapping mapping, final EdmPrimitiveType edmPrimitiveType) {
+  private Class<?> getJavaClassForPrimitiveType(final EdmMapping mapping, final EdmPrimitiveType type) {
+    final EdmPrimitiveType edmPrimitiveType =
+        type.getKind() == EdmTypeKind.ENUM ?
+            ((EdmEnumType) type).getUnderlyingType() :
+                type.getKind() == EdmTypeKind.DEFINITION ?
+                    ((EdmTypeDefinition) type).getUnderlyingType() :
+                    type;
     return mapping == null || mapping.getMappedJavaClass() == null ?
         edmPrimitiveType.getDefaultType() :
         mapping.getMappedJavaClass();
@@ -743,9 +654,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
   }
 
   /**
-   * Validate that node is empty (<code>node.size == 0</code>) and if not throw
-   * an <code>DeserializerException</code>.
-   *
+   * Validates that node is empty (<code>node.size() == 0</code>).
    * @param node node to be checked
    * @throws DeserializerException if node is not empty
    */
@@ -757,90 +666,64 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     }
   }
 
-  private void checkJsonTypeBasedOnPrimitiveType(final String propertyName, final String edmPrimitiveTypeName,
-      final JsonNode jsonNode)
-      throws DeserializerException {
-
-    EdmPrimitiveTypeKind primKind;
-    try {
-      primKind = EdmPrimitiveTypeKind.valueOf(edmPrimitiveTypeName);
-    } catch (IllegalArgumentException e) {
-      throw new DeserializerException("Unknown Primitive Type: " + edmPrimitiveTypeName, e,
-          DeserializerException.MessageKeys.UNKNOWN_PRIMITIVE_TYPE, edmPrimitiveTypeName, propertyName);
+  private void checkJsonTypeBasedOnPrimitiveType(final String propertyName, final EdmPrimitiveType edmPrimitiveType,
+      final JsonNode jsonNode) throws DeserializerException {
+    boolean valid = true;
+    if (edmPrimitiveType.getKind() == EdmTypeKind.DEFINITION) {
+      checkJsonTypeBasedOnPrimitiveType(propertyName,
+          ((EdmTypeDefinition) edmPrimitiveType).getUnderlyingType(), jsonNode);
+    } else if (edmPrimitiveType.getKind() == EdmTypeKind.ENUM) {
+      // Enum values must be strings.
+      valid = jsonNode.isTextual();
+    } else {
+      final String name = edmPrimitiveType.getName();
+      EdmPrimitiveTypeKind primKind;
+      try {
+        primKind = EdmPrimitiveTypeKind.valueOf(name);
+      } catch (final IllegalArgumentException e) {
+        throw new DeserializerException("Unknown Primitive Type: " + name, e,
+            DeserializerException.MessageKeys.UNKNOWN_PRIMITIVE_TYPE, name, propertyName);
+      }
+      valid = matchTextualCase(jsonNode, primKind)
+          || matchNumberCase(jsonNode, primKind)
+          || matchBooleanCase(jsonNode, primKind)
+          || matchIEEENumberCase(jsonNode, primKind);
     }
-
-    boolean valid = matchTextualCase(jsonNode, primKind);
-    valid |= matchNumberCase(jsonNode, primKind);
-    valid |= matchBooleanCase(jsonNode, primKind);
-    valid |= matchIEEENumberCase(jsonNode, primKind);
-
     if (!valid) {
-      throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
-          + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+      throw new DeserializerException(
+          "Invalid json type: " + jsonNode.getNodeType() + " for " + edmPrimitiveType + " property: " + propertyName,
+          DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
     }
   }
 
-  private boolean matchIEEENumberCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
-    switch (primKind) {
-    case Int64:
-    case Decimal:
-      // Numbers (either numbers or string)
-      if (isIEEE754Compatible) {
-        return node.isTextual();
-      } else {
-        return node.isNumber();
-      }
-    default:
-      return false;
-    }
+  private boolean matchIEEENumberCase(final JsonNode node, final EdmPrimitiveTypeKind primKind) {
+    return (isIEEE754Compatible ? node.isTextual() : node.isNumber())
+        && (primKind == EdmPrimitiveTypeKind.Int64 || primKind == EdmPrimitiveTypeKind.Decimal);
   }
 
-  private boolean matchBooleanCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
-    if (node.isBoolean()) {
-      switch (primKind) {
-      case Boolean:
-        return true;
-      default:
-        return false;
-      }
-    }
-    return false;
+  private boolean matchBooleanCase(final JsonNode node, final EdmPrimitiveTypeKind primKind) {
+    return node.isBoolean() && primKind == EdmPrimitiveTypeKind.Boolean;
   }
 
-  private boolean matchNumberCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
-    if (node.isNumber()) {
-      switch (primKind) {
-      // Numbers (must be numbers)
-      case Int16:
-      case Int32:
-      case Byte:
-      case SByte:
-      case Single:
-      case Double:
-        return true;
-      default:
-        return false;
-      }
-    }
-    return false;
+  private boolean matchNumberCase(final JsonNode node, final EdmPrimitiveTypeKind primKind) {
+    return node.isNumber() &&
+      (primKind == EdmPrimitiveTypeKind.Int16
+      || primKind == EdmPrimitiveTypeKind.Int32
+      || primKind == EdmPrimitiveTypeKind.Byte
+      || primKind == EdmPrimitiveTypeKind.SByte
+      || primKind == EdmPrimitiveTypeKind.Single
+      || primKind == EdmPrimitiveTypeKind.Double);
   }
 
-  private boolean matchTextualCase(JsonNode node, EdmPrimitiveTypeKind primKind) {
-    if (node.isTextual()) {
-      switch (primKind) {
-      case String:
-      case Binary:
-      case Date:
-      case DateTimeOffset:
-      case Duration:
-      case Guid:
-      case TimeOfDay:
-        return true;
-      default:
-        return false;
-      }
-    }
-    return false;
+  private boolean matchTextualCase(final JsonNode node, final EdmPrimitiveTypeKind primKind) {
+    return node.isTextual() &&
+        (primKind == EdmPrimitiveTypeKind.String
+        || primKind == EdmPrimitiveTypeKind.Binary
+        || primKind == EdmPrimitiveTypeKind.Date
+        || primKind == EdmPrimitiveTypeKind.DateTimeOffset
+        || primKind == EdmPrimitiveTypeKind.Duration
+        || primKind == EdmPrimitiveTypeKind.Guid
+        || primKind == EdmPrimitiveTypeKind.TimeOfDay);
   }
 
   @Override
@@ -866,14 +749,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
             tree);
       }
       return DeserializerResultImpl.with().property(property).build();
-    } catch (JsonParseException e) {
-      throw new DeserializerException(AN_JSON_PARSE_EXCEPTION_OCCURRED_MSG, e,
-          DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
-    } catch (JsonMappingException e) {
-      throw new DeserializerException(DUPLICATE_JSON_PROPERTY_DETECTED_MSG, e,
-          DeserializerException.MessageKeys.DUPLICATE_PROPERTY);
-    } catch (IOException e) {
-      throw new DeserializerException(AN_IO_EXCEPTION_OCCURRED_MSG, e, DeserializerException.MessageKeys.IO_EXCEPTION);
+    } catch (final IOException e) {
+      throw wrapParseException(e);
     }
   }
 
@@ -906,18 +783,24 @@ public class ODataJsonDeserializer implements ODataDeserializer {
         throw new DeserializerException("Missing entity reference", DeserializerException.MessageKeys.UNKNOWN_CONTENT);
       }
       return DeserializerResultImpl.with().entityReferences(parsedValues).build();
-    } catch (JsonParseException e) {
-      throw new DeserializerException(AN_JSON_PARSE_EXCEPTION_OCCURRED_MSG, e,
+    } catch (final IOException e) {
+      throw wrapParseException(e);
+    } catch (final URISyntaxException e) {
+      throw new DeserializerException("failed to read @odata.id", e,
+          DeserializerException.MessageKeys.UNKNOWN_CONTENT);
+    }
+  }
+
+  private DeserializerException wrapParseException(final IOException e) {
+    if (e instanceof JsonParseException) {
+      return new DeserializerException("A JsonParseException occurred.", e,
           DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
-    } catch (JsonMappingException e) {
-      throw new DeserializerException(DUPLICATE_JSON_PROPERTY_DETECTED_MSG, e,
+    } else if (e instanceof JsonMappingException) {
+      return new DeserializerException("Duplicate json property detected.", e,
           DeserializerException.MessageKeys.DUPLICATE_PROPERTY);
-    } catch (IOException e) {
-      throw new DeserializerException(AN_IO_EXCEPTION_OCCURRED_MSG, e,
+    } else {
+      return new DeserializerException("An IOException occurred.", e,
           DeserializerException.MessageKeys.IO_EXCEPTION);
-    } catch (URISyntaxException e) {
-      throw new DeserializerException("failed to read @odata.id", e,
-          DeserializerException.MessageKeys.UNKNOWN_CONTENT);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
index a762f5c..776868b 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/xml/ODataXmlDeserializer.java
@@ -61,6 +61,7 @@ import org.apache.olingo.commons.core.edm.primitivetype.SingletonPrimitiveType;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.DeserializerResult;
 import org.apache.olingo.server.api.deserializer.ODataDeserializer;
+import org.apache.olingo.server.api.deserializer.DeserializerException.MessageKeys;
 import org.apache.olingo.server.core.deserializer.DeserializerResultImpl;
 
 import com.fasterxml.aalto.stax.InputFactoryImpl;
@@ -69,11 +70,9 @@ public class ODataXmlDeserializer implements ODataDeserializer {
 
   private static final XMLInputFactory FACTORY = new InputFactoryImpl();
   private static final String ATOM = "a";
-  private static final String NS_ATOM = "http://www.w3.org/2005/Atom";  
-  private static final QName REF_ELEMENT = new QName("http://docs.oasis-open.org/odata/ns/metadata", "ref");
-  private static final QName PARAMETERS_ELEMENT = 
-      new QName("http://docs.oasis-open.org/odata/ns/metadata", "parameters");
-  private static final QName ID_ATTR = new QName(NS_ATOM, ATOM);
+  private static final QName REF_ELEMENT = new QName(Constants.NS_METADATA, Constants.ATOM_ELEM_ENTRY_REF);
+  private static final QName PARAMETERS_ELEMENT = new QName(Constants.NS_METADATA, "parameters");
+  private static final QName ID_ATTR = new QName(Constants.NS_ATOM, ATOM);
 
   private final QName propertiesQName = new QName(Constants.NS_METADATA, Constants.PROPERTIES);
   private final QName propertyValueQName = new QName(Constants.NS_METADATA, Constants.VALUE);
@@ -83,16 +82,7 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   private final QName entryRefQName = new QName(Constants.NS_METADATA, Constants.ATOM_ELEM_ENTRY_REF);
   private final QName etagQName = new QName(Constants.NS_METADATA, Constants.ATOM_ATTR_ETAG); 
   private final QName countQName = new QName(Constants.NS_METADATA, Constants.ATOM_ELEM_COUNT);
-  
-//  private void namespaces(final XMLStreamWriter writer) throws XMLStreamException {
-//    writer.writeNamespace(StringUtils.EMPTY, Constants.NS_ATOM);
-//    writer.writeNamespace(XMLConstants.XML_NS_PREFIX, XMLConstants.XML_NS_URI);
-//    writer.writeNamespace(Constants.PREFIX_METADATA, Constants.NS_METADATA);
-//    writer.writeNamespace(Constants.PREFIX_DATASERVICES, Constants.NS_DATASERVICES);
-//    writer.writeNamespace(Constants.PREFIX_GML, Constants.NS_GML);
-//    writer.writeNamespace(Constants.PREFIX_GEORSS, Constants.NS_GEORSS);
-//  }
-  
+
   protected XMLEventReader getReader(final InputStream input) throws XMLStreamException {
     return FACTORY.createXMLEventReader(input);
   }
@@ -715,12 +705,12 @@ public class ODataXmlDeserializer implements ODataDeserializer {
   public DeserializerResult actionParameters(InputStream stream, EdmAction edmAction) 
       throws DeserializerException {
     Map<String, Parameter> parameters = new LinkedHashMap<String, Parameter>();
-    if(edmAction.getParameterNames() == null || edmAction.getParameterNames().isEmpty()
-        || (edmAction.isBound() && edmAction.getParameterNames().size() == 1)) {
+    if (edmAction.getParameterNames() == null || edmAction.getParameterNames().isEmpty()
+        || edmAction.isBound() && edmAction.getParameterNames().size() == 1) {
       return DeserializerResultImpl.with().actionParameters(parameters)
           .build();
     }
-        
+
     try {             
       final XMLEventReader reader = getReader(stream);
       while (reader.hasNext()) {
@@ -729,14 +719,26 @@ public class ODataXmlDeserializer implements ODataDeserializer {
           consumeParameters(edmAction, reader, event.asStartElement(), parameters);
         }        
       }
-      // NULL fill for missing parameters
-      Parameter nullParameter = new Parameter();
-      nullParameter.setValue(ValueType.PRIMITIVE, null);
-      for (String param:edmAction.getParameterNames()) {
-        if (parameters.get(param) == null) {
-          parameters.put(param, nullParameter);
+      // EDM checks.
+      for (final String param : edmAction.getParameterNames()) {
+        Parameter parameter = parameters.get(param);
+        if (parameter == null) {
+          final EdmParameter edmParameter = edmAction.getParameter(param);
+          if (!edmParameter.isNullable()) {
+            throw new DeserializerException("Non-nullable parameter not present or null: " + param,
+                MessageKeys.INVALID_NULL_PARAMETER, param);
+          }
+          if (edmParameter.isCollection()) {
+            throw new DeserializerException("Collection must not be null for parameter: " + param,
+                MessageKeys.INVALID_NULL_PARAMETER, param);
+          }
+          // NULL fill for missing parameters.
+          parameter = new Parameter();
+          parameter.setName(param);
+          parameter.setValue(ValueType.PRIMITIVE, null);
+          parameters.put(param, parameter);
         }
-      }      
+      }
       return DeserializerResultImpl.with().actionParameters(parameters)
           .build();
     } catch (XMLStreamException e) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
index 4e1ba56..27ba073 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/ODataXmlSerializer.java
@@ -72,16 +72,16 @@ import org.apache.olingo.server.core.serializer.utils.ExpandSelectHelper;
 
 public class ODataXmlSerializer extends AbstractODataSerializer {
 
-  private static final String DATA = "d";
   private static final String CONTEXT = "context";
   /** The default character set is UTF-8. */
   public static final String DEFAULT_CHARSET = "UTF-8";
   private static final String ATOM = "a";
-  private static final String NS_ATOM = "http://www.w3.org/2005/Atom";
+  private static final String NS_ATOM = Constants.NS_ATOM;
   private static final String METADATA = "m";
-  private static final String NS_METADATA = "http://docs.oasis-open.org/odata/ns/metadata";
-  private static final String NS_DATA = "http://docs.oasis-open.org/odata/ns/data";
-  private static final String NS_SCHEMA = "http://docs.oasis-open.org/odata/ns/scheme";
+  private static final String NS_METADATA = Constants.NS_METADATA;
+  private static final String DATA = "d";
+  private static final String NS_DATA = Constants.NS_DATASERVICES;
+  private static final String NS_SCHEMA = Constants.NS_SCHEME;
 
   @Override
   public SerializerResult serviceDocument(final ServiceMetadata metadata, final String serviceRoot)
@@ -235,7 +235,7 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
           ContextURLBuilder.create(contextURL).toASCIIString());
       writeMetadataETag(metadata, writer);
 
-      if (options != null) {
+      if (options != null && options.getId() != null) {
         writer.writeStartElement(ATOM, "id", NS_ATOM);
         writer.writeCharacters(options.getId());
         writer.writeEndElement();
@@ -364,16 +364,20 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       writer.writeAttribute(METADATA, NS_METADATA, "etag", entity.getETag());
     }
 
-    writer.writeStartElement(NS_ATOM, "id");
-    writer.writeCharacters(entity.getId().toASCIIString());
-    writer.writeEndElement();
+    if (entity.getId() != null) {
+      writer.writeStartElement(NS_ATOM, "id");
+      writer.writeCharacters(entity.getId().toASCIIString());
+      writer.writeEndElement();
+    }
 
     writerAuthorInfo(entity.getTitle(), writer);
 
-    writer.writeStartElement(NS_ATOM, "link");
-    writer.writeAttribute("rel", "edit");
-    writer.writeAttribute("href", entity.getId().toASCIIString());
-    writer.writeEndElement();
+    if (entity.getId() != null) {
+      writer.writeStartElement(NS_ATOM, "link");
+      writer.writeAttribute("rel", "edit");
+      writer.writeAttribute("href", entity.getId().toASCIIString());
+      writer.writeEndElement();
+    }
 
     if (entityType.hasStream()) {
       writer.writeStartElement(NS_ATOM, "content");
@@ -551,12 +555,14 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
     Link link = linked.getNavigationLink(navigationPropertyName);
     if (link == null) {
       link = new Link();
-      link.setRel("http://docs.oasis-open.org/odata/ns/related/" + navigationPropertyName);
+      link.setRel(Constants.NS_NAVIGATION_LINK_REL + navigationPropertyName);
       link.setType(Constants.ENTITY_SET_NAVIGATION_LINK_TYPE);
       link.setTitle(navigationPropertyName);
       EntityCollection target = new EntityCollection();
       link.setInlineEntitySet(target);
-      link.setHref(linked.getId().toASCIIString() + "/" + navigationPropertyName);
+      if (linked.getId() != null) {
+        link.setHref(linked.getId().toASCIIString() + "/" + navigationPropertyName);
+      }
     }
     return link;
   }
@@ -575,7 +581,9 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
     if (link.getTitle() != null) {
       writer.writeAttribute("title", link.getTitle());
     }
-    writer.writeAttribute("href", link.getHref());
+    if (link.getHref() != null) {
+      writer.writeAttribute("href", link.getHref());
+    }
     if (close) {
       writer.writeEndElement();
     }
@@ -606,11 +614,11 @@ public class ODataXmlSerializer extends AbstractODataSerializer {
       SerializerException {
     writer.writeStartElement(DATA, edmProperty.getName(), NS_DATA);
     if (property == null || property.isNull()) {
-      if (edmProperty.isNullable() == Boolean.FALSE) {
+      if (edmProperty.isNullable()) {
+        writer.writeAttribute(METADATA, NS_METADATA, "null", "true");
+      } else {
         throw new SerializerException("Non-nullable property not present!",
             SerializerException.MessageKeys.MISSING_PROPERTY, edmProperty.getName());
-      } else {
-        writer.writeAttribute(METADATA, NS_METADATA, "null", "true");
       }
     } else {
       writePropertyValue(metadata, edmProperty, property, selectedPaths, writer);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
index 72c34b2..2adf7c2 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/ActionData.java
@@ -19,6 +19,7 @@
 package org.apache.olingo.server.tecsvc.data;
 
 import java.math.BigDecimal;
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -31,11 +32,13 @@ import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Parameter;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
+import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.tecsvc.data.DataProvider.DataProviderException;
 
 public class ActionData {
@@ -101,57 +104,45 @@ public class ActionData {
       throws DataProviderException {
     if ("UARTCTTwoPrimParam".equals(name)) {
       Parameter paramInt16 = parameters.get("ParameterInt16");
-      final Short number = paramInt16 == null ? (short) 32767 : (Short) paramInt16.asPrimitive();
-      return createCTTwoPrimComplexProperty(number, "UARTCTTwoPrimParam string value");
+      final Short number = paramInt16 == null || paramInt16.isNull() ?
+          (short) 32767 :
+          (Short) paramInt16.asPrimitive();
+      return createCTTwoPrimComplexProperty(name, number, "UARTCTTwoPrimParam string value");
     }
     throw new DataProviderException("Action " + name + " is not yet implemented.");
   }
 
-  private static Property createCTTwoPrimComplexProperty(final Short number, final String text) {
-    ComplexValue compValue = new ComplexValue();
-    Property propInt = new Property();
-    propInt.setName("PropertyInt16");
-    propInt.setValue(ValueType.PRIMITIVE, number);
-    compValue.getValue().add(propInt);
-    Property propString = new Property();
-    propString.setName("PropertyString");
-    propString.setValue(ValueType.PRIMITIVE, text);
-    compValue.getValue().add(propString);
-
-    Property complexProp = new Property();
-    complexProp.setValue(ValueType.COMPLEX, compValue);
-    return complexProp;
+  private static Property createCTTwoPrimComplexProperty(final String name, final Short number, final String text) {
+    return DataCreator.createComplex(name,
+        DataCreator.createPrimitive("PropertyInt16", number),
+        DataCreator.createPrimitive("PropertyString", text));
   }
 
   protected static Property complexCollectionAction(final String name, final Map<String, Parameter> parameters)
       throws DataProviderException {
     if ("UARTCollCTTwoPrimParam".equals(name)) {
       List<ComplexValue> complexCollection = new ArrayList<ComplexValue>();
-      complexCollection.add(createCTTwoPrimComplexProperty((short) 16, "Test123").asComplex());
-      complexCollection.add(createCTTwoPrimComplexProperty((short) 17, "Test456").asComplex());
-      complexCollection.add(createCTTwoPrimComplexProperty((short) 18, "Test678").asComplex());
-
-      Parameter paramInt16 = parameters.get("ParameterInt16");
-      if (paramInt16 != null) {
-        Short number = (Short) paramInt16.asPrimitive();
-        if (number < 0) {
-          complexCollection.clear();
-        } else if (number >= 0 && number < complexCollection.size()) {
-          complexCollection = complexCollection.subList(0, number);
-        }
-        Property complexCollProperty = new Property();
-        complexCollProperty.setValue(ValueType.COLLECTION_COMPLEX, complexCollection);
-        return complexCollProperty;
+      final Parameter paramInt16 = parameters.get("ParameterInt16");
+      final Short number = paramInt16 == null || paramInt16.isNull() ? 0 : (Short) paramInt16.asPrimitive();
+      if (number >= 1) {
+        complexCollection.add(createCTTwoPrimComplexProperty(null, (short) 16, "Test123").asComplex());
       }
+      if (number >= 2) {
+        complexCollection.add(createCTTwoPrimComplexProperty(null, (short) 17, "Test456").asComplex());
+      }
+      if (number >= 3) {
+        complexCollection.add(createCTTwoPrimComplexProperty(null, (short) 18, "Test678").asComplex());
+      }
+      return new Property(null, name, ValueType.COLLECTION_COMPLEX, complexCollection);
     }
     throw new DataProviderException("Action " + name + " is not yet implemented.");
   }
 
   protected static EntityActionResult entityAction(final String name, final Map<String, Parameter> parameters,
-      final Map<String, EntityCollection> data) throws DataProviderException {
+      final Map<String, EntityCollection> data, final OData oData, final Edm edm) throws DataProviderException {
     if ("UARTETTwoKeyTwoPrimParam".equals(name)) {
       Parameter parameter = parameters.get("ParameterInt16");
-      final Short number = parameter == null ? 0 : (Short) parameter.asPrimitive();
+      final Short number = parameter == null || parameter.isNull() ? 0 : (Short) parameter.asPrimitive();
 
       EntityCollection entityCollection = data.get("ESTwoKeyTwoPrim");
       for (Entity entity : entityCollection.getEntities()) {
@@ -180,7 +171,8 @@ public class ActionData {
             }
           }
         } while (!freeKey);
-        return new EntityActionResult().setEntity(createAllPrimEntity(key, "UARTETAllPrimParam string value", date))
+        return new EntityActionResult().setEntity(
+            createAllPrimEntity(key, "UARTETAllPrimParam string value", date, oData, edm))
             .setCreated(true);
       } else {
         return new EntityActionResult().setEntity(entityCollection.getEntities().get(0));
@@ -189,8 +181,9 @@ public class ActionData {
     throw new DataProviderException("Action " + name + " is not yet implemented.");
   }
 
-  private static Entity createAllPrimEntity(final Short key, final String val, final Calendar date) {
-    return new Entity().addProperty(DataCreator.createPrimitive("PropertyInt16", key))
+  private static Entity createAllPrimEntity(final Short key, final String val, final Calendar date,
+      final OData oData, final Edm edm) throws DataProviderException {
+    Entity entity = new Entity().addProperty(DataCreator.createPrimitive("PropertyInt16", key))
         .addProperty(DataCreator.createPrimitive("PropertyString", val))
         .addProperty(DataCreator.createPrimitive("PropertyBoolean", false))
         .addProperty(DataCreator.createPrimitive("PropertyByte", null))
@@ -206,28 +199,31 @@ public class ActionData {
         .addProperty(DataCreator.createPrimitive("PropertyDuration", null))
         .addProperty(DataCreator.createPrimitive("PropertyGuid", null))
         .addProperty(DataCreator.createPrimitive("PropertyTimeOfDay", null));
+    setEntityId(entity, "ESAllPrim", oData, edm);
+    return entity;
   }
 
-  protected static EntityCollection entityCollectionAction(final String name, final Map<String, Parameter> parameters)
-      throws DataProviderException {
+  protected static EntityCollection entityCollectionAction(final String name, final Map<String, Parameter> parameters,
+      final OData oData, final Edm edm) throws DataProviderException {
     if ("UARTCollETKeyNavParam".equals(name)) {
-      Parameter paramInt16 = parameters.get("ParameterInt16");
-      final Short number = paramInt16 == null ? 0 : (Short) paramInt16.asPrimitive();
       EntityCollection collection = new EntityCollection();
+      Parameter paramInt16 = parameters.get("ParameterInt16");
+      final Short number = paramInt16 == null || paramInt16.isNull() ? 0 : (Short) paramInt16.asPrimitive();
       if (number > 0) {
         for (short i = 1; i <= number; i++) {
-          collection.getEntities().add(createETKeyNavEntity(i));
+          collection.getEntities().add(createETKeyNavEntity(i, oData, edm));
         }
       }
       return collection;
     } else if ("UARTCollETAllPrimParam".equals(name)) {
-      Parameter paramTimeOfDay = parameters.get("ParameterTimeOfDay");
       EntityCollection collection = new EntityCollection();
-      if (paramTimeOfDay != null) {
+      Parameter paramTimeOfDay = parameters.get("ParameterTimeOfDay");
+      if (paramTimeOfDay != null && !paramTimeOfDay.isNull()) {
         Calendar timeOfDay = (Calendar) paramTimeOfDay.asPrimitive();
         int count = timeOfDay.get(Calendar.HOUR_OF_DAY);
         for (short i = 1; i <= count; i++) {
-          collection.getEntities().add(createAllPrimEntity(i, "UARTCollETAllPrimParam int16 value: " + i, null));
+          collection.getEntities().add(
+              createAllPrimEntity(i, "UARTCollETAllPrimParam int16 value: " + i, null, oData, edm));
         }
       }
       return collection;
@@ -236,8 +232,9 @@ public class ActionData {
   }
 
   @SuppressWarnings("unchecked")
-  private static Entity createETKeyNavEntity(final Short number) {
-    return new Entity()
+  private static Entity createETKeyNavEntity(final Short number, final OData oData, final Edm edm)
+      throws DataProviderException {
+    Entity entity = new Entity()
         .addProperty(DataCreator.createPrimitive("PropertyInt16", number))
         .addProperty(DataCreator.createPrimitive("PropertyString", "UARTCollETKeyNavParam int16 value: " + number))
         .addProperty(DataCreator.createComplex("PropertyCompNav", 
@@ -253,6 +250,18 @@ public class ActionData {
             DataCreator.createPrimitive("PropertyString", ""),
             DataCreator.createComplex("PropertyCompNav", 
                 DataCreator.createPrimitive("PropertyInt16", (short) 0))));
+    setEntityId(entity, "ESKeyNav", oData, edm);
+    return entity;
+  }
+
+  private static void setEntityId(Entity entity, final String entitySetName, final OData oData, final Edm edm)
+      throws DataProviderException {
+    try {
+      entity.setId(URI.create(oData.createUriHelper().buildCanonicalURL(
+          edm.getEntityContainer().getEntitySet(entitySetName), entity)));
+    } catch (final SerializerException e) {
+      throw new DataProviderException("Unable to set entity ID!", e);
+    }
   }
 
   protected static Property createKeyNavAllPrimComplexValue(final String name) {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
index 1d3ef71..f9e2ee2 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java
@@ -77,9 +77,12 @@ public class DataProvider {
   }
 
   public EntityCollection readAll(final EdmEntitySet edmEntitySet) throws DataProviderException {
-    final EntityCollection entityCollection = data.get(edmEntitySet.getName());
-
-    return (entityCollection == null) ? createEntityCollection(edmEntitySet) : entityCollection;
+    EntityCollection entityCollection = data.get(edmEntitySet.getName());
+    if (entityCollection == null) {
+      entityCollection = new EntityCollection();
+      data.put(edmEntitySet.getName(), entityCollection);
+    }
+    return entityCollection;
   }
 
   public Entity read(final EdmEntitySet edmEntitySet, final List<UriParameter> keys) throws DataProviderException {
@@ -146,7 +149,7 @@ public class DataProvider {
     final EdmEntityType edmEntityType = edmEntitySet.getEntityType();
     EntityCollection entitySet = readAll(edmEntitySet);
     final List<Entity> entities = entitySet.getEntities();
-    final Map<String, Object> newKey = findFreeComposedKey(entities, edmEntitySet.getEntityType());
+    final Map<String, Object> newKey = findFreeComposedKey(entities, edmEntityType);
     Entity newEntity = new Entity();
     newEntity.setType(edmEntityType.getFullQualifiedName().getFullQualifiedNameAsString());
     for (final String keyName : edmEntityType.getKeyPredicateNames()) {
@@ -163,14 +166,6 @@ public class DataProvider {
 
     return newEntity;
   }
-  
-  private EntityCollection createEntityCollection(final EdmEntitySet edmEntitySet) {
-    if(data.get(edmEntitySet.getName()) == null ) {
-      data.put(edmEntitySet.getName(), new EntityCollection());
-    }
-    
-    return data.get(edmEntitySet.getName());
-  }
 
   private Map<String, Object> findFreeComposedKey(final List<Entity> entities, final EdmEntityType entityType)
       throws DataProviderException {
@@ -545,12 +540,12 @@ public class DataProvider {
 
   public EntityActionResult processActionEntity(final String name, final Map<String, Parameter> actionParameters)
       throws DataProviderException {
-    return ActionData.entityAction(name, actionParameters, data);
+    return ActionData.entityAction(name, actionParameters, data, odata, edm);
   }
 
   public EntityCollection processActionEntityCollection(final String name,
       final Map<String, Parameter> actionParameters) throws DataProviderException {
-    return ActionData.entityCollectionAction(name, actionParameters);
+    return ActionData.entityCollectionAction(name, actionParameters, odata, edm);
   }
   
   public void createReference(final Entity entity, final EdmNavigationProperty navigationProperty, final URI entityId, 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/ActionDataProviderTest.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/ActionDataProviderTest.java b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/ActionDataProviderTest.java
index 199f0f1..3cb1b09 100644
--- a/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/ActionDataProviderTest.java
+++ b/lib/server-tecsvc/src/test/java/org/apache/olingo/server/tecsvc/data/ActionDataProviderTest.java
@@ -161,7 +161,7 @@ public class ActionDataProviderTest {
     paramInt16.setValue(ValueType.PRIMITIVE, new Short((short) 32767));
     final Map<String, Parameter> parameters = Collections.singletonMap("ParameterInt16", paramInt16);
 
-    EntityActionResult result = ActionData.entityAction("UARTETTwoKeyTwoPrimParam", parameters, data);
+    EntityActionResult result = ActionData.entityAction("UARTETTwoKeyTwoPrimParam", parameters, data, oData, edm);
     assertNotNull(result);
     assertFalse(result.isCreated());
     assertEquals((short) 32767, result.getEntity().getProperty("PropertyInt16").asPrimitive());
@@ -175,7 +175,7 @@ public class ActionDataProviderTest {
     final Map<String, Parameter> parameters = Collections.singletonMap("ParameterInt16", paramInt16);
 
     try {
-      ActionData.entityAction("UARTETTwoKeyTwoPrimParam", parameters, data);
+      ActionData.entityAction("UARTETTwoKeyTwoPrimParam", parameters, data, oData, edm);
       fail("Expected a DataProviderException but wasn't thrown");
     } catch (DataProviderException e) {
       assertEquals("Entity not found with key: 12345", e.getMessage());
@@ -186,7 +186,7 @@ public class ActionDataProviderTest {
   @Test
   public void actionUARTETAllPrimParamWithoutParam() throws Exception {
     final EntityActionResult result = ActionData.entityAction("UARTETAllPrimParam",
-        Collections.<String, Parameter> emptyMap(), data);
+        Collections.<String, Parameter> emptyMap(), data, oData, edm);
     assertNotNull(result);
     assertFalse(result.isCreated());
     assertEquals(Short.MAX_VALUE, result.getEntity().getProperty("PropertyInt16").asPrimitive());
@@ -199,7 +199,7 @@ public class ActionDataProviderTest {
     paramDate.setValue(ValueType.PRIMITIVE, null);
     final Map<String, Parameter> parameters = Collections.singletonMap("ParameterDate", paramDate);
 
-    EntityActionResult result = ActionData.entityAction("UARTETAllPrimParam", parameters, data);
+    EntityActionResult result = ActionData.entityAction("UARTETAllPrimParam", parameters, data, oData, edm);
     assertNotNull(result);
     assertTrue(result.isCreated());
     assertEquals((short) 1, result.getEntity().getProperty("PropertyInt16").asPrimitive());
@@ -212,7 +212,7 @@ public class ActionDataProviderTest {
     paramInt16.setValue(ValueType.PRIMITIVE, Short.valueOf((short) 5));
     final Map<String, Parameter> parameters = Collections.singletonMap("ParameterInt16", paramInt16);
 
-    EntityCollection result = ActionData.entityCollectionAction("UARTCollETKeyNavParam", parameters);
+    EntityCollection result = ActionData.entityCollectionAction("UARTCollETKeyNavParam", parameters, oData, edm);
     assertNotNull(result);
     assertEquals(5, result.getEntities().size());
   }
@@ -224,7 +224,7 @@ public class ActionDataProviderTest {
     paramTimeOfDay.setValue(ValueType.PRIMITIVE, getTime(5, 0, 0));
     final Map<String, Parameter> parameters = Collections.singletonMap("ParameterTimeOfDay", paramTimeOfDay);
 
-    EntityCollection result = ActionData.entityCollectionAction("UARTCollETAllPrimParam", parameters);
+    EntityCollection result = ActionData.entityCollectionAction("UARTCollETAllPrimParam", parameters, oData, edm);
     assertNotNull(result);
     assertEquals(5, result.getEntities().size());
   }
@@ -232,7 +232,7 @@ public class ActionDataProviderTest {
   @Test
   public void actionUARTCollETAllPrimParamNoParam() throws Exception {
     final EntityCollection result = ActionData.entityCollectionAction("UARTCollETAllPrimParam",
-        Collections.<String, Parameter> emptyMap());
+        Collections.<String, Parameter> emptyMap(), oData, edm);
     assertNotNull(result);
     assertEquals(0, result.getEntities().size());
   }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
new file mode 100644
index 0000000..c90ad6d
--- /dev/null
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/AbstractODataDeserializerTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.deserializer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.edmx.EdmxReference;
+import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
+
+public class AbstractODataDeserializerTest {
+
+  protected static final String NAMESPACE = "Namespace1_Alias";
+  protected static final Edm edm = OData.newInstance()
+      .createServiceMetadata(new EdmTechProvider(), Collections.<EdmxReference> emptyList())
+      .getEdm();
+
+  protected InputStream getFileAsStream(final String filename) throws IOException {
+    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
+    if (in == null) {
+      throw new IOException("Requested file '" + filename + "' was not found.");
+    }
+    return in;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/AbstractODataDeserializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/AbstractODataDeserializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/AbstractODataDeserializerTest.java
deleted file mode 100644
index 5cc025d..0000000
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/AbstractODataDeserializerTest.java
+++ /dev/null
@@ -1,46 +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.
- */
-package org.apache.olingo.server.core.deserializer.json;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Collections;
-
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.format.ContentType;
-import org.apache.olingo.server.api.OData;
-import org.apache.olingo.server.api.edmx.EdmxReference;
-import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
-
-public class AbstractODataDeserializerTest {
-  protected static final ContentType CONTENT_TYPE_JSON = ContentType.JSON;
-  protected static final ContentType CONTENT_TYPE_JSON_IEEE754Compatible = 
-      ContentType.create(ContentType.JSON, ContentType.PARAMETER_IEEE754_COMPATIBLE, "true");
-  
-  protected static final Edm edm = OData.newInstance().createServiceMetadata(
-      new EdmTechProvider(), Collections.<EdmxReference> emptyList()).getEdm();
-
-  protected InputStream getFileAsStream(final String filename) throws IOException {
-    InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);
-    if (in == null) {
-      throw new IOException("Requested file '" + filename + "' was not found.");
-    }
-    return in;
-  }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
index 7bae022..8b87a12 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
@@ -21,25 +21,24 @@ package org.apache.olingo.server.core.deserializer.json;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
+import java.io.IOException;
 
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.Link;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.edm.FullQualifiedName;
-import org.apache.olingo.server.api.OData;
+import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
+import org.apache.olingo.server.core.deserializer.AbstractODataDeserializerTest;
 import org.junit.Test;
 
 public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTest {
+
   @Test
   public void esAllPrimExpandedToOne() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimOne.json");
-    Entity entity = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType).getEntity();
+    final Entity entity = deserialize("EntityESAllPrimExpandedNavPropertyETTwoPrimOne.json");
+
     Link navigationLink = entity.getNavigationLink("NavPropertyETTwoPrimOne");
     assertNotNull(navigationLink);
 
@@ -51,16 +50,12 @@ public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTe
 
   @Test
   public void esAllPrimExpandedToOneWithODataAnnotations() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json");
-    OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
+    deserialize("EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json");
   }
 
   @Test
   public void esAllPrimExpandedToMany() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimMany.json");
-    Entity entity = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType).getEntity();
+    final Entity entity = deserialize("EntityESAllPrimExpandedNavPropertyETTwoPrimMany.json");
 
     Link navigationLink = entity.getNavigationLink("NavPropertyETTwoPrimMany");
     assertNotNull(navigationLink);
@@ -74,61 +69,46 @@ public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTe
 
   @Test
   public void esAllPrimExpandedToManyWithODataAnnotations() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json");
-    OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
+    deserialize("EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json");
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void esAllPrimExpandedToOneWithCustomAnnotations() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json");
     try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
-    } catch (DeserializerException e) {
+      deserialize("EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json");
+      fail("Expected exception not thrown.");
+    } catch (final DeserializerException e) {
       assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
-      throw e;
     }
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void esAllPrimExpandedToManyWithCustomAnnotations() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json");
     try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
-    } catch (DeserializerException e) {
+      deserialize("EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json");
+      fail("Expected exception not thrown.");
+    } catch (final DeserializerException e) {
       assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
-      throw e;
     }
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void expandedToOneInvalidNullValue() throws Exception {
-    String entityString =
+    ODataJsonDeserializerEntityTest.expectException(
         "{\"PropertyInt16\":32767,"
             + "\"NavPropertyETTwoPrimOne\":null"
-            + "}";
-    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, e.getMessageKey());
-      throw e;
-    }
+            + "}",
+        "ETAllPrim",
+        DeserializerException.MessageKeys.INVALID_NULL_PROPERTY);
   }
 
   @Test
   public void expandedToOneValidNullValue() throws Exception {
-    String entityString =
+    final Entity entity = ODataJsonDeserializerEntityTest.deserialize(
         "{\"PropertyInt16\":32767,"
             + "\"NavPropertyETAllPrimOne\":null"
-            + "}";
-    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETTwoPrim"));
-    final Entity entity = OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType)
-        .getEntity();
+            + "}",
+        "ETTwoPrim");
 
     assertEquals(1, entity.getNavigationLinks().size());
     final Link link = entity.getNavigationLinks().get(0);
@@ -138,51 +118,38 @@ public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTe
     assertNull(link.getInlineEntitySet());
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void expandedToOneInvalidStringValue() throws Exception {
-    String entityString =
+    ODataJsonDeserializerEntityTest.expectException(
         "{\"PropertyInt16\":32767,"
             + "\"NavPropertyETTwoPrimOne\":\"First Resource - positive values\""
-            + "}";
-    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY, e.getMessageKey());
-      throw e;
-    }
+            + "}",
+        "ETAllPrim",
+        DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void expandedToManyInvalidNullValue() throws Exception {
-    String entityString =
+    ODataJsonDeserializerEntityTest.expectException(
         "{\"PropertyInt16\":32767,"
             + "\"NavPropertyETTwoPrimMany\":null"
-            + "}";
-    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.INVALID_NULL_PROPERTY, e.getMessageKey());
-      throw e;
-    }
+            + "}",
+        "ETAllPrim",
+        DeserializerException.MessageKeys.INVALID_NULL_PROPERTY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void expandedToManyInvalidStringValue() throws Exception {
-    String entityString =
+    ODataJsonDeserializerEntityTest.expectException(
         "{\"PropertyInt16\":32767,"
             + "\"NavPropertyETTwoPrimMany\":\"First Resource - positive values\""
-            + "}";
-    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entity(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY, e.getMessageKey());
-      throw e;
-    }
+            + "}",
+        "ETAllPrim",
+        DeserializerException.MessageKeys.INVALID_VALUE_FOR_NAVIGATION_PROPERTY);
+  }
+
+  private Entity deserialize(final String resourceName) throws IOException, DeserializerException {
+    return ODataJsonDeserializerEntityTest.deserialize(getFileAsStream(resourceName),
+        "ETAllPrim", ContentType.JSON);
   }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/d6db341d/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
index 49b476d..4b2c6c3 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
@@ -21,6 +21,7 @@ package org.apache.olingo.server.core.deserializer.json;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -30,22 +31,18 @@ import java.util.List;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntityCollection;
 import org.apache.olingo.commons.api.data.Property;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.server.api.OData;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
+import org.apache.olingo.server.core.deserializer.AbstractODataDeserializerTest;
 import org.junit.Test;
 
 public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserializerTest {
 
   @Test
   public void esAllPrim() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("ESAllPrim.json");
-    EntityCollection entitySet =
-        OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType)
-            .getEntityCollection();
-
+    final EntityCollection entitySet = deserialize(getFileAsStream("ESAllPrim.json"), "ETAllPrim");
     assertNotNull(entitySet);
     assertEquals(3, entitySet.getEntities().size());
 
@@ -75,12 +72,7 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
 
   @Test
   public void eSCompCollComp() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETCompCollComp"));
-    InputStream stream = getFileAsStream("ESCompCollComp.json");
-    EntityCollection entitySet =
-        OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType)
-            .getEntityCollection();
-
+    final EntityCollection entitySet = deserialize(getFileAsStream("ESCompCollComp.json"), "ETCompCollComp");
     assertNotNull(entitySet);
     assertEquals(2, entitySet.getEntities().size());
 
@@ -89,172 +81,115 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
 
   @Test
   public void esAllPrimODataAnnotationsAreIgnored() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("ESAllPrimWithODataAnnotations.json");
-    OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
+    deserialize(getFileAsStream("ESAllPrimWithODataAnnotations.json"), "ETAllPrim");
   }
 
   @Test
   public void emptyETAllPrim() throws Exception {
     String entityCollectionString = "{\"value\" : []}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    EntityCollection entityCollection =
-        OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType)
-            .getEntityCollection();
+    final EntityCollection entityCollection = deserialize(entityCollectionString, "ETAllPrim");
     assertNotNull(entityCollection.getEntities());
     assertTrue(entityCollection.getEntities().isEmpty());
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void esAllPrimCustomAnnotationsLeadToNotImplemented() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("ESAllPrimWithCustomAnnotations.json");
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
-      throw e;
-    }
+    expectException(getFileAsStream("ESAllPrimWithCustomAnnotations.json"), "ETAllPrim",
+        DeserializerException.MessageKeys.NOT_IMPLEMENTED);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void esAllPrimDoubleKeysLeadToException() throws Exception {
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    InputStream stream = getFileAsStream("ESAllPrimWithDoubleKey.json");
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.DUPLICATE_JSON_PROPERTY, e.getMessageKey());
-      throw e;
-    }
+    expectException(getFileAsStream("ESAllPrimWithDoubleKey.json"), "ETAllPrim",
+        DeserializerException.MessageKeys.DUPLICATE_PROPERTY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void wrongValueTagJsonValueNull() throws Exception {
-    String entityCollectionString = "{\"value\" : null}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\" : null}", "ETAllPrim",
+        DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void wrongValueTagJsonValueNumber() throws Exception {
-    String entityCollectionString = "{\"value\" : 1234}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\" : 1234}", "ETAllPrim",
+        DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void wrongValueTagJsonValueObject() throws Exception {
-    String entityCollectionString = "{\"value\" : {}}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\" : {}}", "ETAllPrim",
+        DeserializerException.MessageKeys.VALUE_TAG_MUST_BE_AN_ARRAY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void valueTagMissing() throws Exception {
-    String entityCollectionString = "{}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.VALUE_ARRAY_NOT_PRESENT, e.getMessageKey());
-      throw e;
-    }
+    expectException("{}", "ETAllPrim",
+        DeserializerException.MessageKeys.VALUE_ARRAY_NOT_PRESENT);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void wrongValueInValueArrayNumber() throws Exception {
-    String entityCollectionString = "{\"value\" : [1234,123]}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.INVALID_ENTITY, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\" : [1234,123]}", "ETAllPrim",
+        DeserializerException.MessageKeys.INVALID_ENTITY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void wrongValueInValueArrayNestedArray() throws Exception {
-    String entityCollectionString = "{\"value\" : [[],[]]}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.INVALID_ENTITY, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\" : [[],[]]}", "ETAllPrim",
+        DeserializerException.MessageKeys.INVALID_ENTITY);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void invalidJsonSyntax() throws Exception {
-    String entityCollectionString = "{\"value\" : }";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\" : }", "ETAllPrim",
+        DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void emptyInput() throws Exception {
-    OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(
-        new ByteArrayInputStream(new byte[] {}),
-        edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
+    expectException("", "ETAllPrim", DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void unknownContentInCollection() throws Exception {
-    String entityCollectionString = "{\"value\" : [],"
-        + "\"unknown\":null"
-        + "}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
-    try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.UNKNOWN_CONTENT, e.getMessageKey());
-      throw e;
-    }
+    expectException("{\"value\":[],\"unknown\":null}", "ETAllPrim",
+        DeserializerException.MessageKeys.UNKNOWN_CONTENT);
   }
 
-  @Test(expected = DeserializerException.class)
+  @Test
   public void customAnnotationNotSupportedYet() throws Exception {
-    String entityCollectionString = "{\"value\" : [],"
-        + "\"@custom.annotation\":null"
-        + "}";
-    InputStream stream = new ByteArrayInputStream(entityCollectionString.getBytes());
-    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    expectException("{\"value\": [], \"@custom.annotation\": null}", "ETAllPrim",
+        DeserializerException.MessageKeys.NOT_IMPLEMENTED);
+  }
+
+  private EntityCollection deserialize(final InputStream stream, final String entityTypeName)
+      throws DeserializerException {
+    return OData.newInstance().createDeserializer(ContentType.JSON)
+        .entityCollection(stream, edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)))
+        .getEntityCollection();
+  }
+
+  private EntityCollection deserialize(final String input, final String entityTypeName)
+      throws DeserializerException {
+    return OData.newInstance().createDeserializer(ContentType.JSON)
+        .entityCollection(new ByteArrayInputStream(input.getBytes()),
+            edm.getEntityType(new FullQualifiedName(NAMESPACE, entityTypeName)))
+        .getEntityCollection();
+  }
+
+  private void expectException(final InputStream stream, final String entityTypeName,
+      final DeserializerException.MessageKeys messageKey) {
     try {
-      OData.newInstance().createDeserializer(CONTENT_TYPE_JSON).entityCollection(stream, edmEntityType);
-    } catch (DeserializerException e) {
-      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
-      throw e;
+      deserialize(stream, entityTypeName);
+      fail("Expected exception not thrown.");
+    } catch (final DeserializerException e) {
+      assertEquals(messageKey, e.getMessageKey());
     }
   }
+
+  private void expectException(final String entityCollectionString, final String entityTypeName,
+    final DeserializerException.MessageKeys messageKey) {
+    expectException(new ByteArrayInputStream(entityCollectionString.getBytes()), entityTypeName, messageKey);
+  }
 }