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/20 15:16:04 UTC

[1/2] [OLINGO-450]: implementing support for execution of Functions and Actions

Repository: olingo-odata4
Updated Branches:
  refs/heads/OLINGO-450_FunctionActionExecution [created] 9c6217632


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
index ba808ee..627813e 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/UriResourceImplTest.java
@@ -44,6 +44,7 @@ import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
@@ -84,7 +85,7 @@ public class UriResourceImplTest {
     // action import
     impl = new UriResourceActionImpl();
     EdmActionImport actionImport = edm.getEntityContainer(null).getActionImport("AIRTPrimParam");
-    impl.setActionImport(actionImport);
+    impl.setActionImport(actionImport, Collections.EMPTY_LIST);
     assertEquals(actionImport, impl.getActionImport());
     assertEquals(actionImport.getUnboundAction(), impl.getAction());
     assertEquals(false, impl.isCollection());


[2/2] git commit: [OLINGO-450]: implementing support for execution of Functions and Actions

Posted by mi...@apache.org.
[OLINGO-450]: implementing support for execution of Functions and Actions

Signed-off-by: mibo <mi...@apache.org>


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

Branch: refs/heads/OLINGO-450_FunctionActionExecution
Commit: 9c621763216d93bfb61bfcd277fad4572ec9c09d
Parents: 35f24e9
Author: Ramesh Reddy <ra...@jboss.org>
Authored: Thu Oct 2 15:11:13 2014 -0500
Committer: mibo <mi...@apache.org>
Committed: Mon Oct 20 15:06:43 2014 +0200

----------------------------------------------------------------------
 .../fit/tecsvc/client/ProcedureITCase.java      | 295 +++++++++++++++++++
 .../olingo/commons/api/edm/EdmOperation.java    |   5 +
 .../commons/core/edm/AbstractEdmOperation.java  |   5 +
 .../api/processor/ProcedureProcessor.java       |  48 +++
 .../api/serializer/BoundProcedureOption.java    |  98 ++++++
 .../server/api/serializer/ODataSerializer.java  |  10 +
 .../api/serializer/ODataSerializerOptions.java  |  15 +-
 .../server/api/uri/UriResourceAction.java       |   7 +
 .../apache/olingo/server/core/ODataHandler.java |  27 ++
 .../core/serializer/ODataXmlSerializerImpl.java |   9 +
 .../serializer/json/ODataJsonSerializer.java    | 197 +++++++++++--
 .../xml/MetadataDocumentXmlSerializer.java      |   5 +-
 .../server/core/uri/UriResourceActionImpl.java  |  23 +-
 .../core/uri/parser/UriParseTreeVisitor.java    |  27 +-
 lib/server-tecsvc/pom.xml                       |   1 -
 .../olingo/server/tecsvc/data/DataProvider.java | 107 +++++++
 .../tecsvc/processor/TechnicalProcessor.java    | 174 ++++++++++-
 .../tecsvc/provider/ContainerProvider.java      |   8 +
 .../tecsvc/provider/FunctionProvider.java       |  64 +++-
 .../server/tecsvc/provider/SchemaProvider.java  |   4 +
 .../olingo/server/core/ODataHandlerTest.java    |  61 +++-
 .../server/core/uri/UriResourceImplTest.java    |   3 +-
 22 files changed, 1160 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java
new file mode 100644
index 0000000..45c3e10
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/ProcedureITCase.java
@@ -0,0 +1,295 @@
+/* 
+ * 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.fit.tecsvc.client;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.olingo.client.api.CommonODataClient;
+import org.apache.olingo.client.api.communication.request.invoke.ODataInvokeRequest;
+import org.apache.olingo.client.api.communication.request.invoke.ODataNoContent;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataPropertyRequest;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.v4.ODataClient;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.commons.api.domain.CommonODataProperty;
+import org.apache.olingo.commons.api.domain.ODataPrimitiveValue;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.commons.api.domain.v4.ODataProperty;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.fit.tecsvc.TecSvcConst;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class ProcedureITCase  extends AbstractBaseTestITCase {
+
+  private static final String SERVICE_URI = TecSvcConst.BASE_URI;
+  
+  @Override
+  protected CommonODataClient<?> getClient() {
+    ODataClient odata = ODataClientFactory.getV4();
+    odata.getConfiguration().setDefaultPubFormat(ODataFormat.JSON);
+    return odata;
+  }  
+
+  @Test // primitive return
+  public void executeFINRTInt16() {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FINRTInt16")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+    final CommonODataProperty property = response.getBody();
+    assertNotNull(property);
+    assertEquals(5, property.getPrimitiveValue().toValue());
+  }
+  
+  @Test
+  public void executeFINRTInt16Raw() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FINRTInt16")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+    assertEquals("{\"@odata.context\":\"$metadata#Edm.Int16\",\"value\":5}", 
+        IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }
+  
+  @Test // collection return
+  public void executeUFCRTCollString() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FICRTCollString")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+
+    assertEquals("{\"@odata.context\":\"$metadata#Collection(Edm.String)\",\"value\":[\"dummy1\",\"dummy2\"]}", 
+        IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }
+  
+  @Test  // complex return 
+  public void executeUFCRTCTTwoPrimParam() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FICRTCTTwoPrimParam(ParameterString='param1',ParameterInt16=2)")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+    String expected = 
+        "{\"@odata.context\":\"$metadata#olingo.odata.test1.CTTwoPrim\","+
+        "\"PropertyInt16\":2,"+
+        "\"PropertyString\":\"param1\""+
+        "}";
+    assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }
+  
+  @Test // complex collection
+  public void executeUFCRTCollCTTwoPrimParam() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FICRTCollCTTwoPrimParam(ParameterString='param1',ParameterInt16=2)")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+    String expected = 
+        "{\"@odata.context\":\"$metadata#Collection(olingo.odata.test1.CTTwoPrim)\","+
+        "\"value\":[{" +
+        "\"PropertyInt16\":2,"+
+        "\"PropertyString\":\"param1\"}"+
+        ",{" +
+        "\"PropertyInt16\":2,"+
+        "\"PropertyString\":\"param1\"}"+
+        "]}";
+    assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }
+  
+  @Test // Entity type return 
+  public void executeUFCRTETAllPrimTwoParam() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FICRTETAllPrimTwoParam(ParameterString='param1',ParameterInt16=2)")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+    String expected = 
+        "{\"@odata.context\":\"$metadata#ESAllPrim/$entity\","
+        + "\"PropertyInt16\":32767,"
+        + "\"PropertyString\":\"First Resource - positive values\","
+        + "\"PropertyBoolean\":true,"
+        + "\"PropertyByte\":255,"
+        + "\"PropertySByte\":127,"
+        + "\"PropertyInt32\":2147483647,"
+        + "\"PropertyInt64\":9223372036854775807,"
+        + "\"PropertySingle\":1.79E20,"
+        + "\"PropertyDouble\":-1.79E19,"
+        + "\"PropertyDecimal\":34,"
+        + "\"PropertyBinary\":\"ASNFZ4mrze8=\","
+        + "\"PropertyDate\":\"2012-12-03\","
+        + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\","
+        + "\"PropertyDuration\":\"PT6S\","
+        + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\""
+        + ",\"PropertyTimeOfDay\":\"03:26:05\""
+        + "}";
+    assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }
+  
+  @Test // Entity Set return 
+  public void executeUFFICRTESMixPrimCollCompTwoParam() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendOperationCallSegment("FICRTESMixPrimCollCompTwoParam(ParameterString='param1',ParameterInt16=2)")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString()));
+    String expected = 
+        "{\"@odata.context\":\"$metadata#ESMixPrimCollComp\","
+        + "\"value\":["
+        + "{\"PropertyInt16\":32767,"
+        + "\"CollPropertyString\":["
+          + "\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"],"
+        + "\"PropertyComp\":{\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"},"
+        + "\"CollPropertyComp\":["
+          + "{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"},"
+          + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"},"
+          + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}"
+          + "]"
+        + "},";
+    assertTrue(IOUtils.toString(response.getRawResponse(), "UTF-8").startsWith(expected));
+  }  
+  
+  //Bounded - binding param enitityset return string
+  @Test
+  public void executeBFESTwoPrimRTString() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESTwoPrim")
+            .appendNavigationSegment("olingo.odata.test1")
+            .appendOperationCallSegment("BFESTwoPrimRTString")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    String expected = "{\"@odata.context\":\"$metadata#Edm.String\","
+        + "\"#olingo.odata.test1.BFESTwoPrimRTString(BindingParam)\":{},"
+        + "\"value\":\"TEST-A\"}";
+    assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  } 
+  
+  //Bounded - binding param enitity return string[]
+  @Test
+  public void executeBFESTwoPrimRTCollString() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESTwoPrim")
+            .appendKeySegment(1)
+            .appendNavigationSegment("olingo.odata.test1")
+            .appendOperationCallSegment("BFESTwoPrimRTCollString")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    String expected = "{\"@odata.context\":\"$metadata#Collection(Edm.String)\","
+        + "\"#olingo.odata.test1.BFESTwoPrimRTCollString(BindingParam)\":{},"
+        + "\"value\":[\"dummy1\",\"dummy2\"]}";
+    assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }
+  
+  //Bounded - binding param enitityset return entity
+  @Test
+  @Ignore
+  public void executenameBFESTwoPrimRTETTwoPrim() throws Exception {
+    final ODataPropertyRequest<CommonODataProperty> request = getClient().getRetrieveRequestFactory()
+        .getPropertyRequest(getClient().newURIBuilder(SERVICE_URI)
+            .appendEntitySetSegment("ESTwoPrim")
+            .appendNavigationSegment("olingo.odata.test1")
+            .appendOperationCallSegment("BFESTwoPrimRTETTwoPrim(ParameterString='param1')")
+            .build());
+    
+    assertNotNull(request);
+
+    final ODataRetrieveResponse<CommonODataProperty> response = request.execute();
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    String expected = "";
+    assertEquals(expected, IOUtils.toString(response.getRawResponse(), "UTF-8"));
+  }  
+  
+  /*
+   *  Actions test cases
+   */
+  
+  @Test // primitive return
+  public void executeAIRTPrimParam() throws Exception {
+    final ODataPrimitiveValue param = getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt16((short)22);
+    final ODataInvokeRequest<ODataProperty> request = getClient().getInvokeRequestFactory().
+        getActionInvokeRequest(getClient().newURIBuilder(SERVICE_URI).
+            appendOperationCallSegment("AIRTPrimParam").build(), ODataProperty.class,
+            Collections.<String, ODataValue> singletonMap("ParameterInt16", param));
+    final ODataProperty response = request.execute().getBody();    
+
+    assertEquals("return-string", response.getValue().asPrimitive().toValue());
+  }
+  
+  @Test // enrity return
+  public void executeActionEnrity() throws Exception {
+    //TODO: needs the EntitySetPath fix
+  }  
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
index d1bc3de..eff49d6 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmOperation.java
@@ -64,4 +64,9 @@ public interface EdmOperation extends EdmType, EdmAnnotatable {
    */
   Boolean isBindingParameterTypeCollection();
 
+  /**
+   * @return EntitySetPath if one available 
+   * @return
+   */
+  String getEntitySetPath();
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
index dd7ae81..9264d42 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java
@@ -114,4 +114,9 @@ public abstract class AbstractEdmOperation extends EdmTypeImpl implements EdmOpe
   public boolean isBound() {
     return isBound;
   }
+  
+  @Override
+  public String getEntitySetPath() {
+    return this.entitySetPath;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java
new file mode 100644
index 0000000..8bcb025
--- /dev/null
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ProcedureProcessor.java
@@ -0,0 +1,48 @@
+/*
+ * 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.SerializerException;
+import org.apache.olingo.server.api.uri.UriInfo;
+
+public interface ProcedureProcessor extends Processor {
+  /**
+   * Execute/Invokes the FunctionImport and returns the result
+   * @param request OData request object containing raw HTTP information
+   * @param response OData response object for collecting response data
+   * @param uriInfo Information about the request URI
+   * @param requestedContentType content-type of the response requested
+   */
+  void executeFunction(ODataRequest request, ODataResponse response,
+      UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException;
+
+  /**
+   * Execute/Invokes the ActionImport and returns the result if one exists.
+   * @param request OData request object containing raw HTTP information
+   * @param response OData response object for collecting response data
+   * @param uriInfo Information about the request URI
+   * @param requestedContentType content-type of the response requested
+   */  
+  void executeAction(ODataRequest request, ODataResponse response,
+      UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException;
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java
new file mode 100644
index 0000000..cb90484
--- /dev/null
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/BoundProcedureOption.java
@@ -0,0 +1,98 @@
+/*
+ * 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.serializer;
+
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+
+public class BoundProcedureOption {
+  private String procedureName;
+  private String title;
+  private String target;
+
+  public String getProcedureName() {
+    return procedureName;
+  }
+  public String getTitle() {
+    return title;
+  }
+  public String getTarget() {
+    return target;
+  }
+  
+  public static Builder with() {
+    return new Builder();
+  }
+
+  public static final class Builder {
+    private BoundProcedureOption procedure = new BoundProcedureOption();
+    private EdmFunction function;
+    private EdmAction action;
+    
+    public Builder setFunction(EdmFunction function) {
+      this.function = function;
+      return this;
+    }
+    public Builder setAction(EdmAction action) {
+      this.action = action;
+      return this;
+    }    
+    public Builder setTitle(String title) {
+      procedure.title = title;
+      return this;
+    }
+    public Builder setTarget(String target) {
+      procedure.target = target;
+      return this;
+    }
+    public BoundProcedureOption build() {
+      if (this.function != null && this.function.isBound()) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.function.getFullQualifiedName().getFullQualifiedNameAsString());
+        if (!this.function.getParameterNames().isEmpty()) {
+          sb.append("(");
+          for (int i = 0; i < this.function.getParameterNames().size(); i++) {
+            if (i > 0) {
+              sb.append(",");
+            }
+            sb.append(this.function.getParameterNames().get(i));
+          }
+          sb.append(")");
+        }
+        this.procedure.procedureName = sb.toString();
+      } else if (this.action != null && this.action.isBound()) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(this.action.getFullQualifiedName().getFullQualifiedNameAsString());
+        if (!this.action.getParameterNames().isEmpty()) {
+          sb.append("(");
+          for (int i = 0; i < this.action.getParameterNames().size(); i++) {
+            if (i > 0) {
+              sb.append(",");
+            }
+            sb.append(this.action.getParameterNames().get(i));
+          }
+          sb.append(")");
+        }
+        this.procedure.procedureName = sb.toString();
+        
+      }
+      return this.procedure;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializer.java
----------------------------------------------------------------------
diff --git 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
index 1331247..0d8acaa 100644
--- 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
@@ -26,6 +26,7 @@ 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.commons.api.edm.EdmReturnType;
 import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
@@ -67,6 +68,15 @@ public interface ODataSerializer {
    */
   InputStream entityProperty(EdmProperty edmProperty, Property property, ODataSerializerOptions options)
           throws SerializerException;
+  
+  /**
+   * Writes the Function/Action procedure return values.
+   * @param returnType return type definition
+   * @param property property value
+   * @param options options for the serializer
+   */
+  InputStream procedureReturn(EdmReturnType returnType, Property property,
+      ODataSerializerOptions options) throws SerializerException;
 
   /**
    * Writes entity-set data into an InputStream.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
index e4ac767..e019ab7 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/serializer/ODataSerializerOptions.java
@@ -30,6 +30,7 @@ public class ODataSerializerOptions {
   private CountOption count;
   private ExpandOption expand;
   private SelectOption select;
+  private BoundProcedureOption boundProcedure;
 
   /** Gets the {@link ContextURL}. */
   public ContextURL getContextURL() {
@@ -50,7 +51,12 @@ public class ODataSerializerOptions {
   public SelectOption getSelect() {
     return select;
   }
-
+  
+  /** Gets BoundProcedure options */
+  public BoundProcedureOption getBoundProcedure() {
+    return boundProcedure;
+  }
+  
   private ODataSerializerOptions() {}
 
   /** Initializes the options builder. */
@@ -90,6 +96,13 @@ public class ODataSerializerOptions {
       options.select = select;
       return this;
     }
+    /**
+     * Sets bound procedure (fuction/action) metadata   
+     */
+    public Builder boundProcedure(final BoundProcedureOption proc) {
+      options.boundProcedure = proc;
+      return this;
+    }    
 
     /** Builds the OData serializer options. */
     public ODataSerializerOptions build() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
index 1cdc521..aebc857 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/uri/UriResourceAction.java
@@ -18,6 +18,8 @@
  */
 package org.apache.olingo.server.api.uri;
 
+import java.util.List;
+
 import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmActionImport;
 
@@ -38,5 +40,10 @@ public interface UriResourceAction extends UriResourcePartTyped {
    * @return
    */
   EdmActionImport getActionImport();
+  
+  /**
+   * @return List of action parameters
+   */
+  List<UriParameter> getParameters();  
 
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
index 4ac780d..79c1547 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java
@@ -38,6 +38,7 @@ 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.ProcedureProcessor;
 import org.apache.olingo.server.api.processor.Processor;
 import org.apache.olingo.server.api.processor.PropertyProcessor;
 import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
@@ -272,6 +273,32 @@ public class ODataHandler {
             ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
       }
       break;
+    case action:
+      if (request.getMethod().equals(HttpMethod.POST)) {
+        ProcedureProcessor pp = selectProcessor(ProcedureProcessor.class);
+
+        requestedContentType =
+            ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, pp, ProcedureProcessor.class);
+
+        pp.executeAction(request, response, uriInfo, requestedContentType);
+      } else {
+        throw new ODataHandlerException("not implemented",
+            ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
+      }            
+      break;
+    case function:
+      if (request.getMethod().equals(HttpMethod.GET)) {
+        ProcedureProcessor pp = selectProcessor(ProcedureProcessor.class);
+
+        requestedContentType =
+            ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, pp, ProcedureProcessor.class);
+
+        pp.executeFunction(request, response, uriInfo, requestedContentType);
+      } else {
+        throw new ODataHandlerException("not implemented",
+            ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
+      }      
+      break;
     default:
       throw new ODataHandlerException("not implemented",
           ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/ODataXmlSerializerImpl.java
----------------------------------------------------------------------
diff --git 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
index 8956a6d..e991d96 100644
--- 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
@@ -30,6 +30,7 @@ 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.commons.api.edm.EdmReturnType;
 import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
@@ -116,4 +117,12 @@ public class ODataXmlSerializerImpl implements ODataSerializer {
     throw new SerializerException("error serialization not implemented for XML format",
       SerializerException.MessageKeys.NOT_IMPLEMENTED);
 	}
+
+  @Override
+  public InputStream procedureReturn(EdmReturnType returnType,
+      Property property, ODataSerializerOptions options)
+      throws SerializerException {
+    // rameshTODO Auto-generated method stub
+    return null;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
----------------------------------------------------------------------
diff --git 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
index 324c5aa..3cae645 100644
--- 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
@@ -39,13 +39,15 @@ 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.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
 import org.apache.olingo.server.api.ODataServerError;
 import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.BoundProcedureOption;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
-import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
 import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
 import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
 import org.apache.olingo.server.api.uri.queryoption.SelectOption;
@@ -141,6 +143,11 @@ public class ODataJsonSerializer implements ODataSerializer {
             ContextURLBuilder.create(contextURL).toASCIIString());
       }
 
+      if (options != null) {
+        // write title, target in case of bound function/action
+        writeProcedureMetadata(options.getBoundProcedure(), json);
+      }
+
       if (options != null && options.getCount() != null && options.getCount().getValue()
           && entitySet.getCount() != null) {
         json.writeNumberField(Constants.JSON_COUNT, entitySet.getCount());
@@ -167,7 +174,8 @@ public class ODataJsonSerializer implements ODataSerializer {
     try {
       JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
       writeEntity(edmEntitySet.getEntityType(), entity, contextURL,
-          options == null ? null : options.getExpand(), options == null ? null : options.getSelect(), json);
+          options == null ? null : options.getExpand(), options == null ? null : options.getSelect(), 
+          options == null ? null : options.getBoundProcedure(), json);
       json.close();
     } catch (final IOException e) {
       throw new SerializerException("An I/O exception occurred.", e,
@@ -194,13 +202,13 @@ public class ODataJsonSerializer implements ODataSerializer {
       throws IOException, SerializerException {
     json.writeStartArray();
     for (final Entity entity : entitySet.getEntities()) {
-      writeEntity(entityType, entity, null, expand, select, json);
+      writeEntity(entityType, entity, null, expand, select, null, json);
     }
     json.writeEndArray();
   }
 
   protected void writeEntity(final EdmEntityType entityType, final Entity entity, final ContextURL contextURL,
-      final ExpandOption expand, final SelectOption select, final JsonGenerator json)
+      final ExpandOption expand, final SelectOption select, BoundProcedureOption boundOption, final JsonGenerator json)
       throws IOException, SerializerException {
     json.writeStartObject();
     if (format != ODataFormat.JSON_NO_METADATA) {
@@ -219,6 +227,9 @@ public class ODataJsonSerializer implements ODataSerializer {
         }
       }
     }
+    // write title, target in case of bound function/action
+    writeProcedureMetadata(boundOption, json);
+    
     writeProperties(entityType, entity, select, json);
     writeNavigationProperties(entityType, entity, expand, json);
     json.writeEndObject();
@@ -280,7 +291,7 @@ public class ODataJsonSerializer implements ODataSerializer {
       if (navigationLink == null || navigationLink.getInlineEntity() == null) {
         json.writeNull();
       } else {
-        writeEntity(property.getType(), navigationLink.getInlineEntity(), null, innerExpand, innerSelect, json);
+        writeEntity(property.getType(), navigationLink.getInlineEntity(), null, innerExpand, innerSelect, null, json);
       }
     }
   }
@@ -309,9 +320,10 @@ public class ODataJsonSerializer implements ODataSerializer {
       } else if (edmProperty.isPrimitive()) {
         writePrimitive(edmProperty, property, json);
       } else if (property.isLinkedComplex()) {
-        writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), selectedPaths, json);
+        writeComplexValue((EdmComplexType) edmProperty.getType(), 
+            property.asLinkedComplex().getValue(), selectedPaths, json);
       } else if (property.isComplex()) {
-        writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
+        writeComplexValue((EdmComplexType)edmProperty.getType(), property.asComplex(), selectedPaths, json);
       } else {
         throw new SerializerException("Property type not yet supported!",
             SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, edmProperty.getName());
@@ -339,10 +351,11 @@ public class ODataJsonSerializer implements ODataSerializer {
         json.writeString(value.toString());
         break;
       case COLLECTION_LINKED_COMPLEX:
-        writeComplexValue(edmProperty, ((LinkedComplexValue) value).getValue(), selectedPaths, json);
+        writeComplexValue((EdmComplexType)edmProperty.getType(), 
+            ((LinkedComplexValue) value).getValue(), selectedPaths, json);
         break;
       case COLLECTION_COMPLEX:
-        writeComplexValue(edmProperty, property.asComplex(), selectedPaths, json);
+        writeComplexValue((EdmComplexType)edmProperty.getType(), property.asComplex(), selectedPaths, json);
         break;
       default:
         throw new SerializerException("Property type not yet supported!",
@@ -351,6 +364,38 @@ public class ODataJsonSerializer implements ODataSerializer {
     }
     json.writeEndArray();
   }
+  
+  private void writeCollection(final EdmReturnType edmProperty, final Property property,
+      final Set<List<String>> selectedPaths, JsonGenerator json)
+      throws IOException, EdmPrimitiveTypeException, SerializerException {
+    json.writeStartArray();
+    for (Object value : property.asCollection()) {
+      switch (property.getValueType()) {
+      case COLLECTION_PRIMITIVE:
+        writePrimitiveValue(edmProperty, value, json);
+        break;
+      case COLLECTION_GEOSPATIAL:
+        throw new SerializerException("Property type not yet supported!",
+            SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, 
+            edmProperty.getType().getFullQualifiedName().toString());
+      case COLLECTION_ENUM:
+        json.writeString(value.toString());
+        break;
+      case COLLECTION_LINKED_COMPLEX:
+        writeComplexValue((EdmComplexType)edmProperty.getType(), 
+            ((LinkedComplexValue) value).getValue(), selectedPaths, json);
+        break;
+      case COLLECTION_COMPLEX:
+        writeComplexValue((EdmComplexType)edmProperty.getType(), property.asComplex(), selectedPaths, json);
+        break;
+      default:
+        throw new SerializerException("Property type not yet supported!",
+            SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, 
+            edmProperty.getType().getFullQualifiedName().toString());
+      }
+    }
+    json.writeEndArray();
+  }  
 
   private void writePrimitive(EdmProperty edmProperty, Property property, JsonGenerator json)
       throws EdmPrimitiveTypeException, IOException, SerializerException {
@@ -366,6 +411,23 @@ public class ODataJsonSerializer implements ODataSerializer {
           SerializerException.MessageKeys.INCONSISTENT_PROPERTY_TYPE, edmProperty.getName());
     }
   }
+  
+  private void writePrimitive(EdmReturnType edmReturnType, Property property, JsonGenerator json)
+      throws EdmPrimitiveTypeException, IOException, SerializerException {
+    if (property.isPrimitive()) {
+      writePrimitiveValue(edmReturnType, property.asPrimitive(), json);
+    } else if (property.isGeospatial()) {
+      throw new SerializerException("Property type not yet supported!",
+          SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, 
+          edmReturnType.getType().getFullQualifiedName().toString());
+    } else if (property.isEnum()) {
+      writePrimitiveValue(edmReturnType, property.asEnum(), json);
+    } else {
+      throw new SerializerException("Inconsistent property type!",
+          SerializerException.MessageKeys.INCONSISTENT_PROPERTY_TYPE, 
+          edmReturnType.getType().getFullQualifiedName().toString());
+    }
+  }  
 
   protected void writePrimitiveValue(final EdmProperty edmProperty, final Object primitiveValue,
       final JsonGenerator json) throws EdmPrimitiveTypeException, IOException {
@@ -388,19 +450,40 @@ public class ODataJsonSerializer implements ODataSerializer {
       json.writeString(value);
     }
   }
+  
+  protected void writePrimitiveValue(final EdmReturnType edmReturnType, final Object primitiveValue,
+      final JsonGenerator json) throws EdmPrimitiveTypeException, IOException {
+    final EdmPrimitiveType type = (EdmPrimitiveType) edmReturnType.getType();
+    final String value = type.valueToString(primitiveValue,
+        edmReturnType.isNullable(), edmReturnType.getMaxLength(),
+        edmReturnType.getPrecision(), edmReturnType.getScale(), true);
+    if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)) {
+      json.writeBoolean(Boolean.parseBoolean(value));
+    } else if (type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Byte)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Double)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int16)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int32)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Int64)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.SByte)
+        || type == EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Single)) {
+      json.writeNumber(value);
+    } else {
+      json.writeString(value);
+    }
+  }  
 
-  protected void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
+  protected void writeComplexValue(final EdmComplexType type, final List<Property> properties,
       final Set<List<String>> selectedPaths, JsonGenerator json)
-      throws IOException, EdmPrimitiveTypeException, SerializerException {
+      throws IOException, SerializerException {
     json.writeStartObject();
-    writePropertyValues(edmProperty, properties, selectedPaths, json);
+    writeComplexPropertyValues(type, properties, selectedPaths, json);
     json.writeEndObject();
   }
 
-  private void writePropertyValues(final EdmProperty edmProperty,
+  private void writeComplexPropertyValues(final EdmComplexType type,
                                    final List<Property> properties, final Set<List<String>> selectedPaths,
-                                   JsonGenerator json) throws IOException, SerializerException {
-    final EdmComplexType type = (EdmComplexType) edmProperty.getType();
+                                   JsonGenerator json) throws IOException, SerializerException {    
     for (final String propertyName : type.getPropertyNames()) {
       final Property property = findProperty(propertyName, properties);
       if (selectedPaths == null || ExpandSelectHelper.isSelected(selectedPaths, propertyName)) {
@@ -444,9 +527,10 @@ public class ODataJsonSerializer implements ODataSerializer {
         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);
+        writeComplexPropertyValues((EdmComplexType)edmProperty.getType(), property.asComplex(), null, json);
       } else if (property.isLinkedComplex() && !property.isNull()) {
-        writePropertyValues(edmProperty, property.asLinkedComplex().getValue(), null, json);
+        writeComplexPropertyValues((EdmComplexType)edmProperty.getType(), 
+            property.asLinkedComplex().getValue(), null, json);
       } else {
         json.writeFieldName(Constants.VALUE);
         writePropertyValue(edmProperty, property, null, json);
@@ -459,4 +543,83 @@ public class ODataJsonSerializer implements ODataSerializer {
     }
     return buffer.getInputStream();
   }
+
+  @Override
+  public InputStream procedureReturn(EdmReturnType returnType, Property property,
+      ODataSerializerOptions options) throws SerializerException {
+    final ContextURL contextURL = checkContextURL(options);
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+    try {
+      JsonGenerator json = new JsonFactory().createGenerator(buffer.getOutputStream());
+      json.writeStartObject();
+      
+      if (this.format != ODataFormat.JSON_NO_METADATA) {
+        if (contextURL != null) {
+          json.writeStringField(Constants.JSON_CONTEXT, ContextURLBuilder.create(contextURL).toASCIIString());
+        }
+      }
+      // write title, target in case of bound function/action
+      if (options != null) {
+        writeProcedureMetadata(options.getBoundProcedure(), json);
+      }
+
+      if (returnType.isCollection()) {
+        switch (returnType.getType().getKind()) {
+        case PRIMITIVE:
+        case COMPLEX:
+          json.writeFieldName(Constants.VALUE);
+          writeCollection(returnType, property, null, json);
+          break;
+        default:
+          throw new SerializerException("Property type not yet supported!",
+              SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, 
+              returnType.getType().getFullQualifiedName().toString());          
+        }
+      } else {
+        switch (returnType.getType().getKind()) {
+        case PRIMITIVE:
+          json.writeFieldName(Constants.VALUE);
+          writePrimitiveValue(returnType, property.getValue(), json);
+          break;
+        case COMPLEX:
+          if (property.isComplex()) {
+            writeComplexPropertyValues((EdmComplexType)returnType.getType(), property.asComplex(), null, json);
+          } else if (property.isLinkedComplex()) {
+            writeComplexPropertyValues((EdmComplexType)returnType.getType(), 
+                property.asLinkedComplex().getValue(), null, json);
+          }
+          break;
+        default:
+          throw new SerializerException("Property type not yet supported!",
+              SerializerException.MessageKeys.UNSUPPORTED_PROPERTY_TYPE, 
+              returnType.getType().getFullQualifiedName().toString());          
+        }        
+      }
+      json.writeEndObject();
+      json.close();
+    } catch (final IOException e) {
+      throw new SerializerException("An I/O exception occurred.", e,
+          SerializerException.MessageKeys.IO_EXCEPTION);
+    } catch (EdmPrimitiveTypeException e) {
+      throw new SerializerException("An I/O exception occurred.", e,
+          SerializerException.MessageKeys.IO_EXCEPTION);
+    }
+    return buffer.getInputStream();
+  }
+
+  private void writeProcedureMetadata(BoundProcedureOption bpOption, JsonGenerator json) throws IOException {
+    if (bpOption != null) {
+      if (this.format == ODataFormat.JSON) {
+        json.writeFieldName("#"+bpOption.getProcedureName());
+        json.writeStartObject();
+        json.writeEndObject();
+      } else if (this.format == ODataFormat.JSON_FULL_METADATA) {
+        json.writeFieldName("#"+bpOption.getProcedureName());
+        json.writeStartObject();
+        json.writeStringField("title", bpOption.getTitle());
+        json.writeStringField("target", bpOption.getTarget());
+        json.writeEndObject();
+      }
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
index 9f81ef3..e73682f 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentXmlSerializer.java
@@ -83,6 +83,7 @@ public class MetadataDocumentXmlSerializer {
   private static final String XML_PARAMETER = "Parameter";
   private static final String XML_IS_COMPOSABLE = "IsComposable";
   private static final String XML_IS_BOUND = "IsBound";
+  private static final String XML_ENTITY_SET_PATH = "EntitySetPath";
   private static final String XML_ENTITY_TYPE = "EntityType";
   private static final String XML_SINGLETON = "Singleton";
   private static final String XML_ACTION = "Action";
@@ -293,7 +294,9 @@ public class MetadataDocumentXmlSerializer {
     for (EdmFunction function : functions) {
       writer.writeStartElement(XML_FUNCTION);
       writer.writeAttribute(XML_NAME, function.getName());
-      // TODO: EntitySetPath
+      if (function.getEntitySetPath() != null) {
+        writer.writeAttribute(XML_ENTITY_SET_PATH, function.getEntitySetPath());
+      }
       writer.writeAttribute(XML_IS_BOUND, "" + function.isBound());
       writer.writeAttribute(XML_IS_COMPOSABLE, "" + function.isComposable());
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
index 4ca162c..535413e 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/UriResourceActionImpl.java
@@ -18,9 +18,13 @@
  */
 package org.apache.olingo.server.core.uri;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmActionImport;
 import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResourceAction;
 import org.apache.olingo.server.api.uri.UriResourceKind;
 
@@ -28,6 +32,7 @@ public class UriResourceActionImpl extends UriResourceTypedImpl implements UriRe
 
   protected EdmAction action;
   protected EdmActionImport actionImport;
+  protected List<UriParameterImpl> parameters;
 
   public UriResourceActionImpl() {
     super(UriResourceKind.action);
@@ -48,9 +53,11 @@ public class UriResourceActionImpl extends UriResourceTypedImpl implements UriRe
     return actionImport;
   }
 
-  public UriResourceActionImpl setActionImport(final EdmActionImport actionImport) {
+  public UriResourceActionImpl setActionImport(final EdmActionImport actionImport, 
+      final List<UriParameterImpl> parameters) {
     this.actionImport = actionImport;
     setAction(actionImport.getUnboundAction());
+    setParameters(parameters);
     return this;
   }
 
@@ -63,6 +70,20 @@ public class UriResourceActionImpl extends UriResourceTypedImpl implements UriRe
   public EdmType getType() {
     return action.getReturnType().getType();
   }
+  
+  @Override
+  public List<UriParameter> getParameters() {
+    List<UriParameter> retList = new ArrayList<UriParameter>();
+    for (UriParameterImpl item : parameters) {
+      retList.add(item);
+    }
+    return retList;
+  }
+  
+  public UriResourceActionImpl setParameters(final List<UriParameterImpl> parameters) {
+    this.parameters = parameters;
+    return this;
+  }  
 
   @Override
   public String toString() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
index 63d8fb9..4ab3262 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParseTreeVisitor.java
@@ -18,6 +18,10 @@
  */
 package org.apache.olingo.server.core.uri.parser;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.misc.ParseCancellationException;
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -181,9 +185,6 @@ import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl;
 import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl;
 import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * UriVisitor
  * 
@@ -312,10 +313,24 @@ public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> {
       // check ActionImport
       EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi);
       if (edmActionImport != null) {
-        UriResourceActionImpl uriResource = new UriResourceActionImpl()
-            .setActionImport(edmActionImport);
+        
+        // read the URI parameters, since unbound actions can not be overloaded
+        // there can be atmost one with given name
+        List<UriParameterImpl> parameters = Collections.EMPTY_LIST;
+        if (!ctx.vlNVO.isEmpty()) {
+          context.contextReadingFunctionParameters = true;
+          parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this);
+          context.contextReadingFunctionParameters = false;
+          
+          // mark parameters as consumed
+          ctx.vlNVO.remove(0);
+        }
+
+        UriResourceActionImpl uriResource = new UriResourceActionImpl().setActionImport(edmActionImport, parameters);
+
+        uriResource.setAction(edmActionImport.getUnboundAction());
         context.contextUriInfo.addResourcePart(uriResource);
-        return null;
+        return null;        
       }
 
       // check FunctionImport

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/pom.xml
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/pom.xml b/lib/server-tecsvc/pom.xml
index bcf29ec..bfe3298 100644
--- a/lib/server-tecsvc/pom.xml
+++ b/lib/server-tecsvc/pom.xml
@@ -121,7 +121,6 @@
       <groupId>org.apache.olingo</groupId>
       <artifactId>odata-server-core</artifactId>
       <version>${project.version}</version>
-      <scope>runtime</scope>
     </dependency>
 
     <dependency>

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/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 6010e95..8c6136a 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
@@ -35,8 +35,10 @@ import org.apache.olingo.commons.api.data.Link;
 import org.apache.olingo.commons.api.data.LinkedComplexValue;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
+import org.apache.olingo.commons.api.edm.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
 import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmProperty;
@@ -48,6 +50,10 @@ import org.apache.olingo.commons.core.data.LinkedComplexValueImpl;
 import org.apache.olingo.commons.core.data.PropertyImpl;
 import org.apache.olingo.server.api.ODataApplicationException;
 import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.UriResourceAction;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
+import org.apache.olingo.server.tecsvc.provider.ActionProvider;
+import org.apache.olingo.server.tecsvc.provider.FunctionProvider;
 
 public class DataProvider {
 
@@ -543,4 +549,105 @@ public class DataProvider {
     link.setInlineEntitySet(target);
     entity.getNavigationLinks().add(link);
   }
+  
+  public Object invokeFunction(UriResourceFunction uriFunction) {
+    final EdmFunction function = uriFunction.getFunction(); 
+    final List<UriParameter> keys = uriFunction.getParameters();
+    
+    if (function.isBound()) {
+      if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTString)) {
+        // bound - return primitive
+        return createPrimitive("any", "TEST-A");
+      } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTCollString)) {
+        // bound - return Collection(primitive)
+        return createCollection("any", "dummy1", "dummy2");
+      } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTETTwoPrim)) {
+        // bound- entity
+        return data.get("ESTwoPrim").getEntities().get(0);
+      } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFESTwoPrimRTString)) {
+        // bound- Collection(entity)
+        List<Entity> rows =  data.get("ESTwoPrim").getEntities();
+      } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFCETTwoKeyNavRTCTTwoPrim)) {
+        // bound- complex
+        LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+        complexValue.getValue().add(createPrimitive("PropertyInt16", 5));
+        complexValue.getValue().add(createPrimitive("PropertyString", "TEST-A"));
+        return new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue);
+      } else if (function.getFullQualifiedName().equals(FunctionProvider.nameBFCESTwoKeyNavRTCollCTTwoPrim)) {
+        // bound- Collection(complex)
+        List<LinkedComplexValue> complexCollection = new ArrayList<LinkedComplexValue>();
+        LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+        complexValue.getValue().add(createPrimitive("PropertyInt16", 5));
+        complexValue.getValue().add(createPrimitive("PropertyString", "TEST-A"));      
+        complexCollection.add(complexValue);
+        complexCollection.add(complexValue);
+        return new PropertyImpl(null, "PropertyComp", ValueType.COLLECTION_LINKED_COMPLEX, complexCollection);
+      }
+    }
+    
+    if (function.getFullQualifiedName().equals(FunctionProvider.nameUFNRTInt16)) {
+      // unbound - return primitive
+      return createPrimitive("any", new Short((short)5));
+    } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTCollString)) {
+      // unbound - return Collection(primitive)
+      return createCollection("any", "dummy1", "dummy2");
+    } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTETAllPrimTwoParam)) {
+      // unbound- entity
+      String parameterString = getParameter("ParameterString", keys).getText();
+      short parameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+      return data.get("ESAllPrim").getEntities().get(0);
+    } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTESMixPrimCollCompTwoParam)) {
+      // unbound- Collection(entity)
+      String parameterString = getParameter("ParameterString", keys).getText();
+      short ParameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+      return data.get("ESMixPrimCollComp");
+    } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTCTTwoPrimParam)) {
+      // unbound- complex
+      String parameterString = unquote(getParameter("ParameterString", keys).getText());
+      short parameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+      LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+      complexValue.getValue().add(createPrimitive("PropertyInt16", parameterInt16));
+      complexValue.getValue().add(createPrimitive("PropertyString", parameterString));
+      return new PropertyImpl(null, "PropertyComp", ValueType.LINKED_COMPLEX, complexValue);
+    } else if (function.getFullQualifiedName().equals(FunctionProvider.nameUFCRTCollCTTwoPrimParam)) {
+      // unbound- Collection(complex)
+      String parameterString = unquote(getParameter("ParameterString", keys).getText());
+      short parameterInt16 = Short.valueOf(getParameter("ParameterInt16", keys).getText());
+      List<LinkedComplexValue> complexCollection = new ArrayList<LinkedComplexValue>();
+      LinkedComplexValue complexValue = new LinkedComplexValueImpl();
+      complexValue.getValue().add(createPrimitive("PropertyInt16", parameterInt16));
+      complexValue.getValue().add(createPrimitive("PropertyString", parameterString));      
+      complexCollection.add(complexValue);
+      complexCollection.add(complexValue);
+      return new PropertyImpl(null, "PropertyComp", ValueType.COLLECTION_LINKED_COMPLEX, complexCollection);
+    }
+    return null;
+  }
+  
+  public Object invokeAction(UriResourceAction uriAction) {
+    final EdmAction action = uriAction.getAction(); 
+    final List<UriParameter> keys = uriAction.getParameters();
+    
+    if (action.getFullQualifiedName().equals(ActionProvider.nameUARTPrimParam)) {
+      // unbound - return primitive
+      return createPrimitive("any", "return-string");
+    }    
+    return null;
+  }  
+  
+  private UriParameter getParameter(String name, List<UriParameter> keys) {
+    for (UriParameter key:keys) {
+      if (key.getName().equals(name)) {
+        return key;
+      }
+    }
+    return null;
+  }
+  
+  private static String unquote(String str) {
+    if (str.startsWith("'") && str.endsWith("'")) {
+      return str.substring(1, str.length()-1);
+    }
+    return str;
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --git 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
index ca87c6b..9ff5f47 100644
--- 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
@@ -24,16 +24,22 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.TreeMap;
 
 import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.ContextURL.Suffix;
 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.EdmAction;
 import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmFunction;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
 import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
 import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.commons.api.http.HttpContentType;
@@ -46,7 +52,9 @@ import org.apache.olingo.server.api.ODataResponse;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.processor.EntityProcessor;
 import org.apache.olingo.server.api.processor.EntitySetProcessor;
+import org.apache.olingo.server.api.processor.ProcedureProcessor;
 import org.apache.olingo.server.api.processor.PropertyProcessor;
+import org.apache.olingo.server.api.serializer.BoundProcedureOption;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
 import org.apache.olingo.server.api.serializer.ODataSerializerOptions;
 import org.apache.olingo.server.api.serializer.SerializerException;
@@ -54,7 +62,9 @@ import org.apache.olingo.server.api.uri.UriInfo;
 import org.apache.olingo.server.api.uri.UriInfoResource;
 import org.apache.olingo.server.api.uri.UriParameter;
 import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourceAction;
 import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
 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;
@@ -64,18 +74,20 @@ import org.apache.olingo.server.tecsvc.data.DataProvider;
 /**
  * Technical Processor which provides currently implemented processor functionality.
  */
-public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor {
+public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor, PropertyProcessor, ProcedureProcessor {
 
   private OData odata;
   private DataProvider dataProvider;
+  private ServiceMetadata edm;
 
   public TechnicalProcessor(final DataProvider dataProvider) {
-    this.dataProvider = dataProvider;
+    this.dataProvider = dataProvider;    
   }
 
   @Override
   public void init(final OData odata, final ServiceMetadata edm) {
     this.odata = odata;
+    this.edm = edm;
   }
 
   @Override
@@ -297,4 +309,162 @@ public class TechnicalProcessor implements EntitySetProcessor, EntityProcessor,
       }
     }
   }
+
+  @Override
+  public void executeFunction(ODataRequest request, ODataResponse response,
+      UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException {
+    final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+    Object result = null;
+
+    UriResourceFunction functionURI = null;
+    for (UriResource uriResource:resourcePaths) {
+      if (uriResource instanceof UriResourceFunction) {
+        functionURI = (UriResourceFunction)uriResource;
+        break;
+      }
+    }
+    
+    if (functionURI == null) {
+      throw new ODataApplicationException("Function not found",
+          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+    }
+    
+    ODataSerializerOptions.Builder options = ODataSerializerOptions.with();
+    if (functionURI.getFunction().isBound()) {
+      options.boundProcedure(BoundProcedureOption.with()
+          .setFunction(functionURI.getFunction())
+          .setTarget(request.getRawODataPath())
+          .setTitle(functionURI.getFunction().getName()).build());
+    }
+
+    EdmFunction edmFunction = functionURI.getFunction();
+    result = dataProvider.invokeFunction(functionURI);
+    if (result == null) {
+      response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+    } else {
+        final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
+        ODataSerializer serializer = odata.createSerializer(format);      
+        EdmReturnType returnType = edmFunction.getReturnType();
+        switch(returnType.getType().getKind()) {
+        case PRIMITIVE:          
+        case COMPLEX:
+          ContextURL.Builder contextURL = ContextURL.with().propertyType(returnType.getType());
+          if (returnType.isCollection()) {
+            contextURL.asCollection();
+          }
+          response.setContent(serializer.procedureReturn(returnType, (Property)result,
+              options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
+                contextURL.build()).build()));
+          response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+          response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());          
+          break;
+        case ENTITY:
+          EdmEntitySet edmEntitySet = null;
+          if (edmFunction.isBound()) {
+            //TODO: this needs to be fixed to return correct entitySet
+            edmEntitySet = edmFunction.getReturnedEntitySet(null);
+          } else {
+            edmEntitySet = functionURI.getFunctionImport().getReturnedEntitySet();
+          }
+          if (edmEntitySet == null) {
+            throw new ODataApplicationException("EntitySet type not defined on function",
+                HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+          }          
+          if (returnType.isCollection()) {
+            response.setContent(serializer.entitySet(edmEntitySet, (EntitySet)result,                 
+                options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null: 
+                    getContextUrl(serializer, edmEntitySet, false, null, null, null)).build()));           
+          } else {
+            response.setContent(serializer.entity(edmEntitySet, (Entity) result,
+                options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null: 
+                      getContextUrl(serializer, edmEntitySet, true, null, null, null)).build()));           
+          }
+          response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+          response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+          break;
+        default:
+          throw new ODataApplicationException("Return type not supported",
+              HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+        }    
+    }       
+  }
+
+  @Override
+  public void executeAction(ODataRequest request, ODataResponse response,
+      UriInfo uriInfo, ContentType requestedContentType) throws ODataApplicationException, SerializerException {
+    final List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+    Object result = null;
+
+    UriResourceAction actionURI = null;
+    for (UriResource uriResource:resourcePaths) {
+      if (uriResource instanceof UriResourceAction) {
+        actionURI = (UriResourceAction)uriResource;
+        break;
+      }
+    }
+    
+    if (actionURI == null) {
+      throw new ODataApplicationException("Action not found",
+          HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+    }
+    
+    ODataSerializerOptions.Builder options = ODataSerializerOptions.with();
+    if (actionURI.getAction().isBound()) {
+      options.boundProcedure(BoundProcedureOption.with()
+          .setAction(actionURI.getAction())
+          .setTarget(request.getRawODataPath())
+          .setTitle(actionURI.getAction().getName()).build());
+    }
+
+    EdmAction edmAction = actionURI.getAction();
+    result = dataProvider.invokeAction(actionURI);
+    if (result == null) {
+      response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+    } else {
+        final ODataFormat format = ODataFormat.fromContentType(requestedContentType);
+        ODataSerializer serializer = odata.createSerializer(format);      
+        EdmReturnType returnType = edmAction.getReturnType();
+        switch(returnType.getType().getKind()) {
+        case PRIMITIVE:          
+        case COMPLEX:
+          ContextURL.Builder contextURL = ContextURL.with().propertyType(returnType.getType());
+          if (returnType.isCollection()) {
+            contextURL.asCollection();
+          }
+          response.setContent(serializer.procedureReturn(returnType, (Property)result,
+              options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null :
+                contextURL.build()).build()));
+          response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+          response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());          
+          break;
+        case ENTITY:
+          EdmEntitySet edmEntitySet = null;
+          if (edmAction.isBound()) {
+            //TODO: this needs to be fixed to return correct entitySet
+            edmEntitySet = edmAction.getReturnedEntitySet(null);
+          } else {
+            edmEntitySet = actionURI.getActionImport().getReturnedEntitySet();
+          }
+          if (edmEntitySet == null) {
+            throw new ODataApplicationException("EntitySet type not defined on function",
+                HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+          }          
+          if (returnType.isCollection()) {
+            response.setContent(serializer.entitySet(edmEntitySet, (EntitySet)result,                 
+                options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null: 
+                    getContextUrl(serializer, edmEntitySet, false, null, null, null)).build()));           
+          } else {
+            response.setContent(serializer.entity(edmEntitySet, (Entity) result,
+                options.contextURL(format == ODataFormat.JSON_NO_METADATA ? null: 
+                      getContextUrl(serializer, edmEntitySet, true, null, null, null)).build()));           
+          }
+          response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+          response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString());
+          break;
+        default:
+          throw new ODataApplicationException("Return type not supported",
+              HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT);
+        }    
+    }       
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
index 813bb87..2386d9d 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java
@@ -349,6 +349,8 @@ public class ContainerProvider {
         return new FunctionImport()
             .setName("FICRTESMixPrimCollCompTwoParam")
             .setFunction(FunctionProvider.nameUFCRTESMixPrimCollCompTwoParam)
+            .setEntitySet(new Target.Builder(entityContainer.getFullQualifiedNameAsString()
+                +"/ESMixPrimCollComp", null).build())
             .setIncludeInServiceDocument(true);
 
       } else if (name.equals("FINRTESMixPrimCollCompTwoParam")) {
@@ -405,6 +407,12 @@ public class ContainerProvider {
             .setFunction(FunctionProvider.nameUFCRTCollCTTwoPrimParam)
             .setIncludeInServiceDocument(true);
 
+      } else if (name.equals("FICRTETAllPrimTwoParam")) {
+        return new FunctionImport()
+        .setName("FICRTETAllPrimTwoParam")
+        .setFunction(FunctionProvider.nameUFCRTETAllPrimTwoParam)
+        .setEntitySet(new Target.Builder(entityContainer.getFullQualifiedNameAsString()+"/ESAllPrim", null).build())
+        .setIncludeInServiceDocument(true);
       }
     }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
index c4ee503..7153f4f 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/FunctionProvider.java
@@ -20,6 +20,7 @@ package org.apache.olingo.server.tecsvc.provider;
 
 import org.apache.olingo.commons.api.ODataException;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.server.api.edm.provider.EntitySetPath;
 import org.apache.olingo.server.api.edm.provider.Function;
 import org.apache.olingo.server.api.edm.provider.Parameter;
 import org.apache.olingo.server.api.edm.provider.ReturnType;
@@ -111,6 +112,17 @@ public class FunctionProvider {
 
   public static final FullQualifiedName nameBFESTwoKeyNavRTESTwoKeyNav =
       new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoKeyNavRTESTwoKeyNav");
+  
+  public static final FullQualifiedName nameBFESTwoPrimRTString =
+      new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoPrimRTString");
+
+  public static final FullQualifiedName nameBFESTwoPrimRTCollString =
+      new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoPrimRTCollString");
+  
+  public static final FullQualifiedName nameBFESTwoPrimRTETTwoPrim =
+      new FullQualifiedName(SchemaProvider.NAMESPACE, "BFESTwoPrimRTETTwoPrim");
+  
+  
 
   // Unbound Functions
   public static final FullQualifiedName nameUFCRTCollCTTwoPrim =
@@ -839,13 +851,61 @@ public class FunctionProvider {
                       new Parameter().setName("BindingParam").setType(ComplexTypeProvider.nameCTPrimComp).setNullable(
                           false),
                       new Parameter().setName("ParameterString").setType(PropertyProvider.nameString)
-                          .setNullable(false)))
+                          .setNullable(false)))              
               .setComposable(true)
               .setReturnType(
                   new ReturnType().setType(EntityTypeProvider.nameETTwoKeyNav).setCollection(true).setNullable(false))
           );
+    } else if (functionName.equals(nameBFESTwoPrimRTString)) {
+      return Arrays.asList(
+          new Function()
+              .setName("BFESTwoPrimRTString")
+              .setBound(true)
+              .setParameters(
+                  Arrays.asList(
+                      new Parameter().setName("BindingParam").setType(EntityTypeProvider.nameETTwoPrim).setNullable(
+                          false).setCollection(true)))
+              .setEntitySetPath(new EntitySetPath().
+                  setBindingParameter("BindingParam").setPath("ESTwoPrim"))                          
+              .setComposable(true)
+              .setReturnType(
+                  new ReturnType().setType(PropertyProvider.nameString).setCollection(false).setNullable(false))
+          );
+    } else if (functionName.equals(nameBFESTwoPrimRTCollString)) {
+      return Arrays.asList(
+          new Function()
+              .setName("BFESTwoPrimRTCollString")
+              .setBound(true)
+              .setParameters(
+                  Arrays.asList(
+                      new Parameter().setName("BindingParam").
+                      setType(EntityTypeProvider.nameETTwoPrim).setNullable(false)))
+              .setEntitySetPath(new EntitySetPath().setBindingParameter("BindingParam")
+                  .setPath("ESTwoPrim"))                          
+              .setComposable(true)
+              .setReturnType(
+                  new ReturnType().setType(PropertyProvider.nameString).setCollection(true).setNullable(false))
+          );
+    } else if (functionName.equals(nameBFESTwoPrimRTETTwoPrim)) {
+      return Arrays.asList(
+          new Function()
+              .setName("BFESTwoPrimRTETTwoPrim")
+              .setBound(true)
+              .setParameters(
+                  Arrays.asList(
+                      new Parameter().setName("BindingParam")
+                      .setType(EntityTypeProvider.nameETTwoPrim).setNullable(false).setCollection(true),
+                      new Parameter().setName("ParameterString")
+                      .setType(PropertyProvider.nameString).setNullable(false)))
+              .setEntitySetPath(new EntitySetPath().setBindingParameter("BindingParam")
+                  .setPath("ESTwoPrim"))                          
+              .setComposable(true)
+              .setReturnType(
+                  new ReturnType().setType(EntityTypeProvider.nameETTwoPrim)
+                  .setCollection(false).setNullable(false))
+          );
     }
-
+    
     return null;
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
index a0a282e..fe22fa1 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java
@@ -165,6 +165,10 @@ public class SchemaProvider {
     functions.addAll(prov.getFunctions(FunctionProvider.nameBFCESTwoKeyNavRTStringParam));
     functions.addAll(prov.getFunctions(FunctionProvider.nameBFCESKeyNavRTETKeyNavParam));
     functions.addAll(prov.getFunctions(FunctionProvider.nameBFCCTPrimCompRTETTwoKeyNavParam));
+    functions.addAll(prov.getFunctions(FunctionProvider.nameBFESTwoPrimRTString));
+    functions.addAll(prov.getFunctions(FunctionProvider.nameBFESTwoPrimRTCollString));
+    functions.addAll(prov.getFunctions(FunctionProvider.nameBFESTwoPrimRTETTwoPrim));
+    
     // functions.addAll(prov.getFunctions(FunctionProvider.nameBFCCTPrimCompRTESTwoKeyNavParam));
 
     // EntityContainer

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9c621763/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
index d99c9ae..ea5cdd7 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java
@@ -40,9 +40,11 @@ import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.api.processor.EntitySetProcessor;
 import org.apache.olingo.server.api.processor.MetadataProcessor;
+import org.apache.olingo.server.api.processor.ProcedureProcessor;
 import org.apache.olingo.server.api.processor.PropertyProcessor;
 import org.apache.olingo.server.api.processor.ServiceDocumentProcessor;
 import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.tecsvc.provider.ActionProvider;
 import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
 import org.junit.Before;
 import org.junit.Test;
@@ -341,4 +343,61 @@ public class ODataHandlerTest {
             Mockito.any(UriInfo.class),
             Mockito.any(ContentType.class));
   }
-}
\ No newline at end of file
+  
+  @Test
+  public void testInvokeActionImport() throws Exception {
+    ODataRequest request = new ODataRequest();
+
+    request.setMethod(HttpMethod.POST);
+    request.setRawODataPath("AIRTPrimParam(ParameterInt16=1)");
+
+    ProcedureProcessor processor = mock(ProcedureProcessor.class);
+    handler.register(processor);
+
+    ODataResponse response = handler.process(request);
+
+    Mockito.verify(processor).executeAction(
+            Mockito.any(ODataRequest.class), 
+            Mockito.any(ODataResponse.class), 
+            Mockito.any(UriInfo.class),
+            Mockito.any(ContentType.class));
+  }
+  
+  public void testInvokeFunctionImport() throws Exception {
+    ODataRequest request = new ODataRequest();
+
+    request.setMethod(HttpMethod.GET);
+    request.setRawODataPath("FICRTETTwoKeyNavParam(ParameterInt16=1)");
+
+    ProcedureProcessor processor = mock(ProcedureProcessor.class);
+    handler.register(processor);
+
+    ODataResponse response = handler.process(request);
+    
+    Mockito.verify(processor).executeFunction(
+        Mockito.any(ODataRequest.class), 
+        Mockito.any(ODataResponse.class), 
+        Mockito.any(UriInfo.class),
+        Mockito.any(ContentType.class));
+  }
+  
+  @Test
+  public void testInvokeBoundAction() throws Exception {
+    ODataRequest request = new ODataRequest();
+
+    request.setMethod(HttpMethod.POST);
+    request.setRawODataPath("ESAllPrim/"
+        + ActionProvider.nameBAESAllPrimRTETAllPrim.getFullQualifiedNameAsString());
+
+    ProcedureProcessor processor = mock(ProcedureProcessor.class);
+    handler.register(processor);
+
+    ODataResponse response = handler.process(request);
+    
+    Mockito.verify(processor).executeAction(
+            Mockito.any(ODataRequest.class), 
+            Mockito.any(ODataResponse.class), 
+            Mockito.any(UriInfo.class),
+            Mockito.any(ContentType.class));
+  }   
+}