You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/08/15 05:43:39 UTC

[camel] 01/06: CAMEL-13852: Support OData action's

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 895dee3d9fe5fbc0f07afc1e12cbd2f9450a330b
Author: Marc Giger <gi...@gmx.ch>
AuthorDate: Sun Aug 11 14:08:01 2019 +0200

    CAMEL-13852: Support OData action's
---
 .../camel/component/olingo4/api/Olingo4App.java    | 10 +++
 .../component/olingo4/api/impl/Olingo4AppImpl.java | 31 ++++++---
 .../camel/component/olingo4/Olingo4AppAPITest.java | 73 ++++++++++++++++++++++
 .../camel-olingo4/camel-olingo4-component/pom.xml  |  1 +
 .../src/signatures/olingo-api-signature.txt        |  1 +
 .../olingo4/Olingo4ComponentProducerTest.java      | 21 +++++++
 6 files changed, 129 insertions(+), 8 deletions(-)

diff --git a/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/Olingo4App.java b/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/Olingo4App.java
index 3863c1b..0649a7c 100644
--- a/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/Olingo4App.java
+++ b/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/Olingo4App.java
@@ -149,4 +149,14 @@ public interface Olingo4App {
      * @param responseHandler callback handler
      */
     void batch(Edm edm, Map<String, String> endpointHttpHeaders, Object data, Olingo4ResponseHandler<List<Olingo4BatchResponse>> responseHandler);
+
+    /**
+     * Calls a OData action
+     * @param edm service Edm
+     * @param resourcePath resource path to action
+     * @param endpointHttpHeaders HTTP Headers to add/override the component versions
+     * @param data action data
+     * @param responseHandler {@link org.apache.olingo.client.api.domain.ClientEntity} callback handler
+     */
+    <T> void action(Edm edm, String resourcePath, Map<String, String> endpointHttpHeaders, Object data, Olingo4ResponseHandler<T> responseHandler);
 }
diff --git a/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/impl/Olingo4AppImpl.java b/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/impl/Olingo4AppImpl.java
index c59e562..84ef1e3 100644
--- a/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/impl/Olingo4AppImpl.java
+++ b/components/camel-olingo4/camel-olingo4-api/src/main/java/org/apache/camel/component/olingo4/api/impl/Olingo4AppImpl.java
@@ -40,14 +40,7 @@ import org.apache.camel.util.ObjectHelper;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.LineIterator;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.http.Consts;
-import org.apache.http.Header;
-import org.apache.http.HttpException;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpResponse;
-import org.apache.http.HttpResponseFactory;
-import org.apache.http.HttpVersion;
-import org.apache.http.StatusLine;
+import org.apache.http.*;
 import org.apache.http.client.entity.DecompressingEntity;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpDelete;
@@ -60,6 +53,7 @@ import org.apache.http.client.methods.HttpUriRequest;
 import org.apache.http.concurrent.FutureCallback;
 import org.apache.http.config.MessageConstraints;
 import org.apache.http.entity.AbstractHttpEntity;
+import org.apache.http.entity.BasicHttpEntity;
 import org.apache.http.entity.ByteArrayEntity;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.DefaultHttpResponseFactory;
@@ -311,6 +305,13 @@ public final class Olingo4AppImpl implements Olingo4App {
         writeContent(edm, new HttpPost(createUri(SegmentType.BATCH.getValue(), null)), uriInfo, data, endpointHttpHeaders, responseHandler);
     }
 
+    @Override
+    public <T> void action(final Edm edm, final String resourcePath, final Map<String, String> endpointHttpHeaders, final Object data, final Olingo4ResponseHandler<T> responseHandler) {
+        final UriInfo uriInfo = parseUri(edm, resourcePath, null, serviceUri);
+
+        writeContent(edm, new HttpPost(createUri(resourcePath, null)), uriInfo, data, endpointHttpHeaders, responseHandler);
+    }
+
     private ContentType getResourceContentType(UriInfo uriInfo) {
         ContentType resourceContentType;
         switch (uriInfo.getKind()) {
@@ -478,6 +479,7 @@ public final class Olingo4AppImpl implements Olingo4App {
                             List<UriResource> listResource = uriInfo.getUriResourceParts();
                             UriResourceKind lastResourceKind = listResource.get(listResource.size() - 1).getKind();
                             switch (lastResourceKind) {
+                            case action:
                             case entitySet:
                                 ClientEntity entity = odataReader.readEntity(result.getEntity().getContent(),
                                                                              ContentType.parse(result.getEntity().getContentType().getValue()));
@@ -511,6 +513,19 @@ public final class Olingo4AppImpl implements Olingo4App {
             List<UriResource> listResource = uriInfo.getUriResourceParts();
             UriResourceKind lastResourceKind = listResource.get(listResource.size() - 1).getKind();
             switch (lastResourceKind) {
+            case action:
+                if (content == null) {
+                    requestStream = new ByteArrayInputStream(new byte[0]);
+                } else if (content instanceof ClientEntity) {
+                    requestStream = odataWriter.writeEntity((ClientEntity)content, getResourceContentType(uriInfo));
+                } else if (content instanceof String) {
+                    httpEntity = new StringEntity((String) content, org.apache.http.entity.ContentType.APPLICATION_JSON);
+                    httpEntity.setChunked(false);
+                    return httpEntity;
+                } else {
+                    throw new ODataException("Unsupported content type: " + content);
+                }
+                break;
             case entitySet:
                 if (content instanceof ClientEntity) {
                     requestStream = odataWriter.writeEntity((ClientEntity)content, getResourceContentType(uriInfo));
diff --git a/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java b/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
index 728cb2d..86ebfc6 100644
--- a/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
+++ b/components/camel-olingo4/camel-olingo4-api/src/test/java/org/apache/camel/component/olingo4/Olingo4AppAPITest.java
@@ -39,11 +39,16 @@ import org.apache.camel.component.olingo4.api.batch.Olingo4BatchRequest;
 import org.apache.camel.component.olingo4.api.batch.Olingo4BatchResponse;
 import org.apache.camel.component.olingo4.api.batch.Operation;
 import org.apache.camel.component.olingo4.api.impl.Olingo4AppImpl;
+import org.apache.http.HttpException;
 import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpResponseInterceptor;
 import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.entity.InputStreamEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.protocol.BasicHttpContext;
 import org.apache.http.protocol.ExecutionContext;
@@ -60,6 +65,8 @@ import org.apache.olingo.client.api.domain.ClientProperty;
 import org.apache.olingo.client.api.domain.ClientServiceDocument;
 import org.apache.olingo.client.api.domain.ClientValue;
 import org.apache.olingo.client.api.serialization.ODataReader;
+import org.apache.olingo.client.api.serialization.ODataSerializerException;
+import org.apache.olingo.client.api.serialization.ODataWriter;
 import org.apache.olingo.client.core.ODataClientFactory;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.edm.Edm;
@@ -98,6 +105,8 @@ public class Olingo4AppAPITest {
     private static final String TEST_AIRPORTS_COMPLEX_PROPERTY = TEST_AIRPORT + "/Location";
     private static final String TEST_AIRPORTS_SIMPLE_PROPERTY_VALUE = TEST_AIRPORTS_SIMPLE_PROPERTY + "/$value";
     private static final String COUNT_OPTION = "/$count";
+    private static final String TEST_UNBOUND_ACTION_RESETDATASOURCE = "ResetDataSource";
+    private static final String TEST_BOUND_ACTION_PEOPLE_SHARETRIP = TEST_PEOPLE +"/Microsoft.OData.Service.Sample.TrippinInMemory.Models.ShareTrip";
 
     private static final String TEST_SERVICE_BASE_URL = "http://services.odata.org/TripPinRESTierService";
     private static final ContentType TEST_FORMAT = ContentType.APPLICATION_JSON;
@@ -405,6 +414,70 @@ public class Olingo4AppAPITest {
         assertEquals(HttpStatusCode.NOT_FOUND.getStatusCode(), responseParts.get(7).getStatusCode());
     }
 
+    @Test
+    public void testUnboundActionRequest() throws Exception {
+        final TestOlingo4ResponseHandler<HttpStatusCode> responseHandler = new TestOlingo4ResponseHandler<>();
+        olingoApp.action(edm, TEST_UNBOUND_ACTION_RESETDATASOURCE, null, null, responseHandler);
+
+        final HttpStatusCode statusCode = responseHandler.await(15, TimeUnit.MINUTES);
+        assertEquals(204, statusCode.getStatusCode());
+    }
+
+    @Test
+    public void testBoundActionRequest() throws Exception {
+        final ClientEntity clientEntity = objFactory.newEntity(null);
+        clientEntity.getProperties().add(objFactory.newPrimitiveProperty("userName", objFactory.newPrimitiveValueBuilder().buildString("scottketchum")));
+        clientEntity.getProperties().add(objFactory.newPrimitiveProperty("tripId", objFactory.newPrimitiveValueBuilder().buildInt32(0)));
+
+        final TestOlingo4ResponseHandler<HttpStatusCode> responseHandler = new TestOlingo4ResponseHandler<>();
+        olingoApp.action(edm, TEST_BOUND_ACTION_PEOPLE_SHARETRIP, null, clientEntity, responseHandler);
+
+        final HttpStatusCode statusCode = responseHandler.await(15, TimeUnit.MINUTES);
+        assertEquals(204, statusCode.getStatusCode());
+    }
+
+
+    // Unfortunately there is no action that returns a client entity. So we fake one
+    @Test
+    public void testBoundActionRequestWithClientEntityResponse() throws Exception {
+        final ODataClient odataClient = ODataClientFactory.getClient();
+        final ODataWriter odataWriter = odataClient.getWriter();
+
+        final HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+        httpClientBuilder.addInterceptorFirst(new HttpResponseInterceptor() {
+            @Override
+            public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
+                if (response.getStatusLine().getStatusCode() == 204) {
+                    try {
+                        response.setEntity(
+                                new InputStreamEntity(
+                                        odataWriter.writeEntity(createEntity(), ContentType.JSON),
+                                        org.apache.http.entity.ContentType.parse(ContentType.JSON.toContentTypeString())));
+                        response.setStatusCode(200);
+                    } catch (ODataSerializerException e) {
+                        throw new IOException(e);
+                    }
+                }
+            }
+        });
+        final Olingo4App olingoApp = new Olingo4AppImpl(getRealServiceUrl(TEST_SERVICE_BASE_URL), httpClientBuilder);
+        olingoApp.setContentType(TEST_FORMAT_STRING);
+
+        final TestOlingo4ResponseHandler<Edm> responseHandler = new TestOlingo4ResponseHandler<>();
+        olingoApp.read(null, Constants.METADATA, null, null, responseHandler);
+        final Edm edm = responseHandler.await();
+
+        final ClientEntity clientEntity = objFactory.newEntity(null);
+        clientEntity.getProperties().add(objFactory.newPrimitiveProperty("userName", objFactory.newPrimitiveValueBuilder().buildString("scottketchum")));
+        clientEntity.getProperties().add(objFactory.newPrimitiveProperty("tripId", objFactory.newPrimitiveValueBuilder().buildInt32(0)));
+
+        final TestOlingo4ResponseHandler<ClientEntity> actionResponseHandler = new TestOlingo4ResponseHandler<>();
+        olingoApp.action(edm, TEST_BOUND_ACTION_PEOPLE_SHARETRIP, null, clientEntity, actionResponseHandler);
+
+        final ClientEntity result = actionResponseHandler.await(15, TimeUnit.MINUTES);
+        assertEquals("lewisblack", result.getProperty("UserName").getValue().toString());
+    }
+
     private ClientEntity createEntity() {
         ClientEntity clientEntity = objFactory.newEntity(null);
 
diff --git a/components/camel-olingo4/camel-olingo4-component/pom.xml b/components/camel-olingo4/camel-olingo4-component/pom.xml
index adcd6af..0f14877 100644
--- a/components/camel-olingo4/camel-olingo4-component/pom.xml
+++ b/components/camel-olingo4/camel-olingo4-component/pom.xml
@@ -149,6 +149,7 @@
                                         <nullableOption>endpointHttpHeaders</nullableOption>
                                         <nullableOption>edm</nullableOption>
                                         <nullableOption>responseHandler</nullableOption>
+                                        <nullableOption>data</nullableOption>
                                     </nullableOptions>
                                 </api>
                             </apis>
diff --git a/components/camel-olingo4/camel-olingo4-component/src/signatures/olingo-api-signature.txt b/components/camel-olingo4/camel-olingo4-component/src/signatures/olingo-api-signature.txt
index fb941e6..66a2110 100644
--- a/components/camel-olingo4/camel-olingo4-component/src/signatures/olingo-api-signature.txt
+++ b/components/camel-olingo4/camel-olingo4-component/src/signatures/olingo-api-signature.txt
@@ -6,3 +6,4 @@ void update(org.apache.olingo.commons.api.edm.Edm edm, String resourcePath, java
 void patch(org.apache.olingo.commons.api.edm.Edm edm, String resourcePath, java.util.Map<String, String> endpointHttpHeaders, Object data, org.apache.camel.component.olingo4.api.Olingo4ResponseHandler responseHandler);
 void merge(org.apache.olingo.commons.api.edm.Edm edm, String resourcePath, java.util.Map<String, String> endpointHttpHeaders, Object data, org.apache.camel.component.olingo4.api.Olingo4ResponseHandler responseHandler);
 void batch(org.apache.olingo.commons.api.edm.Edm edm, java.util.Map<String, String> endpointHttpHeaders, Object data, org.apache.camel.component.olingo4.api.Olingo4ResponseHandler responseHandler);
+void action(org.apache.olingo.commons.api.edm.Edm edm, String resourcePath, java.util.Map<String, String> endpointHttpHeaders, Object data, org.apache.camel.component.olingo4.api.Olingo4ResponseHandler responseHandler);
diff --git a/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentProducerTest.java b/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentProducerTest.java
index 2493b94..13a1de6 100644
--- a/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentProducerTest.java
+++ b/components/camel-olingo4/camel-olingo4-component/src/test/java/org/apache/camel/component/olingo4/Olingo4ComponentProducerTest.java
@@ -273,6 +273,22 @@ public class Olingo4ComponentProducerTest extends AbstractOlingo4TestSupport {
         LOG.info("Read deleted entity error: {}", error.getMessage());
     }
 
+    @Test
+    public void testUnboundActionRequest() throws Exception {
+        final HttpStatusCode status = requestBody("direct:unbound-action-ResetDataSource", null);
+        assertEquals(204, status.getStatusCode());
+    }
+
+    @Test
+    public void testBoundActionRequest() throws Exception {
+        final ClientEntity clientEntity = objFactory.newEntity(null);
+        clientEntity.getProperties().add(objFactory.newPrimitiveProperty("userName", objFactory.newPrimitiveValueBuilder().buildString("scottketchum")));
+        clientEntity.getProperties().add(objFactory.newPrimitiveProperty("tripId", objFactory.newPrimitiveValueBuilder().buildInt32(0)));
+
+        final HttpStatusCode status = requestBody("direct:bound-action-people", clientEntity);
+        assertEquals(204, status.getStatusCode());
+    }
+
     @SuppressWarnings("unchecked")
     @Test
     public void testEndpointHttpHeaders() throws Exception {
@@ -425,6 +441,11 @@ public class Olingo4ComponentProducerTest extends AbstractOlingo4TestSupport {
                 from("direct:read-people-nofilterseen").to("olingo4://read/" + PEOPLE).to("mock:producer-noalreadyseen");
 
                 from("direct:read-people-filterseen").to("olingo4://read/" + PEOPLE + "?filterAlreadySeen=true").to("mock:producer-alreadyseen");
+
+                // test routes action's
+                from("direct:unbound-action-ResetDataSource").to("olingo4://action/ResetDataSource");
+
+                from("direct:bound-action-people").to("olingo4://action/" + TEST_PEOPLE + "/Microsoft.OData.Service.Sample.TrippinInMemory.Models.ShareTrip");
             }
         };
     }