CAMEL-10743: Added support for rawPayload parameter in Salesforce REST APIs
Project: http://git-wip-us.apache.org/repos/asf/camel/repo Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/84625b80 Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/84625b80 Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/84625b80 Branch: refs/heads/master Commit: 84625b800f699bce15dc0bfeb8eac7e5ffd7252f Parents: ecd132a Author: Dhiraj Bokde <dhira...@yahoo.com> Authored: Thu Aug 3 00:38:21 2017 -0700 Committer: Dhiraj Bokde <dhira...@yahoo.com> Committed: Thu Aug 3 00:43:53 2017 -0700 ---------------------------------------------------------------------- .../processor/AbstractRestProcessor.java | 6 + .../internal/processor/JsonRestProcessor.java | 6 +- .../internal/processor/XmlRestProcessor.java | 3 +- .../component/salesforce/RawPayloadTest.java | 240 +++++++++++++++++++ .../salesforce/RestApiIntegrationTest.java | 1 + 5 files changed, 252 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/camel/blob/84625b80/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java index 758cc57..74be887 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java @@ -810,6 +810,12 @@ public abstract class AbstractRestProcessor extends AbstractSalesforceProcessor protected abstract InputStream getRequestStream(Object object) throws SalesforceException; private void setResponseClass(Exchange exchange, String sObjectName) throws SalesforceException { + + // nothing to do if using rawPayload + if (rawPayload) { + return; + } + Class<?> sObjectClass; if (sObjectName != null) { http://git-wip-us.apache.org/repos/asf/camel/blob/84625b80/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java index b361fb3..777338a 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java @@ -183,13 +183,13 @@ public class JsonRestProcessor extends AbstractRestProcessor { } } else if (responseEntity != null) { // do we need to un-marshal a response - Object response = null; + final Object response; Class<?> responseClass = exchange.getProperty(RESPONSE_CLASS, Class.class); - if (responseClass != null) { + if (!rawPayload && responseClass != null) { response = objectMapper.readValue(responseEntity, responseClass); } else { TypeReference<?> responseType = exchange.getProperty(RESPONSE_TYPE, TypeReference.class); - if (responseType != null) { + if (!rawPayload && responseType != null) { response = objectMapper.readValue(responseEntity, responseType); } else { // return the response as a stream, for getBlobField http://git-wip-us.apache.org/repos/asf/camel/blob/84625b80/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java index 6650ff0..3bcba03 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java +++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/XmlRestProcessor.java @@ -33,6 +33,7 @@ import com.thoughtworks.xstream.io.xml.CompactWriter; import com.thoughtworks.xstream.io.xml.XppDriver; import com.thoughtworks.xstream.mapper.CachingMapper; import com.thoughtworks.xstream.mapper.CannotResolveClassException; + import org.apache.camel.AsyncCallback; import org.apache.camel.Exchange; import org.apache.camel.Message; @@ -236,7 +237,7 @@ public class XmlRestProcessor extends AbstractRestProcessor { // do we need to un-marshal a response final Class<?> responseClass = exchange.getProperty(RESPONSE_CLASS, Class.class); Object response; - if (responseClass != null) { + if (!rawPayload && responseClass != null) { // its ok to call this multiple times, as xstream ignores duplicate calls localXStream.processAnnotations(responseClass); final String responseAlias = exchange.getProperty(RESPONSE_ALIAS, String.class); http://git-wip-us.apache.org/repos/asf/camel/blob/84625b80/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawPayloadTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawPayloadTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawPayloadTest.java new file mode 100644 index 0000000..7d6941c --- /dev/null +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawPayloadTest.java @@ -0,0 +1,240 @@ +/** + * 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.camel.component.salesforce; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.camel.builder.RouteBuilder; +import org.eclipse.jetty.http.HttpHeader; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.Dispatcher; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; + +@Category(Standalone.class) +@RunWith(Parameterized.class) +public class RawPayloadTest extends AbstractSalesforceTestBase { + + private static final String OAUTH2_TOKEN_PATH = "/services/oauth2/token"; + private static final String XML_RESPONSE = "<response/>"; + private static final String JSON_RESPONSE = "{ \"response\" : \"mock\" }"; + + private static HttpUrl loginUrl; + private static MockWebServer server; + + @Parameter + public static String format; + + @Parameter(1) + public static String endpointUri; + + private static String lastFormat; + private static String expectedResponse; + private static String requestBody; + private static Map<String, Object> headers; + + @Override + protected void createComponent() throws Exception { + + // create the component + SalesforceComponent component = new SalesforceComponent(); + final SalesforceEndpointConfig config = new SalesforceEndpointConfig(); + config.setApiVersion(System.getProperty("apiVersion", salesforceApiVersionToUse())); + component.setConfig(config); + + SalesforceLoginConfig dummyLoginConfig = new SalesforceLoginConfig(); + dummyLoginConfig.setClientId("ignored"); + dummyLoginConfig.setClientSecret("ignored"); + dummyLoginConfig.setRefreshToken("ignored"); + dummyLoginConfig.setLoginUrl(loginUrl.toString()); + component.setLoginConfig(dummyLoginConfig); + + // add it to context + context().addComponent("salesforce", component); + } + + @AfterClass + public static void shutDownServer() throws IOException { + // shutdown mock server + if (server != null) { + server.shutdown(); + } + } + + @BeforeClass + public static void startServer() throws IOException { + + // create mock server + server = new MockWebServer(); + + server.setDispatcher(new Dispatcher() { + @Override + public MockResponse dispatch(RecordedRequest recordedRequest) throws InterruptedException { + if (recordedRequest.getPath().equals(OAUTH2_TOKEN_PATH)) { + return new MockResponse() + .setResponseCode(200) + .setBody("{ \"access_token\": \"mock_token\", \"instance_url\": \"" + loginUrl + "\"}"); + } else { + return new MockResponse() + .setResponseCode(200) + .setHeader(HttpHeader.CONTENT_TYPE.toString(), recordedRequest.getHeader(HttpHeader.CONTENT_TYPE.toString())) + .setBody("XML".equals(format) ? XML_RESPONSE : JSON_RESPONSE); + } + } + }); + + // start the server + server.start(); + loginUrl = server.url(""); + } + + @Before + public void setupRequestResponse() { + if (!format.equals(lastFormat)) { + // expected response and test request + final boolean isXml = "XML".equals(format); + expectedResponse = isXml ? XML_RESPONSE : JSON_RESPONSE; + if (isXml) { + requestBody = "<request/>"; + } else { + requestBody = "{ \"request\" : \"mock\" }"; + } + headers = new HashMap<>(); + headers.put("sObjectId", "mockId"); + headers.put("sObjectIdValue", "mockIdValue"); + headers.put("id", "mockId"); + headers.put(SalesforceEndpointConfig.APEX_QUERY_PARAM_PREFIX + "id", "mockId"); + + lastFormat = format; + } + } + + @Test + public void testRestApi() throws Exception { + final String responseBody = template().requestBodyAndHeaders(endpointUri, requestBody, headers, String.class); + assertNotNull("Null response for endpoint " + endpointUri, responseBody); + assertEquals("Unexpected response for endpoint " + endpointUri, expectedResponse, responseBody); + } + + @Override + protected RouteBuilder doCreateRouteBuilder() throws Exception { + + // create test route + return new RouteBuilder() { + @Override + public void configure() { + + // testGetVersion + from("direct:getVersions").to("salesforce:getVersions?rawPayload=true&format=" + format); + + // testGetResources + from("direct:getResources").to("salesforce:getResources?rawPayload=true&format=" + format); + + // testGetGlobalObjects + from("direct:getGlobalObjects").to("salesforce:getGlobalObjects?rawPayload=true&format=" + format); + + // testGetBasicInfo + from("direct:getBasicInfo").to("salesforce:getBasicInfo?sObjectName=Merchandise__c&rawPayload=true&format=" + format); + + // testGetDescription + from("direct:getDescription") + .to("salesforce:getDescription?sObjectName=Merchandise__c&rawPayload=true&format=" + format); + + // testGetSObject + from("direct:getSObject") + .to("salesforce:getSObject?sObjectName=Merchandise__c&sObjectFields=Description__c,Price__c&rawPayload=true&format=" + + format); + + // testCreateSObject + from("direct:createSObject").to("salesforce:createSObject?sObjectName=Merchandise__c&rawPayload=true&format=" + format); + + // testUpdateSObject + from("direct:updateSObject").to("salesforce:updateSObject?sObjectName=Merchandise__c&rawPayload=true&format=" + format); + + // testDeleteSObject + from("direct:deleteSObject").to("salesforce:deleteSObject?sObjectName=Merchandise__c&rawPayload=true&format=" + format); + + // testGetSObjectWithId + from("direct:getSObjectWithId") + .to("salesforce:getSObjectWithId?sObjectName=Line_Item__c&sObjectIdName=Name&rawPayload=true&format=" + format); + + // testUpsertSObject + from("direct:upsertSObject") + .to("salesforce:upsertSObject?sObjectName=Line_Item__c&sObjectIdName=Name&rawPayload=true&format=" + format); + + // testDeleteSObjectWithId + from("direct:deleteSObjectWithId") + .to("salesforce:deleteSObjectWithId?sObjectName=Line_Item__c&sObjectIdName=Name&rawPayload=true&format=" + format); + + // testGetBlobField + from("direct:getBlobField") + .to("salesforce:getBlobField?sObjectName=Document&sObjectBlobFieldName=Body&rawPayload=true&format=" + format); + + // testQuery + from("direct:query").to("salesforce:query?sObjectQuery=SELECT name from Line_Item__c&rawPayload=true&format=" + format); + + // testQueryAll + from("direct:queryAll") + .to("salesforce:queryAll?sObjectQuery=SELECT name from Line_Item__c&rawPayload=true&format=" + format); + + // testSearch + from("direct:search").to("salesforce:search?sObjectSearch=FIND {Wee}&rawPayload=true&format=" + format); + + // testApexCall + from("direct:apexCallGet") + .to("salesforce:apexCall?apexMethod=GET&apexUrl=Merchandise/{id}&sObjectName=Merchandise__c&rawPayload=true&format=" + + format); + + from("direct:apexCallGetWithId").to("salesforce:apexCall/Merchandise/?apexMethod=GET&id=dummyId&rawPayload=true&format=" + + format); + + from("direct:apexCallPatch").to("salesforce:apexCall/Merchandise/?rawPayload=true&format=" + format + + "&apexMethod=PATCH"); + } + }; + } + + @Parameters(name = "format = {0}, endpoint = {1}") + public static List<String[]> parameters() { + final String[] endpoints = {"direct:getVersions", "direct:getResources", "direct:getGlobalObjects", + "direct:getBasicInfo", "direct:getDescription", "direct:getSObject", "direct:createSObject", + "direct:updateSObject", "direct:deleteSObject", "direct:getSObjectWithId", "direct:upsertSObject", + "direct:deleteSObjectWithId", "direct:getBlobField", "direct:query", "direct:queryAll", + "direct:search", "direct:apexCallGet", "direct:apexCallGetWithId", "direct:apexCallPatch"}; + + final String[] formats = {"XML", "JSON"}; + + return Stream.of(formats).flatMap(f -> Stream.of(endpoints).map(e -> new String[]{f, e})) + .collect(Collectors.toList()); + } +} http://git-wip-us.apache.org/repos/asf/camel/blob/84625b80/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java ---------------------------------------------------------------------- diff --git a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java index ccd09d9..13485ce 100644 --- a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java +++ b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java @@ -134,6 +134,7 @@ public class RestApiIntegrationTest extends AbstractSalesforceTestBase { merchandise.setName("Test Merchandise"); merchandise.setPrice__c(10.0); merchandise.setTotal_Inventory__c(100.0); + merchandise.setDescription__c("Test Merchandise!"); final CreateSObjectResult result = template().requestBody("salesforce:createSObject", merchandise, CreateSObjectResult.class);