You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by il...@apache.org on 2014/04/29 11:51:52 UTC

[08/11] [OLINGO-236] Refactor complete

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
new file mode 100644
index 0000000..7e2ef22
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/AbstractTestITCase.java
@@ -0,0 +1,132 @@
+/*
+ * 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.v4;
+
+import java.io.IOException;
+import java.net.URI;
+import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.response.ODataDeleteResponse;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.v4.EdmEnabledODataClient;
+import org.apache.olingo.client.api.v4.ODataClient;
+import org.apache.olingo.client.core.ODataClientFactory;
+import org.apache.olingo.fit.AbstractBaseTestITCase;
+import org.apache.olingo.commons.api.domain.ODataCollectionValue;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.domain.v4.ODataProperty;
+import org.apache.olingo.commons.api.domain.v4.ODataValue;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.apache.olingo.commons.core.domain.v4.ODataEntityImpl;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import org.junit.BeforeClass;
+
+public abstract class AbstractTestITCase extends AbstractBaseTestITCase {
+
+  protected static final ODataClient client = ODataClientFactory.getV4();
+
+  protected static EdmEnabledODataClient edmClient;
+
+  protected static String testStaticServiceRootURL;
+
+  protected static String testKeyAsSegmentServiceRootURL;
+
+  protected static String testOpenTypeServiceRootURL;
+
+  protected static String testLargeModelServiceRootURL;
+
+  protected static String testAuthServiceRootURL;
+
+  @BeforeClass
+  public static void setUpODataServiceRoot() throws IOException {
+    testStaticServiceRootURL = "http://localhost:9080/StaticService/V40/Static.svc";
+    testKeyAsSegmentServiceRootURL = "http://localhost:9080/StaticService/V40/KeyAsSegment.svc";
+    testOpenTypeServiceRootURL = "http://localhost:9080/StaticService/V40/OpenType.svc";
+    testLargeModelServiceRootURL = "http://localhost:9080/StaticService/V40/Static.svc/large";
+    testAuthServiceRootURL = "http://localhost:9080/DefaultService.svc";
+
+    edmClient = ODataClientFactory.getEdmEnabledV4(testStaticServiceRootURL);  
+  }
+
+  @Override
+  protected ODataClient getClient() {
+    return client;
+  }
+
+  protected ODataEntity read(final ODataPubFormat format, final URI editLink) {
+    final ODataEntityRequest<ODataEntity> req = getClient().getRetrieveRequestFactory().getEntityRequest(editLink);
+    req.setFormat(format);
+
+    final ODataRetrieveResponse<ODataEntity> res = req.execute();
+    final ODataEntity entity = res.getBody();
+
+    assertNotNull(entity);
+
+    if (ODataPubFormat.JSON_FULL_METADATA == format || ODataPubFormat.ATOM == format) {
+      assertEquals(req.getURI(), entity.getEditLink());
+    }
+
+    return entity;
+  }
+
+  protected void createAndDeleteOrder(final ODataPubFormat format, final int id) {
+    final ODataEntity order = new ODataEntityImpl(
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Order"));
+
+    final ODataProperty orderId = getClient().getObjectFactory().newPrimitiveProperty("OrderID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(id));
+    order.getProperties().add(orderId);
+
+    final ODataProperty orderDate = getClient().getObjectFactory().newPrimitiveProperty("OrderDate",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.DateTimeOffset).setText("2011-03-04T16:03:57Z").build());
+    order.getProperties().add(orderDate);
+
+    final ODataProperty shelfLife = getClient().getObjectFactory().newPrimitiveProperty("ShelfLife",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000001S").build());
+    order.getProperties().add(shelfLife);
+
+    final ODataCollectionValue<ODataValue> orderShelfLifesValue = getClient().getObjectFactory().
+            newCollectionValue("Collection(Duration)");
+    orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000001S").build());
+    orderShelfLifesValue.add(getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000002S").build());
+    final ODataProperty orderShelfLifes = getClient().getObjectFactory().
+            newCollectionProperty("OrderShelfLifes", orderShelfLifesValue);
+    order.getProperties().add(orderShelfLifes);
+
+    final ODataEntityCreateRequest<ODataEntity> req = getClient().getCUDRequestFactory().getEntityCreateRequest(
+            getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Orders").build(), order);
+    req.setFormat(format);
+    final ODataEntity created = req.execute().getBody();
+    assertNotNull(created);
+    assertEquals(2, created.getProperty("OrderShelfLifes").getCollectionValue().size());
+
+    final ODataDeleteRequest deleteReq = getClient().getCUDRequestFactory().getDeleteRequest(created.getEditLink());
+    final ODataDeleteResponse deleteRes = deleteReq.execute();
+    assertEquals(204, deleteRes.getStatusCode());
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v4/AsyncTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/AsyncTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/AsyncTestITCase.java
new file mode 100644
index 0000000..373a489
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/AsyncTestITCase.java
@@ -0,0 +1,166 @@
+/*
+ * 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.v4;
+
+import java.net.URI;
+import java.util.List;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.request.v4.AsyncRequestWrapper;
+import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
+import org.apache.olingo.client.api.communication.response.v4.AsyncResponseWrapper;
+import org.apache.olingo.client.api.uri.CommonURIBuilder;
+import org.apache.olingo.client.api.uri.v4.URIBuilder;
+import static org.apache.olingo.fit.v4.AbstractTestITCase.client;
+import org.apache.olingo.commons.api.domain.CommonODataEntity;
+import org.apache.olingo.commons.api.domain.CommonODataProperty;
+import org.apache.olingo.commons.api.domain.ODataInlineEntity;
+import org.apache.olingo.commons.api.domain.ODataLink;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class AsyncTestITCase extends AbstractTestITCase {
+
+  @Test
+  public void asyncRequestV3Style() throws InterruptedException, ExecutionException {
+    final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Customers");
+    final Future<ODataRetrieveResponse<ODataEntitySet>> futureRes =
+            client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build()).asyncExecute();
+    assertNotNull(futureRes);
+
+    while (!futureRes.isDone()) {
+      Thread.sleep(1000L);
+    }
+
+    final ODataRetrieveResponse<ODataEntitySet> res = futureRes.get();
+    assertNotNull(res);
+    assertEquals(200, res.getStatusCode());
+    assertFalse(res.getBody().getEntities().isEmpty());
+  }
+
+  private void withInlineEntry(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Customers").appendKeySegment(1).expand("Company");
+
+    final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final AsyncRequestWrapper<ODataRetrieveResponse<ODataEntity>> async =
+            client.getAsyncRequestFactory().<ODataRetrieveResponse<ODataEntity>>getAsyncRequestWrapper(req);
+
+    final AsyncResponseWrapper<ODataRetrieveResponse<ODataEntity>> responseWrapper = async.execute();
+
+    assertFalse(responseWrapper.isPreferenceApplied());
+
+    final ODataRetrieveResponse<ODataEntity> res = responseWrapper.getODataResponse();
+    final ODataEntity entity = res.getBody();
+
+    assertNotNull(entity);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Customer", entity.getTypeName().toString());
+    assertEquals(testStaticServiceRootURL + "/Customers(PersonID=1)", entity.getEditLink().toASCIIString());
+
+    assertEquals(3, entity.getNavigationLinks().size());
+
+    if (ODataPubFormat.ATOM == format) {
+      assertTrue(entity.getAssociationLinks().isEmpty());
+      // In JSON, association links for each $ref link will exist.
+    }
+
+    boolean found = false;
+
+    for (ODataLink link : entity.getNavigationLinks()) {
+      if (link instanceof ODataInlineEntity) {
+        final CommonODataEntity inline = ((ODataInlineEntity) link).getEntity();
+        assertNotNull(inline);
+
+        final List<? extends CommonODataProperty> properties = inline.getProperties();
+        assertEquals(5, properties.size());
+
+        assertTrue(properties.get(0).getName().equals("CompanyID")
+                || properties.get(1).getName().equals("CompanyID")
+                || properties.get(2).getName().equals("CompanyID")
+                || properties.get(3).getName().equals("CompanyID")
+                || properties.get(4).getName().equals("CompanyID"));
+        assertTrue(properties.get(0).getValue().toString().equals("0")
+                || properties.get(1).getValue().toString().equals("0")
+                || properties.get(2).getValue().toString().equals("0")
+                || properties.get(3).getValue().toString().equals("0")
+                || properties.get(4).getValue().toString().equals("0"));
+
+        found = true;
+      }
+    }
+
+    assertTrue(found);
+  }
+
+  private void asynOrders(final ODataPubFormat format) {
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("async").appendEntitySetSegment("Orders");
+
+    final ODataEntitySetRequest<ODataEntitySet> req =
+            client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
+    req.setFormat(format);
+
+    final AsyncRequestWrapper<ODataRetrieveResponse<ODataEntitySet>> async =
+            client.getAsyncRequestFactory().<ODataRetrieveResponse<ODataEntitySet>>getAsyncRequestWrapper(req);
+    async.callback(URI.create("http://client.service.it/callback/endpoint"));
+
+    final AsyncResponseWrapper<ODataRetrieveResponse<ODataEntitySet>> responseWrapper = async.execute();
+
+    assertTrue(responseWrapper.isPreferenceApplied());
+    assertTrue(responseWrapper.isDone());
+
+    final ODataRetrieveResponse<ODataEntitySet> res = responseWrapper.getODataResponse();
+    final ODataEntitySet entitySet = res.getBody();
+
+    assertFalse(entitySet.getEntities().isEmpty());
+  }
+
+  @Test
+  public void withInlineEntryAsAtom() {
+    withInlineEntry(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void withInlineEntryAsJSON() {
+    // this needs to be full, otherwise there is no mean to recognize links
+    withInlineEntry(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  @Test
+  public void asynOrdersAsAtom() {
+    asynOrders(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void asynOrdersAsJSON() {
+    asynOrders(ODataPubFormat.JSON);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v4/BatchTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/BatchTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/BatchTestITCase.java
new file mode 100644
index 0000000..0cf694c
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/BatchTestITCase.java
@@ -0,0 +1,710 @@
+/*
+ * 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.v4;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.apache.http.HttpResponse;
+import org.apache.olingo.client.api.ODataBatchConstants;
+import org.apache.olingo.client.api.communication.header.HeaderName;
+import org.apache.olingo.client.api.communication.request.ODataStreamManager;
+import org.apache.olingo.client.api.communication.request.batch.ODataBatchResponseItem;
+import org.apache.olingo.client.api.communication.request.batch.ODataChangeset;
+import org.apache.olingo.client.api.communication.request.batch.ODataRetrieve;
+import org.apache.olingo.client.api.communication.request.batch.v4.BatchStreamManager;
+import org.apache.olingo.client.api.communication.request.batch.v4.ODataBatchRequest;
+import org.apache.olingo.client.api.communication.request.batch.v4.ODataOutsideUpdate;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityUpdateRequest;
+import org.apache.olingo.client.api.communication.request.cud.v4.UpdateType;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.request.v4.AsyncBatchRequestWrapper;
+import org.apache.olingo.client.api.communication.response.ODataBatchResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
+import org.apache.olingo.client.api.communication.response.ODataResponse;
+import org.apache.olingo.client.api.communication.response.v4.AsyncResponse;
+import org.apache.olingo.client.api.communication.response.v4.AsyncResponseWrapper;
+import org.apache.olingo.client.api.uri.v4.URIBuilder;
+import org.apache.olingo.client.core.communication.request.AbstractODataStreamManager;
+import org.apache.olingo.client.core.communication.request.Wrapper;
+import org.apache.olingo.client.core.communication.request.batch.ODataChangesetResponseItem;
+import org.apache.olingo.client.core.communication.request.batch.ODataRetrieveResponseItem;
+import org.apache.olingo.client.core.communication.request.batch.v4.ODataOutsideUpdateResponseItem;
+import org.apache.olingo.client.core.communication.request.retrieve.ODataEntityRequestImpl;
+import org.apache.olingo.client.core.communication.request.retrieve.ODataEntityRequestImpl.ODataEntityResponseImpl;
+import org.apache.olingo.client.core.uri.URIUtils;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Test;
+
+public class BatchTestITCase extends AbstractTestITCase {
+
+  private static final String PREFIX = "!!PREFIX!!";
+
+  private static final String SUFFIX = "!!SUFFIX!!";
+
+  private static final int MAX = 10000;
+
+  // ------------------------
+  // Uncomment to check externally ...
+  // ------------------------
+  // private final static String testStaticServiceRootURL= 
+  //                  "http://odatae2etest.azurewebsites.net/javatest/DefaultService/";
+  // private final static String ACCEPT = ContentType.MULTIPART_MIXED;
+  // ------------------------
+  private final static String ACCEPT = ContentType.APPLICATION_OCTET_STREAM;
+
+  @Test
+  public void stringStreaming() {
+    final TestStreamManager streaming = new TestStreamManager();
+
+    new StreamingThread(streaming).start();
+
+    streaming.addObject((PREFIX + "\n").getBytes());
+
+    for (int i = 0; i <= MAX; i++) {
+      streaming.addObject((i + ") send info\n").getBytes());
+    }
+
+    streaming.addObject(SUFFIX.getBytes());
+    streaming.finalizeBody();
+  }
+
+  @Test
+  public void emptyBatchRequest() {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchStreamManager payload = request.execute();
+    final ODataBatchResponse response = payload.getResponse();
+
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void changesetWithError() {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchStreamManager payload = request.execute();
+    final ODataChangeset changeset = payload.addChangeset();
+
+    URIBuilder targetURI;
+    ODataEntityCreateRequest<ODataEntity> createReq;
+
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    for (int i = 1; i <= 2; i++) {
+      // Create Customer into the changeset
+      createReq = client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), newOrder(100 + i));
+      createReq.setFormat(ODataPubFormat.JSON);
+      changeset.addRequest(createReq);
+    }
+
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("WrongEntitySet");
+    createReq = client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), newOrder(105));
+    createReq.setFormat(ODataPubFormat.JSON);
+    changeset.addRequest(createReq);
+
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    for (int i = 3; i <= 4; i++) {
+      // Create Customer into the changeset
+      createReq = client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), newOrder(100 + i));
+      createReq.setFormat(ODataPubFormat.JSON);
+      changeset.addRequest(createReq);
+    }
+
+    final ODataBatchResponse response = payload.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+
+    ODataChangesetResponseItem retitem = (ODataChangesetResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertEquals(404, res.getStatusCode());
+    assertEquals("Not Found", res.getStatusMessage());
+    assertEquals(Integer.valueOf(3), Integer.valueOf(
+            res.getHeader(ODataBatchConstants.CHANGESET_CONTENT_ID_NAME).iterator().next()));
+
+    assertFalse(retitem.hasNext());
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void continueOnError() {
+    continueOnError(true);
+  }
+
+  @Test
+  public void doNotContinueOnError() {
+    continueOnError(false);
+  }
+
+  private void continueOnError(final boolean continueOnError) {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+    request.continueOnError();
+
+    final BatchStreamManager streamManager = request.execute();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    ODataRetrieve retrieve = streamManager.addRetrieve();
+
+    // prepare URI
+    URIBuilder targetURI = client.getURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("UnexistinfEntitySet").appendKeySegment(1);
+
+    // create new request
+    ODataEntityRequest<ODataEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ODataPubFormat.JSON);
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    retrieve = streamManager.addRetrieve();
+
+    // prepare URI
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataRetrieveResponseItem);
+
+    ODataRetrieveResponseItem retitem = (ODataRetrieveResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertEquals(404, res.getStatusCode());
+    assertEquals("Not Found", res.getStatusMessage());
+
+    if (continueOnError) {
+      item = iter.next();
+      assertTrue(item instanceof ODataRetrieveResponseItem);
+
+      retitem = (ODataRetrieveResponseItem) item;
+      res = retitem.next();
+      assertTrue(res instanceof ODataEntityResponseImpl);
+      assertEquals(200, res.getStatusCode());
+      assertEquals("OK", res.getStatusMessage());
+    }
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void changesetWithReference() throws EdmPrimitiveTypeException {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+    final BatchStreamManager streamManager = request.execute();
+
+    final ODataChangeset changeset = streamManager.addChangeset();
+    ODataEntity order = newOrder(20);
+
+    final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+
+    // add create request
+    final ODataEntityCreateRequest<ODataEntity> createReq =
+            client.getCUDRequestFactory().getEntityCreateRequest(uriBuilder.build(), order);
+
+    changeset.addRequest(createReq);
+
+    // retrieve request reference
+    int createRequestRef = changeset.getLastContentId();
+
+    // add update request: link CustomerInfo(17) to the new customer
+    final ODataEntity customerChanges = client.getObjectFactory().newEntity(order.getTypeName());
+    customerChanges.addLink(client.getObjectFactory().newEntitySetNavigationLink(
+            "OrderDetails",
+            client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("OrderDetails").
+            appendKeySegment(new HashMap<String, Object>() {
+      private static final long serialVersionUID = 3109256773218160485L;
+
+      {
+        put("OrderID", 7);
+        put("ProductID", 5);
+      }
+    }).build()));
+
+    final ODataEntityUpdateRequest<ODataEntity> updateReq = client.getCUDRequestFactory().getEntityUpdateRequest(
+            URI.create("$" + createRequestRef), UpdateType.PATCH, customerChanges);
+
+    changeset.addRequest(updateReq);
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+
+    // verify response payload ...
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    final ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataChangesetResponseItem);
+
+    final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
+
+    ODataResponse res = chgitem.next();
+    assertEquals(201, res.getStatusCode());
+    assertTrue(res instanceof ODataEntityCreateResponse);
+
+    order = ((ODataEntityCreateResponse<ODataEntity>) res).getBody();
+    final ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest(
+            URIUtils.getURI(testStaticServiceRootURL, order.getEditLink().toASCIIString() + "/OrderDetails"));
+
+    assertEquals(Integer.valueOf(7),
+            req.execute().getBody().getEntities().get(0).getProperty("OrderID").getPrimitiveValue().
+            toCastValue(Integer.class));
+
+    res = chgitem.next();
+    assertEquals(204, res.getStatusCode());
+    assertTrue(res instanceof ODataEntityUpdateResponse);
+
+    // clean ...
+    assertEquals(204, client.getCUDRequestFactory().getDeleteRequest(
+            URIUtils.getURI(testStaticServiceRootURL, order.getEditLink().toASCIIString())).execute().
+            getStatusCode());
+
+    try {
+      client.getRetrieveRequestFactory().getEntityRequest(
+              URIUtils.getURI(testStaticServiceRootURL, order.getEditLink().toASCIIString())).
+              execute().getBody();
+      fail();
+    } catch (Exception e) {
+      // ignore
+    }
+  }
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void batchRequestWithOutsideUpdates() throws EdmPrimitiveTypeException {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+    final BatchStreamManager streamManager = request.execute();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    ODataRetrieve retrieve = streamManager.addRetrieve();
+
+    // prepare URI
+    URIBuilder targetURI = client.getURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("Customers").appendKeySegment(1).
+            expand("Orders").select("PersonID,Orders/OrderID");
+
+    // create new request
+    ODataEntityRequest<ODataEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ODataPubFormat.JSON);
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add new order with outside item
+    // -------------------------------------------
+    final ODataOutsideUpdate outside = streamManager.addOutsideUpdate();
+
+    // prepare URI
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    final ODataEntity original = newOrder(2000);
+    final ODataEntityCreateRequest<ODataEntity> createReq =
+            client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), original);
+    createReq.setFormat(ODataPubFormat.JSON);
+    outside.setRequest(createReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataRetrieveResponseItem);
+
+    ODataRetrieveResponseItem retitem = (ODataRetrieveResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertTrue(res instanceof ODataEntityResponseImpl);
+    assertEquals(200, res.getStatusCode());
+    assertEquals("OK", res.getStatusMessage());
+
+    // retrieve the second item (ODataChangeset)
+    item = iter.next();
+    assertTrue(item instanceof ODataOutsideUpdateResponseItem);
+
+    final ODataOutsideUpdateResponseItem outitem = (ODataOutsideUpdateResponseItem) item;
+    res = outitem.next();
+    assertTrue(res instanceof ODataEntityCreateResponse);
+    assertEquals(201, res.getStatusCode());
+    assertEquals("Created", res.getStatusMessage());
+
+    final ODataEntityCreateResponse<ODataEntity> entres = (ODataEntityCreateResponse<ODataEntity>) res;
+    final ODataEntity entity = entres.getBody();
+    assertEquals(2000, entity.getProperty("OrderID").getPrimitiveValue().toCastValue(Integer.class).intValue());
+
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  @SuppressWarnings({"unchecked"})
+  public void batchRequest() throws EdmPrimitiveTypeException {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(testStaticServiceRootURL);
+    request.setAccept(ACCEPT);
+
+    final BatchStreamManager streamManager = request.execute();
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    ODataRetrieve retrieve = streamManager.addRetrieve();
+
+    // prepare URI
+    URIBuilder targetURI = client.getURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    ODataEntityRequest<ODataEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ODataPubFormat.JSON);
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add changeset item
+    // -------------------------------------------
+    final ODataChangeset changeset = streamManager.addChangeset();
+
+    // Update Customer into the changeset
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+    final URI editLink = targetURI.build();
+
+    final ODataEntity patch = client.getObjectFactory().newEntity(
+            new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Customer"));
+    patch.setEditLink(editLink);
+
+    patch.getProperties().add(client.getObjectFactory().newPrimitiveProperty(
+            "LastName",
+            client.getObjectFactory().newPrimitiveValueBuilder().buildString("new last name")));
+
+    final ODataEntityUpdateRequest<ODataEntity> changeReq =
+            client.getCUDRequestFactory().getEntityUpdateRequest(UpdateType.PATCH, patch);
+    changeReq.setFormat(ODataPubFormat.JSON_FULL_METADATA);
+
+    changeset.addRequest(changeReq);
+
+    // Create Order into the changeset
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Orders");
+    final ODataEntity original = newOrder(1000);
+    final ODataEntityCreateRequest<ODataEntity> createReq =
+            client.getCUDRequestFactory().getEntityCreateRequest(targetURI.build(), original);
+    createReq.setFormat(ODataPubFormat.JSON);
+    changeset.addRequest(createReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    retrieve = streamManager.addRetrieve();
+
+    // prepare URI
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    final ODataBatchResponse response = streamManager.getResponse();
+    assertEquals(200, response.getStatusCode());
+    assertEquals("OK", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataRetrieveResponseItem);
+
+    ODataRetrieveResponseItem retitem = (ODataRetrieveResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertTrue(res instanceof ODataEntityResponseImpl);
+    assertEquals(200, res.getStatusCode());
+    assertEquals("OK", res.getStatusMessage());
+
+    ODataEntityRequestImpl<ODataEntity>.ODataEntityResponseImpl entres =
+            (ODataEntityRequestImpl.ODataEntityResponseImpl) res;
+
+    ODataEntity entity = entres.getBody();
+    assertEquals(1, entity.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // retrieve the second item (ODataChangeset)
+    item = iter.next();
+    assertTrue(item instanceof ODataChangesetResponseItem);
+
+    final ODataChangesetResponseItem chgitem = (ODataChangesetResponseItem) item;
+    res = chgitem.next();
+    assertTrue(res instanceof ODataEntityUpdateResponse);
+    assertEquals(204, res.getStatusCode());
+    assertEquals("No Content", res.getStatusMessage());
+
+    res = chgitem.next();
+    assertTrue(res instanceof ODataEntityCreateResponse);
+    assertEquals(201, res.getStatusCode());
+    assertEquals("Created", res.getStatusMessage());
+
+    final ODataEntityCreateResponse<ODataEntity> createres = (ODataEntityCreateResponse<ODataEntity>) res;
+    entity = createres.getBody();
+    assertEquals(new Integer(1000), entity.getProperty("OrderID").getPrimitiveValue().toCastValue(Integer.class));
+
+    // retrive the third item (ODataRetrieve)
+    item = iter.next();
+    assertTrue(item instanceof ODataRetrieveResponseItem);
+
+    retitem = (ODataRetrieveResponseItem) item;
+    res = retitem.next();
+    assertTrue(res instanceof ODataEntityResponseImpl);
+    assertEquals(200, res.getStatusCode());
+    assertEquals("OK", res.getStatusMessage());
+
+    entres = (ODataEntityRequestImpl.ODataEntityResponseImpl) res;
+    entity = entres.getBody();
+    assertEquals("new last name", entity.getProperty("LastName").getPrimitiveValue().toCastValue(String.class));
+
+    assertFalse(iter.hasNext());
+  }
+
+  @Test
+  public void async() {
+    // create your request
+    final ODataBatchRequest request = client.getBatchRequestFactory().getBatchRequest(
+            URI.create(testStaticServiceRootURL + "/async/").normalize().toASCIIString());
+    request.setAccept(ACCEPT);
+
+    final AsyncBatchRequestWrapper async = client.getAsyncRequestFactory().getAsyncBatchRequestWrapper(request);
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    ODataRetrieve retrieve = async.addRetrieve();
+
+    // prepare URI
+    URIBuilder targetURI = client.getURIBuilder(testStaticServiceRootURL);
+    targetURI.appendEntitySetSegment("People").appendKeySegment(5);
+
+    // create new request
+    ODataEntityRequest<ODataEntity> queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+    queryReq.setFormat(ODataPubFormat.JSON);
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    // -------------------------------------------
+    // Add retrieve item
+    // -------------------------------------------
+    retrieve = async.addRetrieve();
+
+    // prepare URI
+    targetURI = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").appendKeySegment(1);
+
+    // create new request
+    queryReq = client.getRetrieveRequestFactory().getEntityRequest(targetURI.build());
+
+    retrieve.setRequest(queryReq);
+    // -------------------------------------------
+
+    final AsyncResponseWrapper<ODataBatchResponse> responseWrapper = async.execute();
+
+    assertTrue(responseWrapper.isPreferenceApplied());
+    assertTrue(responseWrapper.isDone());
+
+    final ODataBatchResponse response = responseWrapper.getODataResponse();
+
+    assertEquals(200, response.getStatusCode());
+    assertEquals("Ok", response.getStatusMessage());
+    final Iterator<ODataBatchResponseItem> iter = response.getBody();
+
+    // retrieve the first item (ODataRetrieve)
+    ODataBatchResponseItem item = iter.next();
+    assertTrue(item instanceof ODataRetrieveResponseItem);
+
+    // The service return interim results to an asynchronously executing batch.
+    ODataRetrieveResponseItem retitem = (ODataRetrieveResponseItem) item;
+    ODataResponse res = retitem.next();
+    assertTrue(res instanceof AsyncResponse);
+    assertEquals(202, res.getStatusCode());
+    assertEquals("Accepted", res.getStatusMessage());
+
+    Collection<String> newMonitorLocation = res.getHeader(HeaderName.location);
+    if (newMonitorLocation != null && !newMonitorLocation.isEmpty()) {
+      responseWrapper.forceNextMonitorCheck(URI.create(newMonitorLocation.iterator().next()));
+      // .... now you can start again with isDone() and getODataResponse().
+    }
+
+    assertFalse(retitem.hasNext());
+    assertFalse(iter.hasNext());
+  }
+
+  private static class TestStreamManager extends AbstractODataStreamManager<ODataBatchResponse> {
+
+    public TestStreamManager() {
+      super(new Wrapper<Future<HttpResponse>>());
+    }
+
+    public ODataStreamManager<ODataBatchResponse> addObject(final byte[] src) {
+      stream(src);
+      return this;
+    }
+
+    @Override
+    protected ODataBatchResponse getResponse(final long timeout, final TimeUnit unit) {
+      throw new UnsupportedOperationException("Not supported yet.");
+    }
+  };
+
+  /**
+   * To be used for debug purposes.
+   */
+  private static class StreamingThread extends Thread {
+
+    private final TestStreamManager streaming;
+
+    public StreamingThread(final TestStreamManager streaming) {
+      super();
+      this.streaming = streaming;
+    }
+
+    @Override
+    public void run() {
+      try {
+        final StringBuilder builder = new StringBuilder();
+
+        byte[] buff = new byte[1024];
+
+        int len;
+
+        while ((len = streaming.getBody().read(buff)) >= 0) {
+          builder.append(new String(buff, 0, len));
+        }
+
+        assertTrue(builder.toString().startsWith(PREFIX));
+        assertTrue(builder.toString().contains((MAX / 2) + ") send info"));
+        assertTrue(builder.toString().contains((MAX / 3) + ") send info"));
+        assertTrue(builder.toString().contains((MAX / 20) + ") send info"));
+        assertTrue(builder.toString().contains((MAX / 30) + ") send info"));
+        assertTrue(builder.toString().contains(MAX + ") send info"));
+        assertTrue(builder.toString().endsWith(SUFFIX));
+
+      } catch (IOException e) {
+        fail();
+      }
+    }
+  }
+
+  private static class BatchStreamingThread extends Thread {
+
+    private final BatchStreamManager streaming;
+
+    public BatchStreamingThread(final BatchStreamManager streaming) {
+      super();
+      this.streaming = streaming;
+    }
+
+    @Override
+    public void run() {
+      try {
+        final StringBuilder builder = new StringBuilder();
+
+        final byte[] buff = new byte[1024];
+
+        int len;
+
+        while ((len = streaming.getBody().read(buff)) >= 0) {
+          builder.append(new String(buff, 0, len));
+        }
+
+        LOG.debug("Batch request {}", builder.toString());
+
+        assertTrue(builder.toString().contains("Content-Id:2"));
+        assertTrue(builder.toString().contains("GET " + testStaticServiceRootURL));
+      } catch (IOException e) {
+        fail();
+      }
+    }
+  }
+
+  private ODataEntity newOrder(final int id) {
+    final ODataEntity order = getClient().getObjectFactory().
+            newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Order"));
+
+    order.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("OrderID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+    order.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("OrderDate",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.DateTimeOffset).setValue(Calendar.getInstance()).build()));
+    order.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("ShelfLife",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Duration).setText("PT0.0000002S").build()));
+    order.getProperties().add(getClient().getObjectFactory().newCollectionProperty("OrderShelfLifes",
+            getClient().getObjectFactory().newCollectionValue(EdmPrimitiveTypeKind.Duration.name()).add(
+            getClient().getObjectFactory().newPrimitiveValueBuilder().setType(EdmPrimitiveTypeKind.Duration).
+            setText("PT0.0000002S").build())));
+
+    return order;
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v4/BoundOperationInvokeTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/BoundOperationInvokeTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/BoundOperationInvokeTestITCase.java
new file mode 100644
index 0000000..88e1ac3
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/BoundOperationInvokeTestITCase.java
@@ -0,0 +1,339 @@
+/*
+ * 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.v4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.olingo.client.api.communication.request.invoke.ODataInvokeRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.client.api.uri.v4.URIBuilder;
+import org.apache.olingo.commons.api.domain.ODataCollectionValue;
+import org.apache.olingo.commons.api.domain.ODataComplexValue;
+import org.apache.olingo.commons.api.domain.ODataOperation;
+import org.apache.olingo.commons.api.domain.ODataPrimitiveValue;
+import org.apache.olingo.commons.api.domain.ODataValue;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.v4.ODataEnumValue;
+import org.apache.olingo.commons.api.domain.v4.ODataProperty;
+import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmAction;
+import org.apache.olingo.commons.api.edm.EdmEntityContainer;
+import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Test;
+
+public class BoundOperationInvokeTestITCase extends AbstractTestITCase {
+
+  private Edm getEdm() {
+    final Edm edm = getClient().getRetrieveRequestFactory().
+            getMetadataRequest(testStaticServiceRootURL).execute().getBody();
+    assertNotNull(edm);
+
+    return edm;
+  }
+
+  private void functions(final ODataPubFormat format) throws EdmPrimitiveTypeException {
+    final Edm edm = getEdm();
+    final EdmEntityContainer container = edm.getSchemas().get(0).getEntityContainer();
+    assertNotNull(container);
+
+    // GetEmployeesCount
+    URIBuilder builder = getClient().getURIBuilder(testStaticServiceRootURL).appendSingletonSegment("Company");
+    ODataEntityRequest<ODataEntity> entityReq =
+            getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    ODataEntity entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    ODataOperation boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetEmployeesCount");
+    assertNotNull(boundOp);
+
+    EdmFunction func = edm.getBoundFunction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(),
+            false, null);
+    assertNotNull(func);
+
+    final ODataInvokeRequest<ODataProperty> getEmployeesCountReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), func);
+    getEmployeesCountReq.setFormat(format);
+    final ODataProperty getEmployeesCountRes = getEmployeesCountReq.execute().getBody();
+    assertNotNull(getEmployeesCountRes);
+    assertTrue(getEmployeesCountRes.hasPrimitiveValue());
+
+    // GetProductDetails
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Products").appendKeySegment(5);
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails");
+    assertNotNull(boundOp);
+
+    func = edm.getBoundFunction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false, null);
+    assertNotNull(func);
+
+    final ODataPrimitiveValue count = getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(1);
+    final ODataInvokeRequest<ODataEntitySet> getProductDetailsReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), func,
+                    Collections.<String, ODataValue>singletonMap("count", count));
+    getProductDetailsReq.setFormat(format);
+    final ODataEntitySet getProductDetailsRes = getProductDetailsReq.execute().getBody();
+    assertNotNull(getProductDetailsRes);
+    assertEquals(1, getProductDetailsRes.getCount());
+
+    // GetRelatedProduct
+    final Map<String, Object> keyMap = new LinkedHashMap<String, Object>();
+    keyMap.put("ProductID", 6);
+    keyMap.put("ProductDetailID", 1);
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("ProductDetails").appendKeySegment(keyMap);
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetRelatedProduct");
+    assertNotNull(boundOp);
+
+    func = edm.getBoundFunction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false, null);
+    assertNotNull(func);
+
+    final ODataInvokeRequest<ODataEntity> getRelatedProductReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), func);
+    getRelatedProductReq.setFormat(format);
+    final ODataEntity getRelatedProductRes = getRelatedProductReq.execute().getBody();
+    assertNotNull(getRelatedProductRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.Product",
+            getRelatedProductRes.getTypeName().toString());
+    assertEquals(6, getRelatedProductRes.getProperty("ProductID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // GetDefaultPI
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Accounts").appendKeySegment(101);
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI");
+    assertNotNull(boundOp);
+
+    func = edm.getBoundFunction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false, null);
+    assertNotNull(func);
+
+    final ODataInvokeRequest<ODataEntity> getDefaultPIReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), func);
+    getDefaultPIReq.setFormat(format);
+    final ODataEntity getDefaultPIRes = getDefaultPIReq.execute().getBody();
+    assertNotNull(getDefaultPIRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument",
+            getDefaultPIRes.getTypeName().toString());
+    assertEquals(101901,
+            getDefaultPIRes.getProperty("PaymentInstrumentID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // GetAccountInfo
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo");
+    assertNotNull(boundOp);
+
+    func = edm.getBoundFunction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false, null);
+    assertNotNull(func);
+
+    final ODataInvokeRequest<ODataProperty> getAccountInfoReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), func);
+    getAccountInfoReq.setFormat(format);
+    final ODataProperty getAccountInfoRes = getAccountInfoReq.execute().getBody();
+    assertNotNull(getAccountInfoRes);
+    assertTrue(getAccountInfoRes.hasComplexValue());
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.AccountInfo",
+            getAccountInfoRes.getComplexValue().getTypeName());
+
+    // GetActualAmount
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(
+            entity.getNavigationLink("MyGiftCard").getLink());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+    assertEquals(301, entity.getProperty("GiftCardID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.GetActualAmount");
+    assertNotNull(boundOp);
+
+    func = edm.getBoundFunction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false, null);
+    assertNotNull(func);
+
+    final ODataPrimitiveValue bonusRate = getClient().getObjectFactory().newPrimitiveValueBuilder().buildDouble(1.1);
+    final ODataInvokeRequest<ODataProperty> getActualAmountReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), func,
+                    Collections.<String, ODataValue>singletonMap("bonusRate", bonusRate));
+    getActualAmountReq.setFormat(format);
+    final ODataProperty getActualAmountRes = getActualAmountReq.execute().getBody();
+    assertNotNull(getActualAmountRes);
+    assertEquals(41.79, getActualAmountRes.getPrimitiveValue().toCastValue(Double.class), 0);
+  }
+
+  @Test
+  public void atomFunctions() throws EdmPrimitiveTypeException {
+    functions(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void jsonFunctions() throws EdmPrimitiveTypeException {
+    functions(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+  private void actions(final ODataPubFormat format) throws EdmPrimitiveTypeException {
+    final Edm edm = getEdm();
+    final EdmEntityContainer container = edm.getSchemas().get(0).getEntityContainer();
+    assertNotNull(container);
+
+    // IncreaseRevenue
+    URIBuilder builder = getClient().getURIBuilder(testStaticServiceRootURL).appendSingletonSegment("Company");
+    ODataEntityRequest<ODataEntity> entityReq =
+            getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    ODataEntity entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    ODataOperation boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.IncreaseRevenue");
+    assertNotNull(boundOp);
+
+    EdmAction act = edm.getBoundAction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false);
+    assertNotNull(act);
+
+    final ODataPrimitiveValue increaseValue = getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.Int64).setValue(12).build();
+    final ODataInvokeRequest<ODataProperty> increaseRevenueReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), act,
+                    Collections.<String, ODataValue>singletonMap("IncreaseValue", increaseValue));
+    increaseRevenueReq.setFormat(format);
+    final ODataProperty increaseRevenueRes = increaseRevenueReq.execute().getBody();
+    assertNotNull(increaseRevenueRes);
+    assertTrue(increaseRevenueRes.hasPrimitiveValue());
+
+    // AddAccessRight
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Products").appendKeySegment(5);
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight");
+    assertNotNull(boundOp);
+
+    act = edm.getBoundAction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false);
+    assertNotNull(act);
+
+    final ODataEnumValue accessRight = getClient().getObjectFactory().
+            newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel", "Execute");
+    final ODataInvokeRequest<ODataProperty> getProductDetailsReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), act,
+                    Collections.<String, ODataValue>singletonMap("accessRight", accessRight));
+    getProductDetailsReq.setFormat(format);
+    final ODataProperty getProductDetailsRes = getProductDetailsReq.execute().getBody();
+    assertNotNull(getProductDetailsRes);
+    assertTrue(getProductDetailsRes.hasEnumValue());
+
+    // ResetAddress
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Customers").appendKeySegment(2);
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.ResetAddress");
+    assertNotNull(boundOp);
+
+    act = edm.getBoundAction(new FullQualifiedName(boundOp.getTitle()),
+            edm.getEntityType(entity.getTypeName()).getBaseType().getFullQualifiedName(), false);
+    assertNotNull(act);
+
+    final ODataCollectionValue<org.apache.olingo.commons.api.domain.v4.ODataValue> addresses =
+            getClient().getObjectFactory().
+            newCollectionValue("Collection(Microsoft.Test.OData.Services.ODataWCFService.Address)");
+    final ODataComplexValue<ODataProperty> address = getClient().getObjectFactory().
+            newLinkedComplexValue("Microsoft.Test.OData.Services.ODataWCFService.Address");
+    address.add(client.getObjectFactory().newPrimitiveProperty("Street",
+            client.getObjectFactory().newPrimitiveValueBuilder().buildString("Piazza La Bomba E Scappa")));
+    address.add(client.getObjectFactory().newPrimitiveProperty("City",
+            client.getObjectFactory().newPrimitiveValueBuilder().buildString("Tollo")));
+    address.add(client.getObjectFactory().newPrimitiveProperty("PostalCode",
+            client.getObjectFactory().newPrimitiveValueBuilder().buildString("66010")));
+    addresses.add(address);
+    final ODataPrimitiveValue index = getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(0);
+    final Map<String, ODataValue> params = new LinkedHashMap<String, ODataValue>(2);
+    params.put("addresses", addresses);
+    params.put("index", index);
+    final ODataInvokeRequest<ODataEntity> resetAddressReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), act, params);
+    resetAddressReq.setFormat(format);
+    final ODataEntity resetAddressRes = resetAddressReq.execute().getBody();
+    assertNotNull(resetAddressRes);
+    assertEquals(2, resetAddressRes.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    // RefreshDefaultPI
+    builder = getClient().getURIBuilder(testStaticServiceRootURL).
+            appendEntitySetSegment("Accounts").appendKeySegment(101);
+    entityReq = getClient().getRetrieveRequestFactory().getEntityRequest(builder.build());
+    entityReq.setFormat(format);
+    entity = entityReq.execute().getBody();
+    assertNotNull(entity);
+
+    boundOp = entity.getOperation("Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI");
+    assertNotNull(boundOp);
+
+    act = edm.getBoundAction(new FullQualifiedName(boundOp.getTitle()), entity.getTypeName(), false);
+    assertNotNull(act);
+
+    final ODataPrimitiveValue newDate = getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.DateTimeOffset).setText("2014-04-09T00:00:00Z").build();
+    final ODataInvokeRequest<ODataEntity> getDefaultPIReq =
+            getClient().getInvokeRequestFactory().getInvokeRequest(boundOp.getTarget(), act,
+                    Collections.<String, ODataValue>singletonMap("newDate", newDate));
+    getDefaultPIReq.setFormat(format);
+    final ODataEntity getDefaultPIRes = getDefaultPIReq.execute().getBody();
+    assertNotNull(getDefaultPIRes);
+    assertEquals("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument",
+            getDefaultPIRes.getTypeName().toString());
+    assertEquals(101901,
+            getDefaultPIRes.getProperty("PaymentInstrumentID").getPrimitiveValue().toCastValue(Integer.class), 0);
+  }
+
+  @Test
+  public void atomActions() throws EdmPrimitiveTypeException {
+    actions(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void jsonActions() throws EdmPrimitiveTypeException {
+    actions(ODataPubFormat.JSON_FULL_METADATA);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v4/DeltaTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/DeltaTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/DeltaTestITCase.java
new file mode 100644
index 0000000..700ed98
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/DeltaTestITCase.java
@@ -0,0 +1,86 @@
+/*
+ * 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.v4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
+import org.apache.olingo.client.api.communication.request.retrieve.v4.ODataDeltaRequest;
+import org.apache.olingo.commons.api.domain.v4.ODataDelta;
+import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
+import org.apache.olingo.commons.api.domain.v4.ODataProperty;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Test;
+
+public class DeltaTestITCase extends AbstractTestITCase {
+
+  private void parse(final ODataPubFormat format) {
+    final ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory().getEntitySetRequest(
+            client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").build());
+    req.setPrefer(client.newPreferences().trackChanges());
+    
+    final ODataEntitySet customers = req.execute().getBody();
+    assertNotNull(customers);
+    assertNotNull(customers.getDeltaLink());
+
+    final ODataDeltaRequest deltaReq = client.getRetrieveRequestFactory().getDeltaRequest(customers.getDeltaLink());
+    deltaReq.setFormat(format);
+
+    final ODataDelta delta = deltaReq.execute().getBody();
+    assertNotNull(delta);
+
+    assertNotNull(delta.getDeltaLink());
+    assertTrue(delta.getDeltaLink().isAbsolute());
+    assertEquals(5, delta.getCount(), 0);
+
+    assertEquals(1, delta.getDeletedEntities().size());
+    assertTrue(delta.getDeletedEntities().get(0).getId().isAbsolute());
+    assertTrue(delta.getDeletedEntities().get(0).getId().toASCIIString().endsWith("Customers('ANTON')"));
+
+    assertEquals(1, delta.getAddedLinks().size());
+    assertTrue(delta.getAddedLinks().get(0).getSource().isAbsolute());
+    assertTrue(delta.getAddedLinks().get(0).getSource().toASCIIString().endsWith("Customers('BOTTM')"));
+    assertEquals("Orders", delta.getAddedLinks().get(0).getRelationship());
+
+    assertEquals(1, delta.getDeletedLinks().size());
+    assertTrue(delta.getDeletedLinks().get(0).getSource().isAbsolute());
+    assertTrue(delta.getDeletedLinks().get(0).getSource().toASCIIString().endsWith("Customers('ALFKI')"));
+    assertEquals("Orders", delta.getDeletedLinks().get(0).getRelationship());
+
+    assertEquals(2, delta.getEntities().size());
+    ODataProperty property = delta.getEntities().get(0).getProperty("ContactName");
+    assertNotNull(property);
+    assertTrue(property.hasPrimitiveValue());
+    property = delta.getEntities().get(1).getProperty("ShippingAddress");
+    assertNotNull(property);
+    assertTrue(property.hasComplexValue());
+  }
+
+  @Test
+  public void atomParse() {
+    parse(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void jsonParse() {
+    parse(ODataPubFormat.JSON);
+  }
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/8042913b/fit/src/test/java/org/apache/olingo/fit/v4/EntityCreateTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/EntityCreateTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/EntityCreateTestITCase.java
new file mode 100644
index 0000000..3e66e1d
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/EntityCreateTestITCase.java
@@ -0,0 +1,186 @@
+/*
+ * 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.v4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+import java.util.Calendar;
+import org.apache.commons.lang3.RandomUtils;
+import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest;
+import org.apache.olingo.client.api.communication.response.ODataDeleteResponse;
+import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse;
+import org.apache.olingo.commons.api.domain.ODataInlineEntitySet;
+import org.apache.olingo.commons.api.domain.ODataLink;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Test;
+
+public class EntityCreateTestITCase extends AbstractTestITCase {
+
+  @Test
+  public void atomCreateAndDelete() {
+    createAndDeleteOrder(ODataPubFormat.ATOM, 1000);
+  }
+
+  @Test
+  public void jsonCreateAndDelete() {
+    createAndDeleteOrder(ODataPubFormat.JSON, 1001);
+  }
+
+  private void onContained(final ODataPubFormat format) {
+    final URI uri = getClient().getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Accounts").
+            appendKeySegment(101).appendNavigationSegment("MyPaymentInstruments").build();
+
+    // 1. read contained collection before any operation
+    ODataEntitySet instruments = getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody();
+    assertNotNull(instruments);
+    final int sizeBefore = instruments.getCount();
+
+    // 2. instantiate an ODataEntity of the same type as the collection above
+    final ODataEntity instrument = getClient().getObjectFactory().
+            newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument"));
+
+    int id = RandomUtils.nextInt(101999, 105000);
+    instrument.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("PaymentInstrumentID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(id)));
+    instrument.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("FriendlyName",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("New one")));
+    instrument.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("CreatedDate",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().
+            setType(EdmPrimitiveTypeKind.DateTimeOffset).setValue(Calendar.getInstance()).build()));
+
+    // 3. create it as contained entity
+    final ODataEntityCreateRequest<ODataEntity> req = getClient().getCUDRequestFactory().
+            getEntityCreateRequest(uri, instrument);
+    final ODataEntityCreateResponse<ODataEntity> res = req.execute();
+    assertEquals(201, res.getStatusCode());
+
+    // 4. verify that the contained collection effectively grew
+    instruments = getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody();
+    assertNotNull(instruments);
+    final int sizeAfter = instruments.getCount();
+    assertEquals(sizeBefore + 1, sizeAfter);
+
+    // 5. remove the contained entity created above
+    final ODataDeleteResponse deleteRes = getClient().getCUDRequestFactory().
+            getDeleteRequest(getClient().getURIBuilder(uri.toASCIIString()).appendKeySegment(id).build()).execute();
+    assertEquals(204, deleteRes.getStatusCode());
+
+    // 6. verify that the contained collection effectively reduced
+    instruments = getClient().getRetrieveRequestFactory().getEntitySetRequest(uri).execute().getBody();
+    assertNotNull(instruments);
+    final int sizeEnd = instruments.getCount();
+    assertEquals(sizeBefore, sizeEnd);
+  }
+
+  @Test
+  public void atomOnContained() {
+    onContained(ODataPubFormat.ATOM);
+  }
+
+  @Test
+  public void jsonOnContained() {
+    onContained(ODataPubFormat.JSON);
+  }
+
+  private void deepInsert(final ODataPubFormat format, final int productId, final int productDetailId)
+          throws EdmPrimitiveTypeException {
+
+    final ODataEntity product = getClient().getObjectFactory().
+            newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.Product"));
+    product.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("ProductID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(productId)));
+    product.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("Name",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("Latte")));
+    product.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("QuantityPerUnit",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("100g Bag")));
+    product.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("UnitPrice",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildSingle(3.24f)));
+    product.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("QuantityInStock",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(100)));
+    product.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("Discontinued",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildBoolean(false)));
+    product.getProperties().add(getClient().getObjectFactory().newEnumProperty("UserAccess",
+            getClient().getObjectFactory().
+            newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel", "Execute")));
+    product.getProperties().add(getClient().getObjectFactory().newEnumProperty("SkinColor",
+            getClient().getObjectFactory().
+            newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.Color", "Blue")));
+    product.getProperties().add(getClient().getObjectFactory().newCollectionProperty("CoverColors",
+            getClient().getObjectFactory().
+            newCollectionValue("Collection(Microsoft.Test.OData.Services.ODataWCFService.ProductDetail)")));
+    product.getProperty("CoverColors").getCollectionValue().add(getClient().getObjectFactory().
+            newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.Color", "Green"));
+    product.getProperty("CoverColors").getCollectionValue().add(getClient().getObjectFactory().
+            newEnumValue("Microsoft.Test.OData.Services.ODataWCFService.Color", "Red"));
+
+    final ODataEntity detail = getClient().getObjectFactory().
+            newEntity(new FullQualifiedName("Microsoft.Test.OData.Services.ODataWCFService.ProductDetail"));
+    detail.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("ProductID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(productId)));
+    detail.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("ProductDetailID",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildInt32(productDetailId)));
+    detail.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("ProductName",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("LatteHQ")));
+    detail.getProperties().add(getClient().getObjectFactory().newPrimitiveProperty("Description",
+            getClient().getObjectFactory().newPrimitiveValueBuilder().buildString("High-Quality Milk")));
+
+    final ODataEntitySet details = getClient().getObjectFactory().newEntitySet();
+    details.getEntities().add(detail);
+
+    final ODataInlineEntitySet inlineDetails = getClient().getObjectFactory().
+            newDeepInsertEntitySet("Details", details);
+    product.addLink(inlineDetails);
+
+    final ODataEntityCreateRequest<ODataEntity> req = getClient().getCUDRequestFactory().getEntityCreateRequest(
+            getClient().getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Products").build(), product);
+    req.setFormat(format);
+    final ODataEntityCreateResponse<ODataEntity> res = req.execute();
+    assertEquals(201, res.getStatusCode());
+
+    final ODataEntity createdProduct = res.getBody();
+    assertEquals(productId,
+            createdProduct.getProperty("ProductID").getPrimitiveValue().toCastValue(Integer.class), 0);
+
+    final ODataLink createdLink = createdProduct.getNavigationLink("Details");
+    assertNotNull(createdLink);
+
+    final ODataEntitySet createdProductDetails =
+            getClient().getRetrieveRequestFactory().getEntitySetRequest(createdLink.getLink()).execute().getBody();
+    assertNotNull(createdProductDetails);
+    assertEquals(productDetailId, createdProductDetails.getEntities().iterator().next().
+            getProperty("ProductDetailID").getPrimitiveValue().toCastValue(Integer.class), 0);
+  }
+
+  @Test
+  public void atomDeepInsert() throws EdmPrimitiveTypeException {
+    deepInsert(ODataPubFormat.ATOM, 10, 10);
+  }
+
+  @Test
+  public void jsonDeepInsert() throws EdmPrimitiveTypeException {
+    deepInsert(ODataPubFormat.JSON_FULL_METADATA, 11, 11);
+  }
+}