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 2020/12/09 17:08:08 UTC
[camel] branch master updated: [CAMEL-15757] Add rawPayload support
on camel-salesforce composite (#4514)
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
The following commit(s) were added to refs/heads/master by this push:
new f4bd41a [CAMEL-15757] Add rawPayload support on camel-salesforce composite (#4514)
f4bd41a is described below
commit f4bd41a360fc29b0472a8936e041ddf67cbb7edc
Author: Jean-Baptiste Onofré <jb...@apache.org>
AuthorDate: Wed Dec 9 18:07:44 2020 +0100
[CAMEL-15757] Add rawPayload support on camel-salesforce composite (#4514)
---
.../camel/catalog/docs/salesforce-component.adoc | 6 ++-
.../salesforce/SalesforceComponentConfigurer.java | 6 +++
.../salesforce/SalesforceEndpointConfigurer.java | 6 +++
.../salesforce/SalesforceEndpointUriFactory.java | 3 +-
.../camel/component/salesforce/salesforce.json | 2 +
.../src/main/docs/salesforce-component.adoc | 35 ++++++++++++--
.../salesforce/SalesforceEndpointConfig.java | 17 ++++++-
.../internal/client/CompositeApiClient.java | 6 +++
.../internal/client/DefaultCompositeApiClient.java | 35 ++++++++++++++
.../internal/processor/CompositeApiProcessor.java | 56 +++++++++++++++++++++-
.../camel/component/salesforce/RawPayloadTest.java | 11 ++++-
.../dsl/SalesforceComponentBuilderFactory.java | 13 +++++
.../dsl/SalesforceEndpointBuilderFactory.java | 35 ++++++++++++++
.../modules/ROOT/pages/salesforce-component.adoc | 6 ++-
14 files changed, 224 insertions(+), 13 deletions(-)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/salesforce-component.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/salesforce-component.adoc
index 6747737..7d048fe 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/salesforce-component.adoc
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/salesforce-component.adoc
@@ -656,7 +656,7 @@ for details on how to generate the DTO.
// component options: START
-The Salesforce component supports 73 options, which are listed below.
+The Salesforce component supports 74 options, which are listed below.
@@ -669,6 +669,7 @@ The Salesforce component supports 73 options, which are listed below.
| *apiVersion* (common) | Salesforce API version. | 50.0 | String
| *backoffIncrement* (common) | Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto-reconnect. | 1000 | long
| *batchId* (common) | Bulk API Batch ID | | String
+| *compositeMethod* (common) | Composite (raw) method. | | String
| *contentType* (common) | Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV. There are 6 enums and the value can be one of: XML, CSV, JSON, ZIP_XML, ZIP_CSV, ZIP_JSON | | ContentType
| *defaultReplayId* (common) | Default replayId setting if no value is found in initialReplayIdMap | -1 | Long
| *format* (common) | Payload format to use for Salesforce API calls, either JSON or XML, defaults to JSON. There are 2 enums and the value can be one of: JSON, XML | | PayloadFormat
@@ -768,7 +769,7 @@ with the following path and query parameters:
|===
-=== Query Parameters (44 parameters):
+=== Query Parameters (45 parameters):
[width="100%",cols="2,5,^1,2",options="header"]
@@ -780,6 +781,7 @@ with the following path and query parameters:
| *apiVersion* (common) | Salesforce API version. | 50.0 | String
| *backoffIncrement* (common) | Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto-reconnect. | 1000 | long
| *batchId* (common) | Bulk API Batch ID | | String
+| *compositeMethod* (common) | Composite (raw) method. | | String
| *contentType* (common) | Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV. There are 6 enums and the value can be one of: XML, CSV, JSON, ZIP_XML, ZIP_CSV, ZIP_JSON | | ContentType
| *defaultReplayId* (common) | Default replayId setting if no value is found in initialReplayIdMap | -1 | Long
| *format* (common) | Payload format to use for Salesforce API calls, either JSON or XML, defaults to JSON. There are 2 enums and the value can be one of: JSON, XML | | PayloadFormat
diff --git a/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceComponentConfigurer.java b/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceComponentConfigurer.java
index c912d1d..440be38 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceComponentConfigurer.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceComponentConfigurer.java
@@ -50,6 +50,8 @@ public class SalesforceComponentConfigurer extends PropertyConfigurerSupport imp
case "clientId": target.setClientId(property(camelContext, java.lang.String.class, value)); return true;
case "clientsecret":
case "clientSecret": target.setClientSecret(property(camelContext, java.lang.String.class, value)); return true;
+ case "compositemethod":
+ case "compositeMethod": getOrCreateConfig(target).setCompositeMethod(property(camelContext, java.lang.String.class, value)); return true;
case "config": target.setConfig(property(camelContext, org.apache.camel.component.salesforce.SalesforceEndpointConfig.class, value)); return true;
case "contenttype":
case "contentType": getOrCreateConfig(target).setContentType(property(camelContext, org.apache.camel.component.salesforce.api.dto.bulk.ContentType.class, value)); return true;
@@ -197,6 +199,8 @@ public class SalesforceComponentConfigurer extends PropertyConfigurerSupport imp
case "clientId": return java.lang.String.class;
case "clientsecret":
case "clientSecret": return java.lang.String.class;
+ case "compositemethod":
+ case "compositeMethod": return java.lang.String.class;
case "config": return org.apache.camel.component.salesforce.SalesforceEndpointConfig.class;
case "contenttype":
case "contentType": return org.apache.camel.component.salesforce.api.dto.bulk.ContentType.class;
@@ -345,6 +349,8 @@ public class SalesforceComponentConfigurer extends PropertyConfigurerSupport imp
case "clientId": return target.getClientId();
case "clientsecret":
case "clientSecret": return target.getClientSecret();
+ case "compositemethod":
+ case "compositeMethod": return getOrCreateConfig(target).getCompositeMethod();
case "config": return target.getConfig();
case "contenttype":
case "contentType": return getOrCreateConfig(target).getContentType();
diff --git a/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointConfigurer.java b/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointConfigurer.java
index 92c3e28..5487a30 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointConfigurer.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointConfigurer.java
@@ -35,6 +35,8 @@ public class SalesforceEndpointConfigurer extends PropertyConfigurerSupport impl
case "batchId": target.getConfiguration().setBatchId(property(camelContext, java.lang.String.class, value)); return true;
case "bridgeerrorhandler":
case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
+ case "compositemethod":
+ case "compositeMethod": target.getConfiguration().setCompositeMethod(property(camelContext, java.lang.String.class, value)); return true;
case "contenttype":
case "contentType": target.getConfiguration().setContentType(property(camelContext, org.apache.camel.component.salesforce.api.dto.bulk.ContentType.class, value)); return true;
case "defaultreplayid":
@@ -127,6 +129,8 @@ public class SalesforceEndpointConfigurer extends PropertyConfigurerSupport impl
case "batchId": return java.lang.String.class;
case "bridgeerrorhandler":
case "bridgeErrorHandler": return boolean.class;
+ case "compositemethod":
+ case "compositeMethod": return java.lang.String.class;
case "contenttype":
case "contentType": return org.apache.camel.component.salesforce.api.dto.bulk.ContentType.class;
case "defaultreplayid":
@@ -220,6 +224,8 @@ public class SalesforceEndpointConfigurer extends PropertyConfigurerSupport impl
case "batchId": return target.getConfiguration().getBatchId();
case "bridgeerrorhandler":
case "bridgeErrorHandler": return target.isBridgeErrorHandler();
+ case "compositemethod":
+ case "compositeMethod": return target.getConfiguration().getCompositeMethod();
case "contenttype":
case "contentType": return target.getConfiguration().getContentType();
case "defaultreplayid":
diff --git a/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointUriFactory.java b/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointUriFactory.java
index 475d102..5d39399 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointUriFactory.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/generated/java/org/apache/camel/component/salesforce/SalesforceEndpointUriFactory.java
@@ -20,7 +20,7 @@ public class SalesforceEndpointUriFactory extends org.apache.camel.support.compo
private static final Set<String> PROPERTY_NAMES;
private static final Set<String> SECRET_PROPERTY_NAMES;
static {
- Set<String> props = new HashSet<>(46);
+ Set<String> props = new HashSet<>(47);
props.add("initialReplayIdMap");
props.add("notifyForOperations");
props.add("synchronous");
@@ -30,6 +30,7 @@ public class SalesforceEndpointUriFactory extends org.apache.camel.support.compo
props.add("notifyForOperationUndelete");
props.add("sObjectClass");
props.add("apexUrl");
+ props.add("compositeMethod");
props.add("apexMethod");
props.add("updateTopic");
props.add("apiVersion");
diff --git a/components/camel-salesforce/camel-salesforce-component/src/generated/resources/org/apache/camel/component/salesforce/salesforce.json b/components/camel-salesforce/camel-salesforce-component/src/generated/resources/org/apache/camel/component/salesforce/salesforce.json
index 3963932..0374e20 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/generated/resources/org/apache/camel/component/salesforce/salesforce.json
+++ b/components/camel-salesforce/camel-salesforce-component/src/generated/resources/org/apache/camel/component/salesforce/salesforce.json
@@ -29,6 +29,7 @@
"apiVersion": { "kind": "property", "displayName": "Api Version", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "50.0", "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Salesforce API version." },
"backoffIncrement": { "kind": "property", "displayName": "Backoff Increment", "group": "common", "label": "", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto- [...]
"batchId": { "kind": "property", "displayName": "Batch Id", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Bulk API Batch ID" },
+ "compositeMethod": { "kind": "property", "displayName": "Composite Method", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Composite (raw) method." },
"contentType": { "kind": "property", "displayName": "Content Type", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.salesforce.api.dto.bulk.ContentType", "enum": [ "XML", "CSV", "JSON", "ZIP_XML", "ZIP_CSV", "ZIP_JSON" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Bulk API co [...]
"defaultReplayId": { "kind": "property", "displayName": "Default Replay Id", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "-1", "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Default replayId setting if no value is found in initialReplayIdMap" },
"format": { "kind": "property", "displayName": "Format", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.salesforce.internal.PayloadFormat", "enum": [ "JSON", "XML" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "config", "description": "Payload format to use for Salesforce API calls, either JSON or XM [...]
@@ -106,6 +107,7 @@
"apiVersion": { "kind": "parameter", "displayName": "Api Version", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "50.0", "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Salesforce API version." },
"backoffIncrement": { "kind": "parameter", "displayName": "Backoff Increment", "group": "common", "label": "", "required": false, "type": "duration", "javaType": "long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "1000", "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Backoff interval increment for Streaming connection restart attempts for failures beyond Come [...]
"batchId": { "kind": "parameter", "displayName": "Batch Id", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Bulk API Batch ID" },
+ "compositeMethod": { "kind": "parameter", "displayName": "Composite Method", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Composite (raw) method." },
"contentType": { "kind": "parameter", "displayName": "Content Type", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.salesforce.api.dto.bulk.ContentType", "enum": [ "XML", "CSV", "JSON", "ZIP_XML", "ZIP_CSV", "ZIP_JSON" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Bul [...]
"defaultReplayId": { "kind": "parameter", "displayName": "Default Replay Id", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Long", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "-1", "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Default replayId setting if no value is found in initialReplayIdMap" },
"format": { "kind": "parameter", "displayName": "Format", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.salesforce.internal.PayloadFormat", "enum": [ "JSON", "XML" ], "deprecated": false, "autowired": false, "secret": false, "configurationClass": "org.apache.camel.component.salesforce.SalesforceEndpointConfig", "configurationField": "configuration", "description": "Payload format to use for Salesforce API calls, either JS [...]
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
index 6747737..05e92bb 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/docs/salesforce-component.adoc
@@ -155,7 +155,7 @@ results) using result link returned from the 'query' API
* recent - fetching recent items
* approval - submit a record or records (batch) for approval process
* approvals - fetch a list of all approval processes
-* composite - submit up to 25 possibly related REST requests and receive individual responses
+* composite - submit up to 25 possibly related REST requests and receive individual responses. It's also possible to use "raw" composite without limitation.
* composite-tree - create up to 200 records with parent-child relationships (up to 5 levels) in one go
* composite-batch - submit a composition of requests in batch
* queryAll - Runs a SOQL query. It returns the results that are deleted because of a merge or delete. Also returns the information about archived Task and Event records.
@@ -602,6 +602,33 @@ final Map<String, ?> accountUpdateBody = accountUpdateResult.getBody();
final SObjectCompositeResult contactCreationResult = results.stream().filter(r -> "JunctionRecord".equals(r.getReferenceId())).findFirst().get()
----
+== Using "raw" Salesforce composite
+
+It's possible to directly call Salesforce composite by preparing the Salesforce JSON request in the route thanks to the `rawPayload` option.
+
+For instance, you can have the following route:
+
+----
+from("timer:fire?period=2000").setBody(constant("{\n" +
+ " \"allOrNone\" : true,\n" +
+ " \"records\" : [ { \n" +
+ " \"attributes\" : {\"type\" : \"FOO\"},\n" +
+ " \"Name\" : \"123456789\",\n" +
+ " \"FOO\" : \"XXXX\",\n" +
+ " \"ACCOUNT\" : 2100.0\n" +
+ " \"ExternalID\" : \"EXTERNAL\"\n"
+ " }]\n" +
+ "}")
+ .to("salesforce:composite?rawPayload=true&sObjectName=FOO&sObjectIdName=EXTERNAL&compositeMethod=PATCH")
+ .log("${body}");
+----
+
+The route directly creates the body as JSON and directly submit to salesforce endpoint using `rawPayload=true` option.
+
+With this approach, you have the complete control on the Salesforce request.
+
+The `compositeMethod` option allows you to define the Salesforce client method style (PATCH, PUT, POST, ...).
+
== Sending null values to salesforce
By default, SObject fields with null values are not sent to salesforce. In order to
@@ -656,7 +683,7 @@ for details on how to generate the DTO.
// component options: START
-The Salesforce component supports 73 options, which are listed below.
+The Salesforce component supports 74 options, which are listed below.
@@ -669,6 +696,7 @@ The Salesforce component supports 73 options, which are listed below.
| *apiVersion* (common) | Salesforce API version. | 50.0 | String
| *backoffIncrement* (common) | Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto-reconnect. | 1000 | long
| *batchId* (common) | Bulk API Batch ID | | String
+| *compositeMethod* (common) | Composite (raw) method. | | String
| *contentType* (common) | Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV. There are 6 enums and the value can be one of: XML, CSV, JSON, ZIP_XML, ZIP_CSV, ZIP_JSON | | ContentType
| *defaultReplayId* (common) | Default replayId setting if no value is found in initialReplayIdMap | -1 | Long
| *format* (common) | Payload format to use for Salesforce API calls, either JSON or XML, defaults to JSON. There are 2 enums and the value can be one of: JSON, XML | | PayloadFormat
@@ -768,7 +796,7 @@ with the following path and query parameters:
|===
-=== Query Parameters (44 parameters):
+=== Query Parameters (45 parameters):
[width="100%",cols="2,5,^1,2",options="header"]
@@ -780,6 +808,7 @@ with the following path and query parameters:
| *apiVersion* (common) | Salesforce API version. | 50.0 | String
| *backoffIncrement* (common) | Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto-reconnect. | 1000 | long
| *batchId* (common) | Bulk API Batch ID | | String
+| *compositeMethod* (common) | Composite (raw) method. | | String
| *contentType* (common) | Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV. There are 6 enums and the value can be one of: XML, CSV, JSON, ZIP_XML, ZIP_CSV, ZIP_JSON | | ContentType
| *defaultReplayId* (common) | Default replayId setting if no value is found in initialReplayIdMap | -1 | Long
| *format* (common) | Payload format to use for Salesforce API calls, either JSON or XML, defaults to JSON. There are 2 enums and the value can be one of: JSON, XML | | PayloadFormat
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
index b3a7578..49603f2 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpointConfig.java
@@ -61,6 +61,7 @@ public class SalesforceEndpointConfig implements Cloneable {
public static final String SOBJECT_SEARCH = "sObjectSearch";
public static final String APEX_METHOD = "apexMethod";
public static final String APEX_URL = "apexUrl";
+ public static final String COMPOSITE_METHOD = "compositeMethod";
public static final String LIMIT = "limit";
// prefix for parameters in headers
@@ -125,7 +126,9 @@ public class SalesforceEndpointConfig implements Cloneable {
private String sObjectSearch;
@UriParam
private String apexMethod;
- @UriParam
+ @UriParam(label = "producer")
+ private String compositeMethod;
+ @UriParam(label = "producer")
private String apexUrl;
@UriParam
private Map<String, Object> apexQueryParams;
@@ -377,6 +380,17 @@ public class SalesforceEndpointConfig implements Cloneable {
this.apexQueryParams = apexQueryParams;
}
+ public String getCompositeMethod() {
+ return compositeMethod;
+ }
+
+ /**
+ * Composite (raw) method.
+ */
+ public void setCompositeMethod(String compositeMethod) {
+ this.compositeMethod = compositeMethod;
+ }
+
public ApprovalRequest getApproval() {
return approval;
}
@@ -616,6 +630,7 @@ public class SalesforceEndpointConfig implements Cloneable {
valueMap.put(SOBJECT_SEARCH, sObjectSearch);
valueMap.put(APEX_METHOD, apexMethod);
valueMap.put(APEX_URL, apexUrl);
+ valueMap.put(COMPOSITE_METHOD, compositeMethod);
valueMap.put(LIMIT, limit);
valueMap.put(APPROVAL, approval);
// apexQueryParams are handled explicitly in AbstractRestProcessor
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/CompositeApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/CompositeApiClient.java
index 3ca7a18..4621bf9 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/CompositeApiClient.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/CompositeApiClient.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.salesforce.internal.client;
+import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -42,6 +43,11 @@ public interface CompositeApiClient {
void onResponse(Optional<T> body, Map<String, String> headers, SalesforceException exception);
}
+ void submitCompositeRaw(
+ InputStream raw, Map<String, List<String>> headers, ResponseCallback<InputStream> callback,
+ String sObjectName, String extId, String method)
+ throws SalesforceException;
+
void submitComposite(
SObjectComposite composite, Map<String, List<String>> headers, ResponseCallback<SObjectCompositeResponse> callback)
throws SalesforceException;
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultCompositeApiClient.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultCompositeApiClient.java
index b040875f..530f0ec 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultCompositeApiClient.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultCompositeApiClient.java
@@ -93,6 +93,33 @@ public class DefaultCompositeApiClient extends AbstractClientBase implements Com
xStreamCompositeTree.alias("SObjectTreeResponse", SObjectTreeResponse.class);
}
+ public void submitCompositeRaw(
+ final InputStream raw, final Map<String, List<String>> headers,
+ final ResponseCallback<InputStream> callback,
+ final String sObjectName, final String extId, String compositeMethod)
+ throws SalesforceException {
+ checkCompositeFormat(format, SObjectComposite.REQUIRED_PAYLOAD_FORMAT);
+
+ final String url = String.format("%s%s/%s/%s/%s", versionUrl(), "composite", "sobjects", sObjectName, extId);
+
+ Request request;
+ if (compositeMethod != null) {
+ request = createRequest(compositeMethod, url, headers);
+ } else {
+ request = createRequest(HttpMethod.POST, url, headers);
+ }
+
+ final ContentProvider content = new InputStreamContentProvider(raw);
+ request.content(content);
+
+ doHttpRequest(request, new ClientResponseCallback() {
+ @Override
+ public void onResponse(InputStream response, Map<String, String> headers, SalesforceException ex) {
+ callback.onResponse(Optional.of(response), headers, ex);
+ }
+ });
+ }
+
@Override
public void submitComposite(
final SObjectComposite composite, final Map<String, List<String>> headers,
@@ -152,9 +179,17 @@ public class DefaultCompositeApiClient extends AbstractClientBase implements Com
responseHeaders, exception));
}
+ Request createRequest(final String method, final String url, final Map<String, List<String>> headers) {
+ final Request request = getRequest(method, url, headers);
+ return populateRequest(request);
+ }
+
Request createRequest(final HttpMethod method, final String url, final Map<String, List<String>> headers) {
final Request request = getRequest(method, url, headers);
+ return populateRequest(request);
+ }
+ private Request populateRequest(Request request) {
// setup authorization
setAccessToken(request);
diff --git a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeApiProcessor.java b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeApiProcessor.java
index 1d6f00c..1493a47 100644
--- a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeApiProcessor.java
+++ b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeApiProcessor.java
@@ -16,6 +16,7 @@
*/
package org.apache.camel.component.salesforce.internal.processor;
+import java.io.InputStream;
import java.util.EnumSet;
import java.util.Map;
import java.util.Optional;
@@ -89,8 +90,13 @@ public final class CompositeApiProcessor extends AbstractSalesforceProcessor {
return processInternal(SObjectBatch.class, exchange, compositeClient::submitCompositeBatch,
this::processCompositeBatchResponse, callback);
case COMPOSITE:
- return processInternal(SObjectComposite.class, exchange, compositeClient::submitComposite,
- this::processCompositeResponse, callback);
+ if (rawPayload) {
+ return processRaw(exchange, compositeClient,
+ this::processCompositeResponseRaw, callback);
+ } else {
+ return processInternal(SObjectComposite.class, exchange, compositeClient::submitComposite,
+ this::processCompositeResponse, callback);
+ }
default:
throw new SalesforceException("Unknown operation name: " + operationName.value(), null);
}
@@ -124,6 +130,27 @@ public final class CompositeApiProcessor extends AbstractSalesforceProcessor {
}
}
+ void processCompositeResponseRaw(
+ final Exchange exchange, final Optional<InputStream> responseBody, final Map<String, String> headers,
+ final SalesforceException exception, final AsyncCallback callback) {
+ try {
+ if (!responseBody.isPresent()) {
+ exchange.setException(exception);
+ } else {
+ final Message in = exchange.getIn();
+ final Message out = exchange.getOut();
+
+ final InputStream response = responseBody.get();
+
+ out.copyFromWithNewBody(in, response);
+ out.getHeaders().putAll(headers);
+ }
+ } finally {
+ // notify callback that exchange is done
+ callback.done(false);
+ }
+ }
+
void processCompositeResponse(
final Exchange exchange, final Optional<SObjectCompositeResponse> responseBody, final Map<String, String> headers,
final SalesforceException exception, final AsyncCallback callback) {
@@ -207,6 +234,31 @@ public final class CompositeApiProcessor extends AbstractSalesforceProcessor {
return false;
}
+ boolean processRaw(
+ final Exchange exchange, final CompositeApiClient compositeClient,
+ final ResponseHandler<InputStream> responseHandler, final AsyncCallback callback)
+ throws SalesforceException {
+ final InputStream body;
+
+ final Message in = exchange.getIn();
+ try {
+ body = in.getMandatoryBody(InputStream.class);
+ } catch (final InvalidPayloadException e) {
+ throw new SalesforceException(e);
+ }
+
+ String sObjectName = getParameter(SalesforceEndpointConfig.SOBJECT_NAME, exchange, IGNORE_BODY, NOT_OPTIONAL);
+ String extId = getParameter(SalesforceEndpointConfig.SOBJECT_EXT_ID_NAME, exchange, IGNORE_BODY, NOT_OPTIONAL);
+ String method = getParameter(SalesforceEndpointConfig.COMPOSITE_METHOD, exchange, IGNORE_BODY, NOT_OPTIONAL);
+
+ compositeClient.submitCompositeRaw(body, determineHeaders(exchange),
+ (response, responseHeaders, exception) -> responseHandler.handleResponse(exchange, response, responseHeaders,
+ exception, callback),
+ sObjectName, extId, method);
+
+ return false;
+ }
+
static boolean processException(final Exchange exchange, final AsyncCallback callback, final Exception e) {
exchange.setException(e);
callback.done(true);
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
index 741ef2d6..5d50007 100644
--- 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
@@ -228,6 +228,13 @@ public class RawPayloadTest extends AbstractSalesforceTestBase {
from("direct:apexCallPatch")
.to("salesforce:apexCall/Merchandise/?rawPayload=true&format=" + format + "&apexMethod=PATCH");
+
+ // testComposite (only JSON format is supported)
+ if (format.equalsIgnoreCase("json")) {
+ from("direct:composite").to(
+ "salesforce:composite?rawPayload=true&format=" + format
+ + "&sObjectName=foo&sObjectIdName=bar&compositeMethod=PATCH");
+ }
}
};
}
@@ -240,8 +247,8 @@ public class RawPayloadTest extends AbstractSalesforceTestBase {
"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" };
+ "direct:apexCallGet", "direct:apexCallGetWithId", "direct:apexCallPatch",
+ "direct:composite" };
final String[] formats = { "XML", "JSON" };
diff --git a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SalesforceComponentBuilderFactory.java b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SalesforceComponentBuilderFactory.java
index ef9c814..218e4f0 100644
--- a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SalesforceComponentBuilderFactory.java
+++ b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/SalesforceComponentBuilderFactory.java
@@ -123,6 +123,18 @@ public interface SalesforceComponentBuilderFactory {
return this;
}
/**
+ * Composite (raw) method.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: common
+ */
+ default SalesforceComponentBuilder compositeMethod(
+ java.lang.String compositeMethod) {
+ doSetProperty("compositeMethod", compositeMethod);
+ return this;
+ }
+ /**
* Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV.
*
* The option is a:
@@ -1055,6 +1067,7 @@ public interface SalesforceComponentBuilderFactory {
case "apiVersion": getOrCreateConfiguration((SalesforceComponent) component).setApiVersion((java.lang.String) value); return true;
case "backoffIncrement": getOrCreateConfiguration((SalesforceComponent) component).setBackoffIncrement((long) value); return true;
case "batchId": getOrCreateConfiguration((SalesforceComponent) component).setBatchId((java.lang.String) value); return true;
+ case "compositeMethod": getOrCreateConfiguration((SalesforceComponent) component).setCompositeMethod((java.lang.String) value); return true;
case "contentType": getOrCreateConfiguration((SalesforceComponent) component).setContentType((org.apache.camel.component.salesforce.api.dto.bulk.ContentType) value); return true;
case "defaultReplayId": getOrCreateConfiguration((SalesforceComponent) component).setDefaultReplayId((java.lang.Long) value); return true;
case "format": getOrCreateConfiguration((SalesforceComponent) component).setFormat((org.apache.camel.component.salesforce.internal.PayloadFormat) value); return true;
diff --git a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SalesforceEndpointBuilderFactory.java b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SalesforceEndpointBuilderFactory.java
index 85dcf69..4921261 100644
--- a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SalesforceEndpointBuilderFactory.java
+++ b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SalesforceEndpointBuilderFactory.java
@@ -143,6 +143,18 @@ public interface SalesforceEndpointBuilderFactory {
return this;
}
/**
+ * Composite (raw) method.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: common
+ */
+ default SalesforceEndpointConsumerBuilder compositeMethod(
+ String compositeMethod) {
+ doSetProperty("compositeMethod", compositeMethod);
+ return this;
+ }
+ /**
* Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV.
*
* The option is a:
@@ -1064,6 +1076,18 @@ public interface SalesforceEndpointBuilderFactory {
return this;
}
/**
+ * Composite (raw) method.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: common
+ */
+ default SalesforceEndpointProducerBuilder compositeMethod(
+ String compositeMethod) {
+ doSetProperty("compositeMethod", compositeMethod);
+ return this;
+ }
+ /**
* Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV.
*
* The option is a:
@@ -1909,6 +1933,17 @@ public interface SalesforceEndpointBuilderFactory {
return this;
}
/**
+ * Composite (raw) method.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: common
+ */
+ default SalesforceEndpointBuilder compositeMethod(String compositeMethod) {
+ doSetProperty("compositeMethod", compositeMethod);
+ return this;
+ }
+ /**
* Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV.
*
* The option is a:
diff --git a/docs/components/modules/ROOT/pages/salesforce-component.adoc b/docs/components/modules/ROOT/pages/salesforce-component.adoc
index 34e3bdf9..f93a840 100644
--- a/docs/components/modules/ROOT/pages/salesforce-component.adoc
+++ b/docs/components/modules/ROOT/pages/salesforce-component.adoc
@@ -658,7 +658,7 @@ for details on how to generate the DTO.
// component options: START
-The Salesforce component supports 73 options, which are listed below.
+The Salesforce component supports 74 options, which are listed below.
@@ -671,6 +671,7 @@ The Salesforce component supports 73 options, which are listed below.
| *apiVersion* (common) | Salesforce API version. | 50.0 | String
| *backoffIncrement* (common) | Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto-reconnect. | 1000 | long
| *batchId* (common) | Bulk API Batch ID | | String
+| *compositeMethod* (common) | Composite (raw) method. | | String
| *contentType* (common) | Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV. There are 6 enums and the value can be one of: XML, CSV, JSON, ZIP_XML, ZIP_CSV, ZIP_JSON | | ContentType
| *defaultReplayId* (common) | Default replayId setting if no value is found in initialReplayIdMap | -1 | Long
| *format* (common) | Payload format to use for Salesforce API calls, either JSON or XML, defaults to JSON. There are 2 enums and the value can be one of: JSON, XML | | PayloadFormat
@@ -770,7 +771,7 @@ with the following path and query parameters:
|===
-=== Query Parameters (44 parameters):
+=== Query Parameters (45 parameters):
[width="100%",cols="2,5,^1,2",options="header"]
@@ -782,6 +783,7 @@ with the following path and query parameters:
| *apiVersion* (common) | Salesforce API version. | 50.0 | String
| *backoffIncrement* (common) | Backoff interval increment for Streaming connection restart attempts for failures beyond CometD auto-reconnect. | 1000 | long
| *batchId* (common) | Bulk API Batch ID | | String
+| *compositeMethod* (common) | Composite (raw) method. | | String
| *contentType* (common) | Bulk API content type, one of XML, CSV, ZIP_XML, ZIP_CSV. There are 6 enums and the value can be one of: XML, CSV, JSON, ZIP_XML, ZIP_CSV, ZIP_JSON | | ContentType
| *defaultReplayId* (common) | Default replayId setting if no value is found in initialReplayIdMap | -1 | Long
| *format* (common) | Payload format to use for Salesforce API calls, either JSON or XML, defaults to JSON. There are 2 enums and the value can be one of: JSON, XML | | PayloadFormat