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/10/06 10:22:58 UTC

[3/3] git commit: [OLINGO-444] Merge into master

[OLINGO-444] Merge into master


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

Branch: refs/heads/master
Commit: 6fbdb7834542a5052bec1182a0757998e2445870
Parents: 5af9f46 1971a90
Author: mibo <mi...@apache.org>
Authored: Mon Oct 6 10:15:44 2014 +0200
Committer: mibo <mi...@apache.org>
Committed: Mon Oct 6 10:15:44 2014 +0200

----------------------------------------------------------------------
 .../server/api/processor/EntityProcessor.java   |   2 +-
 .../server/api/processor/PropertyProcessor.java |  62 ++++++
 .../server/api/serializer/ODataSerializer.java  |  11 ++
 .../apache/olingo/server/core/ODataHandler.java |  27 ++-
 .../core/serializer/ODataXmlSerializerImpl.java |   9 +
 .../serializer/json/ODataJsonSerializer.java    | 117 ++++++++----
 .../serializer/utils/ContextURLBuilder.java     |  11 +-
 .../tecsvc/processor/TechnicalProcessor.java    | 140 ++++++++++++--
 .../olingo/server/core/ODataHandlerTest.java    |  79 ++++++--
 .../json/ODataJsonSerializerTest.java           | 189 ++++++++++++++-----
 10 files changed, 542 insertions(+), 105 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java
----------------------------------------------------------------------
diff --cc lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java
index 1d2075b,7f2e3ab..783b3d2
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java
@@@ -31,14 -29,10 +31,14 @@@ import org.apache.olingo.server.api.uri
  public interface EntityProcessor extends Processor {
  
    /**
-    * Reads entity data from persistency and puts serialized content and status into the response.
 -   *  Reads entity data from persistence and puts serialized content and status into the response.
 -   *  @param request - OData request object containing raw HTTP information
 -   *  @param response - OData response object for collecting response data
 -   *  @param uriInfo - information of a parsed OData URI
++   * Reads entity data from persistence and puts serialized content and status into the response.
 +   * @param request - OData request object containing raw HTTP information
 +   * @param response - OData response object for collecting response data
 +   * @param uriInfo - information of a parsed OData URI
 +   * @param requestedContentType - requested content type after content negotiation
 +   * @throws ODataApplicationException
 +   * @throws SerializerException
     */
 -  void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format);
 +  void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestedContentType)
 +      throws ODataApplicationException, SerializerException;
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java
----------------------------------------------------------------------
diff --cc lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java
index 0000000,31ff2b1..d0d0ee7
mode 000000,100644..100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PropertyProcessor.java
@@@ -1,0 -1,62 +1,62 @@@
+ /*
+  * 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.api.processor;
+ 
+ import org.apache.olingo.commons.api.format.ContentType;
+ import org.apache.olingo.server.api.ODataApplicationException;
+ import org.apache.olingo.server.api.ODataRequest;
+ import org.apache.olingo.server.api.ODataResponse;
 -import org.apache.olingo.server.api.serializer.ODataSerializerException;
++import org.apache.olingo.server.api.serializer.SerializerException;
+ import org.apache.olingo.server.api.uri.UriInfo;
+ 
+ /**
+  * Processor interface for handling a property of an entity.
+  */
+ public interface PropertyProcessor extends Processor {
+ 
+   /**
+    * Reads primitive or complex property from entity.
+    * If the property is single-valued and has the null value, the service responds with 204 No Content.
+    * If the property is not available, for example due to permissions, the service responds with 404 Not Found
+    *
+    * @param request - OData request object containing raw HTTP information
+    * @param response - OData response object for collecting response data
+    * @param uriInfo - information of a parsed OData URI
+    * @param format - requested content type after content negotiation
+    * @throws ODataApplicationException if service implementation encounters a failure
 -   * @throws ODataSerializerException if serialization failed
++   * @throws SerializerException if serialization failed
+    */
+   void readProperty(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
 -          throws ODataApplicationException, ODataSerializerException;
++          throws ODataApplicationException, SerializerException;
+ 
+   /**
+    * Reads value for primitive property from entity.
+    * If the property is single-valued and has the null value, the service responds with 204 No Content.
+    * If the property is not available, for example due to permissions, the service responds with 404 Not Found
+    *
+    * @param request - OData request object containing raw HTTP information
+    * @param response - OData response object for collecting response data
+    * @param uriInfo - information of a parsed OData URI
+    * @param format - requested content type after content negotiation
+    * @throws ODataApplicationException if service implementation encounters a failure
 -   * @throws ODataSerializerException if serialization failed
++   * @throws SerializerException if serialization failed
+    */
+   void readPropertyValue(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format)
 -          throws ODataApplicationException, ODataSerializerException;
++          throws ODataApplicationException, SerializerException;
+ }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
----------------------------------------------------------------------
diff --cc lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
index e78f56c,57e0014..ba01f2f
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
@@@ -54,7 -56,16 +56,16 @@@ public interface ODataSerializer 
     * @param options      options for the serializer
     */
    InputStream entity(EdmEntitySet edmEntitySet, Entity entity, ODataSerializerOptions options)
 -      throws ODataSerializerException;
 -  
 +      throws SerializerException;
++
+   /**
+    * Writes entity data into an InputStream.
+    * @param edmProperty property definition
+    * @param property property value
+    * @param options options for the serializer
+    */
+   InputStream entityProperty(EdmProperty edmProperty, Property property, ODataSerializerOptions options)
 -          throws ODataSerializerException;
++          throws SerializerException;
  
    /**
     * Writes entity-set data into an InputStream.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index 1f09b21,827dfd8..12e84ed
--- 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
@@@ -33,14 -33,7 +33,15 @@@ import org.apache.olingo.server.api.ODa
  import org.apache.olingo.server.api.ODataResponse;
  import org.apache.olingo.server.api.ODataServerError;
  import org.apache.olingo.server.api.ODataTranslatedException;
 -import org.apache.olingo.server.api.processor.*;
 +import org.apache.olingo.server.api.processor.DefaultProcessor;
 +import org.apache.olingo.server.api.processor.EntitySetProcessor;
 +import org.apache.olingo.server.api.processor.EntityProcessor;
 +import org.apache.olingo.server.api.processor.ExceptionProcessor;
 +import org.apache.olingo.server.api.processor.MetadataProcessor;
 +import org.apache.olingo.server.api.processor.Processor;
++import org.apache.olingo.server.api.processor.PropertyProcessor;
 +import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
 +import org.apache.olingo.server.api.serializer.SerializerException;
  import org.apache.olingo.server.api.uri.UriInfo;
  import org.apache.olingo.server.api.uri.UriResource;
  import org.apache.olingo.server.api.uri.UriResourceNavigation;
@@@ -173,11 -159,10 +174,10 @@@ public class ODataHandler 
    }
  
    private void handleResourceDispatching(final ODataRequest request, final ODataResponse response,
 -      final UriInfo uriInfo) throws ODataTranslatedException, ODataApplicationException {
 +      final UriInfo uriInfo) throws ODataHandlerException, ContentNegotiatorException, ODataApplicationException,
 +      SerializerException {
      int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1;
      UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex);
--    ContentType requestedContentType = null;
  
      switch (lastPathSegment.getKind()) {
      case entitySet:

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
index d327808,3220ce1..0b13381
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
@@@ -26,11 -26,13 +26,13 @@@ import javax.xml.stream.XMLStreamWriter
  
  import org.apache.olingo.commons.api.data.Entity;
  import org.apache.olingo.commons.api.data.EntitySet;
+ import org.apache.olingo.commons.api.data.Property;
  import org.apache.olingo.commons.api.edm.Edm;
  import org.apache.olingo.commons.api.edm.EdmEntitySet;
+ import org.apache.olingo.commons.api.edm.EdmProperty;
  import org.apache.olingo.server.api.ODataServerError;
  import org.apache.olingo.server.api.serializer.ODataSerializer;
 -import org.apache.olingo.server.api.serializer.ODataSerializerException;
 +import org.apache.olingo.server.api.serializer.SerializerException;
  import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
  import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
  import org.apache.olingo.server.api.uri.queryoption.SelectOption;
@@@ -103,7 -105,14 +105,14 @@@ public class ODataXmlSerializerImpl imp
  
    @Override
    public String buildContextURLSelectList(final EdmEntitySet edmEntitySet,
 -      final ExpandOption expand, final SelectOption select) throws ODataSerializerException {
 +      final ExpandOption expand, final SelectOption select) throws SerializerException {
      return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select);
    }
+ 
+   @Override
+   public 	InputStream entityProperty(EdmProperty edmProperty, Property property,
 -    ODataSerializerOptions options) throws ODataSerializerException{
 -    throw new ODataSerializerException("error serialization not implemented for XML format",
 -      ODataSerializerException.MessageKeys.NOT_IMPLEMENTED);
++    ODataSerializerOptions options) throws SerializerException{
++    throw new SerializerException("error serialization not implemented for XML format",
++      SerializerException.MessageKeys.NOT_IMPLEMENTED);
+ 	}
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
----------------------------------------------------------------------
diff --cc lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
index 6f2ff36,e588448..0066f73
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
@@@ -162,12 -160,8 +160,8 @@@ public class ODataJsonSerializer implem
  
    @Override
    public InputStream entity(final EdmEntitySet edmEntitySet, final Entity entity,
 -      final ODataSerializerOptions options) throws ODataSerializerException {
 +      final ODataSerializerOptions options) throws SerializerException {
-     final ContextURL contextURL = options == null ? null : options.getContextURL();
-     if (format != ODataFormat.JSON_NO_METADATA && contextURL == null) {
-       throw new SerializerException("ContextURL null!",
-           SerializerException.MessageKeys.NO_CONTEXT_URL);
-     }
+     final ContextURL contextURL = checkContextURL(options);
      CircleStreamBuffer buffer = new CircleStreamBuffer();
      try {
        JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
@@@ -181,9 -175,22 +175,22 @@@
      return buffer.getInputStream();
    }
  
+   private ContextURL checkContextURL(final ODataSerializerOptions options)
 -      throws ODataSerializerException {
++      throws SerializerException {
+     ContextURL contextURL = options == null ? null : options.getContextURL();
+     if (format != ODataFormat.JSON_NO_METADATA && contextURL == null) {
 -      throw new ODataSerializerException("ContextURL null!",
 -          ODataSerializerException.MessageKeys.NO_CONTEXT_URL);
++      throw new SerializerException("ContextURL null!",
++          SerializerException.MessageKeys.NO_CONTEXT_URL);
+     }
+     if (format == ODataFormat.JSON_NO_METADATA) {
+       contextURL = null;
+     }
+     return contextURL;
+   }
+ 
    protected void writeEntitySet(final EdmEntityType entityType, final EntitySet entitySet,
        final ExpandOption expand, final SelectOption select, final JsonGenerator json)
 -      throws IOException, ODataSerializerException {
 +      throws IOException, SerializerException {
      json.writeStartArray();
      for (final Entity entity : entitySet.getEntities()) {
        writeEntity(entityType, entity, null, expand, select, json);
@@@ -288,24 -295,30 +295,30 @@@
          json.writeNull();
        }
      } else {
-       try {
-         if (edmProperty.isCollection()) {
-           writeCollection(edmProperty, property, selectedPaths, json);
-         } else if (edmProperty.isPrimitive()) {
-           writePrimitive(edmProperty, property, json);
-         } else if (property.isLinkedComplex()) {
-           writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json);
-         } else if (property.isComplex()) {
-           writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
-         } else {
-           throw new SerializerException("Property type not yet supported!",
-               SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
-         }
-       } catch (final EdmPrimitiveTypeException e) {
-         throw new SerializerException("Wrong value for property!", e,
-             SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
-             edmProperty.getName(), property.getValue().toString());
+       writePropertyValue(edmProperty, property, selectedPaths, json);
+     }
+   }
+ 
+   private void writePropertyValue(final EdmProperty edmProperty,
+       final Property property, final Set<List<String>> selectedPaths,
 -      final JsonGenerator json) throws IOException, ODataSerializerException {
++      final JsonGenerator json) throws IOException, SerializerException {
+     try {
+       if (edmProperty.isCollection()) {
+         writeCollection(edmProperty, property, selectedPaths, json);
+       } else if (edmProperty.isPrimitive()) {
+         writePrimitive(edmProperty, property, json);
+       } else if (property.isLinkedComplex()) {
+         writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json);
+       } else if (property.isComplex()) {
+         writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
+       } else {
 -        throw new ODataSerializerException("Property type not yet supported!",
 -            ODataSerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
++        throw new SerializerException("Property type not yet supported!",
++            SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
        }
+     } catch (final EdmPrimitiveTypeException e) {
 -      throw new ODataSerializerException("Wrong value for property!", e,
 -          ODataSerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
++      throw new SerializerException("Wrong value for property!", e,
++          SerializerException.MessageKeys.WRONG_PROPERTY_VALUE,
+           edmProperty.getName(), property.getValue().toString());
      }
    }
  
@@@ -377,9 -390,16 +390,16 @@@
  
    protected void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
        final Set<List<String>> selectedPaths, JsonGenerator json)
 -      throws IOException, EdmPrimitiveTypeException, ODataSerializerException {
 +      throws IOException, EdmPrimitiveTypeException, SerializerException {
-     final EdmComplexType type = (EdmComplexType) edmProperty.getType();
      json.writeStartObject();
+     writePropertyValues(edmProperty, properties, selectedPaths, json);
+     json.writeEndObject();
+   }
+ 
+   private void writePropertyValues(final EdmProperty edmProperty,
+                                    final List<Property> properties, final Set<List<String>> selectedPaths,
 -                                   JsonGenerator json) throws IOException, ODataSerializerException {
++                                   JsonGenerator json) throws IOException, SerializerException {
+     final EdmComplexType type = (EdmComplexType) edmProperty.getType();
      for (final String propertyName : type.getPropertyNames()) {
        final Property property = findProperty(propertyName, properties);
        if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
@@@ -402,7 -421,41 +421,41 @@@
  
    @Override
    public String buildContextURLSelectList(final EdmEntitySet edmEntitySet,
 -      final ExpandOption expand, final SelectOption select) throws ODataSerializerException {
 +      final ExpandOption expand, final SelectOption select) throws SerializerException {
      return ContextURLHelper.buildSelectList(edmEntitySet.getEntityType(), expand, select);
    }
+ 
+   @Override
+   public InputStream entityProperty(EdmProperty edmProperty,
+       Property property, ODataSerializerOptions options)
 -      throws ODataSerializerException {
++      throws SerializerException {
+     final ContextURL contextURL = checkContextURL(options);
+     CircleStreamBuffer buffer = new CircleStreamBuffer();
+     try {
+       JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
+       json.writeStartObject();
+       if (format != ODataFormat.JSON_NO_METADATA) {
+         if (contextURL != null) {
+           json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
+         }
+       }
+       if (property.isPrimitive() && property.isNull()) {
 -        throw new ODataSerializerException("Property value can not be null",
 -            ODataSerializerException.MessageKeys.NULL_INPUT);
++        throw new SerializerException("Property value can not be null",
++            SerializerException.MessageKeys.NULL_INPUT);
+       } else if (property.isComplex() && !property.isNull()) {
+         writePropertyValues(edmProperty, property.asComplex(), null, json);
+       } else if (property.isLinkedComplex() && !property.isNull()) {
+         writePropertyValues(edmProperty, property.asLinkedComplex().getValue(), null, json);
+       } else {
+         json.writeFieldName(Constants.VALUE);
+         writePropertyValue(edmProperty, property, null, json);
+       }
+       json.writeEndObject();
+       json.close();
+     } catch (final IOException e) {
 -      throw new ODataSerializerException("An I/O exception occurred.", e,
 -          ODataSerializerException.MessageKeys.IO_EXCEPTION);
++      throw new SerializerException("An I/O exception occurred.", e,
++          SerializerException.MessageKeys.IO_EXCEPTION);
+     }
+     return buffer.getInputStream();
+   }
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --cc lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
index 06ccf53,99f64ef..65ae74c
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
@@@ -22,8 -22,8 +22,12 @@@ import org.apache.olingo.commons.api.da
  import org.apache.olingo.commons.api.data.Entity;
  import org.apache.olingo.commons.api.data.EntitySet;
  import org.apache.olingo.commons.api.data.ContextURL.Suffix;
+ import org.apache.olingo.commons.api.data.Property;
 -import org.apache.olingo.commons.api.edm.*;
 +import org.apache.olingo.commons.api.edm.Edm;
 +import org.apache.olingo.commons.api.edm.EdmEntitySet;
++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.format.ContentType;
  import org.apache.olingo.commons.api.format.ODataFormat;
  import org.apache.olingo.commons.api.http.HttpHeader;
@@@ -34,13 -34,11 +38,16 @@@ import org.apache.olingo.server.api.ODa
  import org.apache.olingo.server.api.ODataResponse;
  import org.apache.olingo.server.api.processor.EntitySetProcessor;
  import org.apache.olingo.server.api.processor.EntityProcessor;
+ import org.apache.olingo.server.api.processor.PropertyProcessor;
  import org.apache.olingo.server.api.serializer.ODataSerializer;
 -import org.apache.olingo.server.api.serializer.ODataSerializerException;
 +import org.apache.olingo.server.api.serializer.SerializerException;
  import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
 -import org.apache.olingo.server.api.uri.*;
 +import org.apache.olingo.server.api.uri.UriInfo;
 +import org.apache.olingo.server.api.uri.UriInfoResource;
 +import org.apache.olingo.server.api.uri.UriResource;
 +import org.apache.olingo.server.api.uri.UriResourceEntitySet;
++import org.apache.olingo.server.api.uri.UriResourceKind;
++import org.apache.olingo.server.api.uri.UriResourceProperty;
  import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
  import org.apache.olingo.server.api.uri.queryoption.SelectOption;
  import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
@@@ -224,10 -237,100 +246,100 @@@ public class TechnicalProcessor impleme
    }
  
    private ContextURL getContextUrl(final ODataSerializer serializer,
--      final EdmEntitySet entitySet, final boolean isSingleEntity,
-       final ExpandOption expand, final SelectOption select) throws SerializerException {
 -      final ExpandOption expand, final SelectOption select, final String navOrPropertyPath)
 -      throws ODataSerializerException {
++        final EdmEntitySet entitySet, final boolean isSingleEntity,
++        final ExpandOption expand, final SelectOption select, final String navOrPropertyPath)
++      throws SerializerException {
+ 
      return ContextURL.with().entitySet(entitySet)
          .selectList(serializer.buildContextURLSelectList(entitySet, expand, select))
-         .suffix(isSingleEntity ? Suffix.ENTITY : null).build();
+         .suffix(isSingleEntity ? Suffix.ENTITY : null)
+         .navOrPropertyPath(navOrPropertyPath)
+         .build();
+   }
+ 
+   @Override
+   public void readProperty(ODataRequest request,
+                            ODataResponse response, UriInfo uriInfo, ContentType contentType) {
+ 
+     if (!validateOptions(uriInfo.asUriInfoResource())) {
+       response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
+       return;
+     }
+     try {
+       final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
+       final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet);
+       if (entity == null) {
+         response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode());
+       } else {
+         UriResourceProperty uriProperty = (UriResourceProperty) uriInfo
+             .getUriResourceParts().get(uriInfo.getUriResourceParts().size() - 1);
+         EdmProperty edmProperty = uriProperty.getProperty();
+         Property property = entity.getProperty(edmProperty.getName());
+         if (property == null) {
+           response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode());
+         } else {
+           if (property.getValue() == null) {
+             response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+           } else {
+             final ODataFormat format = ODataFormat.fromContentType(contentType);
+             ODataSerializer serializer = odata.createSerializer(format);
+             response.setContent(serializer.entityProperty(edmProperty, property,
+                 ODataSerializerOptions.with()
+                     .contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
+                         getContextUrl(serializer, edmEntitySet, true, null, null, edmProperty.getName()))
+                     .build()));
+             response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+             response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
+           }
+         }
+       }
+     } catch (final DataProvider.DataProviderException e) {
+       response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
 -    } catch (final ODataSerializerException e) {
++    } catch (final SerializerException e) {
+       response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+     } catch (final ODataApplicationException e) {
+       response.setStatusCode(e.getStatusCode());
+     }
+   }
+ 
+   @Override
+   public void readPropertyValue(ODataRequest request, ODataResponse response,
+                                 UriInfo uriInfo, ContentType contentType) {
+ 
+     if (!validateOptions(uriInfo.asUriInfoResource())) {
+       response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
+       return;
+     }
+     try {
+       final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource());
+       final Entity entity = readEntityInternal(uriInfo.asUriInfoResource(), edmEntitySet);
+       if (entity == null) {
+         response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode());
+       } else {
+         UriResourceProperty uriProperty = (UriResourceProperty) uriInfo
+                 .getUriResourceParts().get(uriInfo.getUriResourceParts().size() - 2);
+         EdmProperty edmProperty = uriProperty.getProperty();
+         Property property = entity.getProperty(edmProperty.getName());
+         if (property == null || property.getValue() == null) {
+           response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+         } else {
+           final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
+           final String value = type.valueToString(property.getValue(),
+                   edmProperty.isNullable(), edmProperty.getMaxLength(),
+                   edmProperty.getPrecision(), edmProperty.getScale(), edmProperty.isUnicode());
+           response.setContent(new ByteArrayInputStream(value.getBytes("UTF-8")));
+           response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+           response.setHeader(HttpHeader.CONTENT_TYPE, ContentType.TEXT_PLAIN.toContentTypeString());
+         }
+       }
+     } catch (final DataProvider.DataProviderException e) {
+       response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+     } catch (final EdmPrimitiveTypeException e) {
+       response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+     } catch (final UnsupportedEncodingException e) {
+       response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+     } catch (final ODataApplicationException e) {
+       response.setStatusCode(e.getStatusCode());
+     }
    }
  }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6fbdb783/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
----------------------------------------------------------------------
diff --cc lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
index 3d8243e,250cabb..7835b7a
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
@@@ -29,13 -29,16 +29,16 @@@ import org.apache.olingo.commons.api.da
  import org.apache.olingo.commons.api.data.EntitySet;
  import org.apache.olingo.commons.api.data.ValueType;
  import org.apache.olingo.commons.api.edm.Edm;
+ import org.apache.olingo.commons.api.edm.EdmElement;
  import org.apache.olingo.commons.api.edm.EdmEntityContainer;
  import org.apache.olingo.commons.api.edm.EdmEntitySet;
+ import org.apache.olingo.commons.api.edm.EdmProperty;
  import org.apache.olingo.commons.api.edm.FullQualifiedName;
  import org.apache.olingo.commons.api.format.ODataFormat;
+ import org.apache.olingo.commons.core.data.PropertyImpl;
  import org.apache.olingo.server.api.OData;
  import org.apache.olingo.server.api.serializer.ODataSerializer;
 -import org.apache.olingo.server.api.serializer.ODataSerializerException;
 +import org.apache.olingo.server.api.serializer.SerializerException;
  import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
  import org.apache.olingo.server.api.uri.queryoption.CountOption;
  import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
@@@ -555,15 -559,111 +559,110 @@@ public class ODataJsonSerializerTest 
                  .expand(expand)
                  .build()));
      Assert.assertEquals("{"
-         + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\","
-         + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\","
-         + "\"NavPropertyETAllPrimMany\":["
-         + "{\"PropertyInt32\":-2147483648,\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]},"
-         + "{\"PropertyInt32\":0,\"NavPropertyETTwoPrimOne\":null,"
-         + "\"NavPropertyETTwoPrimMany\":["
-         + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"
-         + "{\"PropertyInt16\":-32766,\"PropertyString\":\"Test String3\"},"
-         + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}",
+             + "\"@odata.context\":\"$metadata#ESTwoPrim(NavPropertyETAllPrimMany(PropertyInt32))/$entity\","
+             + "\"PropertyInt16\":-365,\"PropertyString\":\"Test String2\","
+             + "\"NavPropertyETAllPrimMany\":["
+             + "{\"PropertyInt32\":-2147483648,\"NavPropertyETTwoPrimOne\":null,\"NavPropertyETTwoPrimMany\":[]},"
+             + "{\"PropertyInt32\":0,\"NavPropertyETTwoPrimOne\":null,"
+             + "\"NavPropertyETTwoPrimMany\":["
+             + "{\"PropertyInt16\":32766,\"PropertyString\":\"Test String1\"},"
+             + "{\"PropertyInt16\":-32766,\"PropertyString\":\"Test String3\"},"
+             + "{\"PropertyInt16\":32767,\"PropertyString\":\"Test String4\"}]}]}",
+         resultString);
+   }
+ 
+   @Test
+   public void individualPrimitiveProperty() throws Exception {
+     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+     final EntitySet entitySet = data.readAll(edmEntitySet);
+ 
+     EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString");
+     Entity entity = entitySet.getEntities().get(0);
+ 
+     InputStream result = serializer
+         .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"),
+             ODataSerializerOptions.with()
+                 .contextURL(ContextURL.with().entitySetOrSingletonOrType("Edm.String")
+                     .build())
+                 .build());
+     final String resultString = IOUtils.toString(result);
+     Assert.assertEquals("{"
+             + "\"@odata.context\":\"$metadata#Edm.String\","
+             + "\"value\":\"First Resource - positive values\"}",
+         resultString);
+   }
+ 
 -  @Test(expected = ODataSerializerException.class)
++  @Test(expected = SerializerException.class)
+   public void individualPrimitivePropertyNull() throws Exception {
+     PropertyImpl property = new PropertyImpl("Edm.String", "PropertyString", ValueType.PRIMITIVE, null);
+     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+     EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString");
 -    InputStream result = serializer
 -        .entityProperty((EdmProperty) edmElement, property,
++    serializer.entityProperty((EdmProperty) edmElement, property,
+             ODataSerializerOptions.with()
+                 .contextURL(ContextURL.with().entitySetOrSingletonOrType("Edm.String")
+                     .build())
+                 .build());
+   }
+ 
+   @Test
+   public void individualPrimitivePropertyArray() throws Exception {
+     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim");
+     final EntitySet entitySet = data.readAll(edmEntitySet);
+ 
+     EdmElement edmElement = edmEntitySet.getEntityType().getProperty("CollPropertyString");
+     Entity entity = entitySet.getEntities().get(0);
+ 
+     InputStream result = serializer
+         .entityProperty((EdmProperty) edmElement, entity.getProperty("CollPropertyString"),
+             ODataSerializerOptions.with()
+                 .contextURL(ContextURL.with().entitySetOrSingletonOrType("Collection(Edm.String)")
+                     .build())
+                 .build());
+     final String resultString = IOUtils.toString(result);
+     Assert.assertEquals("{"
+             + "\"@odata.context\":\"$metadata#Collection%28Edm.String%29\","
+             + "\"value\":[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]}",
+         resultString);
+   }
+ 
+   @Test
+   @Ignore("Serialization of value of primitive property is not done by json serializer")
+   public void individualPrimitivePropertyValue() throws Exception {
+     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim");
+     final EntitySet entitySet = data.readAll(edmEntitySet);
+ 
+     EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyString");
+     Entity entity = entitySet.getEntities().get(0);
+ 
+     InputStream result = serializer
+         .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyString"),
+             ODataSerializerOptions.with()
+                 .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESAllPrim(0)")
+                     .navOrPropertyPath("PropertyString")
+                     .build())
+                 .build());
+     final String resultString = IOUtils.toString(result);
+     Assert.assertEquals("\"First Resource - positive values\"", resultString);
+   }
+ 
+   @Test
+   public void individualComplexProperty() throws Exception {
+     final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESMixPrimCollComp");
+     final EntitySet entitySet = data.readAll(edmEntitySet);
+ 
+     EdmElement edmElement = edmEntitySet.getEntityType().getProperty("PropertyComp");
+     Entity entity = entitySet.getEntities().get(0);
+ 
+     InputStream result = serializer
+         .entityProperty((EdmProperty) edmElement, entity.getProperty("PropertyComp"),
+             ODataSerializerOptions.with()
+                 .contextURL(ContextURL.with().entitySetOrSingletonOrType("ESMixPrimCollComp.PropertyComp")
+                     .build())
+                 .build());
+     final String resultString = IOUtils.toString(result);
+     Assert.assertEquals("{"
+             + "\"@odata.context\":\"$metadata#ESMixPrimCollComp.PropertyComp\","
+             + "\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"}",
          resultString);
    }
  }