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