This is an automated email from the ASF dual-hosted git repository.
jeremyross pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 89524c6 CAMEL-16390: Add salesforce 'raw' operation. (#5582)
89524c6 is described below
commit 89524c67a569db7cb2a6cb706aa3aec1f80ae488
Author: Jeremy Ross <[email protected]>
AuthorDate: Tue May 18 11:07:52 2021 -0500
CAMEL-16390: Add salesforce 'raw' operation. (#5582)
CAMEL-16390: Add salesforce 'raw' operation.
---
.../camel/catalog/docs/salesforce-component.adoc | 60 +++++++++-
.../camel-salesforce-component/pom.xml | 9 +-
.../salesforce/SalesforceComponentConfigurer.java | 24 ++++
.../salesforce/SalesforceEndpointConfigurer.java | 24 ++++
.../salesforce/SalesforceEndpointUriFactory.java | 6 +-
.../camel/component/salesforce/salesforce.json | 12 +-
.../src/main/docs/salesforce-component.adoc | 60 +++++++++-
.../component/salesforce/SalesforceComponent.java | 7 ++
.../component/salesforce/SalesforceEndpoint.java | 3 +-
.../salesforce/SalesforceEndpointConfig.java | 74 ++++++++++++
.../component/salesforce/SalesforceProducer.java | 8 +-
.../salesforce/internal/OperationName.java | 5 +-
.../internal/client/DefaultRawClient.java | 109 ++++++++++++++++++
.../salesforce/internal/client/RawClient.java | 44 +++++++
.../internal/processor/RawProcessor.java | 126 +++++++++++++++++++++
.../salesforce/RawOperationIntegrationTest.java | 79 +++++++++++++
.../dsl/SalesforceComponentBuilderFactory.java | 66 +++++++++++
.../builder/endpoint/StaticEndpointBuilders.java | 8 +-
.../dsl/SalesforceEndpointBuilderFactory.java | 70 +++++++++++-
.../modules/ROOT/pages/salesforce-component.adoc | 60 +++++++++-
20 files changed, 826 insertions(+), 28 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 3bd5a27..8d2677f 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
@@ -168,6 +168,7 @@ Returns a list of UpsertSObjectResult objects.
the information about archived Task and Event records.
* getBlobField - Retrieves the specified blob field from an individual record.
* apexCall - Executes a user defined APEX REST API call.
+* raw - Send requests to salesforce and have full, raw control over endpoint,
parameters, body, etc.
For example, the following producer endpoint uses the upsertSObject API,
with the sObjectIdName parameter specifying 'Name' as the external id
@@ -674,6 +675,51 @@ With this approach, you have the complete control on the
Salesforce request.
`compositeMethod` option to override to the other supported value, `GET`,
which returns a list of
other available composite resources.
+== Using Raw Operation
+
+Send HTTP requests to salesforce with full, raw control of all aspects of the
call. Any serialization or deserialization of request and response bodies must
be performed in the route. The `Content-Type` HTTP
+header will be automatically set based on the `format` option, but this can be
overridden with the `rawHttpHeaders` option.
+
+|===
+| Parameter | Type | Description| Default| Required
+
+| request body | `String` or `InputStream` | Body of the HTTP request | |
+| rawPath | `String` | The portion of the endpoint URL after the domain name,
e.g., '/services/data/v51.0/sobjects/Account/' | | x
+| rawMethod | `String` | The HTTP method | | x
+| rawQueryParameters | `String` | Comma separated list of message headers to
include as query parameters. Do not url-encode values as this will be done
automatically. | |
+| rawHttpHeaders | `String` | Comma separated list of message headers to
include as HTTP headers | |
+|===
+
+=== Query example
+
+In this example we'll send a query to the REST API. The query must be passed
in a URL parameter called "q", so we'll create a message header called q and
tell the
+raw operation to include that message header as a URL parameter:
+----
+from("direct:queryExample")
+ .setHeader("q", "SELECT Id, LastName FROM Contact")
+
.to("salesforce:raw?format=JSON&rawMethod=GET&rawQueryParameters=q&rawPath=/services/data/v51.0/query")
+ // deserialize JSON results or handle in some other way
+----
+
+=== SObject example
+
+In this example, we'll pass a Contact the REST API in a `create` operation.
Since the `raw` operation does not perform any serialization,
+we make sure to pass XML in the message body
+
+----
+from("direct:createAContact")
+ .setBody(constant("<Contact><LastName>TestLast</LastName></Contact>"))
+
.to("salesforce:raw?format=XML&rawMethod=POST&rawPath=/services/data/v51.0/sobjects/Contact")
+----
+The response is:
+----
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Result>
+ <id>0034x00000RnV6zAAF</id>
+ <success>true</success>
+</Result>
+----
+
== Using Composite SObject Collections
The SObject Collections API executes actions on multiple records in one
request. Use sObject Collections to reduce the number of round-trips between
the client and server. The entire request counts as a single call toward your
API limits. This resource is available in API version 42.0 and later. `SObject`
records (aka DTOs) supplied to these operations must be instances of subclasses
of `AbstractDescribedSObjectBase`. See the Maven Plugin section for information
on generating these DTO c [...]
@@ -777,7 +823,7 @@ for details on how to generate the DTO.
== Options
// component options: START
-The Salesforce component supports 80 options, which are listed below.
+The Salesforce component supports 84 options, which are listed below.
@@ -839,6 +885,10 @@ The Salesforce component supports 80 options, which are
listed below.
| *apexUrl* (producer) | APEX method URL | | String
| *compositeMethod* (producer) | Composite (raw) method. | | String
| *lazyStartProducer* (producer) | Whether the producer should be started lazy
(on the first message). By starting lazy you can use this to allow CamelContext
and routes to startup in situations where a producer may otherwise fail during
starting and cause the route to fail being started. By deferring this startup
to be lazy then the startup failure can be handled during routing messages via
Camel's routing error handlers. Beware that when the first message is processed
then creating and [...]
+| *rawHttpHeaders* (producer) | Comma separated list of message headers to
include as HTTP parameters for Raw operation. | | String
+| *rawMethod* (producer) | HTTP method to use for the Raw operation | | String
+| *rawPath* (producer) | The portion of the endpoint URL after the domain
name. E.g., '/services/data/v52.0/sobjects/Account/' | | String
+| *rawQueryParameters* (producer) | Comma separated list of message headers to
include as query parameters for Raw operation. Do not url-encode values as this
will be done automatically. | | String
| *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used
for automatic autowiring options (the option must be marked as autowired) by
looking up in the registry to find if there is a single instance of matching
type, which then gets configured on the component. This can be used for
automatic configuring JDBC data sources, JMS connection factories, AWS Clients,
etc. | true | boolean
| *httpProxyExcludedAddresses* (proxy) | A list of addresses for which HTTP
proxy server should not be used. | | Set
| *httpProxyHost* (proxy) | Hostname of the HTTP proxy server to use. | |
String
@@ -891,12 +941,12 @@ with the following path and query parameters:
[width="100%",cols="2,5,^1,2",options="header"]
|===
| Name | Description | Default | Type
-| *operationName* | The operation to use. There are 64 enums and the value can
be one of: getVersions, getResources, getGlobalObjects, getBasicInfo,
getDescription, getSObject, createSObject, updateSObject, deleteSObject,
getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField, query,
queryMore, queryAll, search, apexCall, recent, createJob, getJob, closeJob,
abortJob, createBatch, getBatch, getAllBatches, getRequest, getResults,
createBatchQuery, getQueryResultIds, getQueryRe [...]
+| *operationName* | The operation to use. There are 65 enums and the value can
be one of: getVersions, getResources, getGlobalObjects, getBasicInfo,
getDescription, getSObject, createSObject, updateSObject, deleteSObject,
getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField, query,
queryMore, queryAll, search, apexCall, recent, createJob, getJob, closeJob,
abortJob, createBatch, getBatch, getAllBatches, getRequest, getResults,
createBatchQuery, getQueryResultIds, getQueryRe [...]
| *topicName* | The name of the topic/channel to use | | String
|===
-=== Query Parameters (50 parameters):
+=== Query Parameters (54 parameters):
[width="100%",cols="2,5,^1,2",options="header"]
@@ -952,6 +1002,10 @@ with the following path and query parameters:
| *apexUrl* (producer) | APEX method URL | | String
| *compositeMethod* (producer) | Composite (raw) method. | | String
| *lazyStartProducer* (producer) | Whether the producer should be started lazy
(on the first message). By starting lazy you can use this to allow CamelContext
and routes to startup in situations where a producer may otherwise fail during
starting and cause the route to fail being started. By deferring this startup
to be lazy then the startup failure can be handled during routing messages via
Camel's routing error handlers. Beware that when the first message is processed
then creating and [...]
+| *rawHttpHeaders* (producer) | Comma separated list of message headers to
include as HTTP parameters for Raw operation. | | String
+| *rawMethod* (producer) | HTTP method to use for the Raw operation | | String
+| *rawPath* (producer) | The portion of the endpoint URL after the domain
name. E.g., '/services/data/v52.0/sobjects/Account/' | | String
+| *rawQueryParameters* (producer) | Comma separated list of message headers to
include as query parameters for Raw operation. Do not url-encode values as this
will be done automatically. | | String
|===
// endpoint options: END
diff --git a/components/camel-salesforce/camel-salesforce-component/pom.xml
b/components/camel-salesforce/camel-salesforce-component/pom.xml
index c301235..cc009ac 100644
--- a/components/camel-salesforce/camel-salesforce-component/pom.xml
+++ b/components/camel-salesforce/camel-salesforce-component/pom.xml
@@ -114,6 +114,10 @@
<artifactId>xstream</artifactId>
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.cometd.java</groupId>
<artifactId>cometd-java-client</artifactId>
<version>${cometd-java-client-version}</version>
@@ -148,11 +152,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<scope>test</scope>
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 f6197e8..281478f 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
@@ -146,8 +146,16 @@ public class SalesforceComponentConfigurer extends
PropertyConfigurerSupport imp
case "pkChunkingStartRow":
getOrCreateConfig(target).setPkChunkingStartRow(property(camelContext,
java.lang.String.class, value)); return true;
case "querylocator":
case "queryLocator":
getOrCreateConfig(target).setQueryLocator(property(camelContext,
java.lang.String.class, value)); return true;
+ case "rawhttpheaders":
+ case "rawHttpHeaders":
getOrCreateConfig(target).setRawHttpHeaders(property(camelContext,
java.lang.String.class, value)); return true;
+ case "rawmethod":
+ case "rawMethod":
getOrCreateConfig(target).setRawMethod(property(camelContext,
java.lang.String.class, value)); return true;
+ case "rawpath":
+ case "rawPath":
getOrCreateConfig(target).setRawPath(property(camelContext,
java.lang.String.class, value)); return true;
case "rawpayload":
case "rawPayload":
getOrCreateConfig(target).setRawPayload(property(camelContext, boolean.class,
value)); return true;
+ case "rawqueryparameters":
+ case "rawQueryParameters":
getOrCreateConfig(target).setRawQueryParameters(property(camelContext,
java.lang.String.class, value)); return true;
case "refreshtoken":
case "refreshToken": target.setRefreshToken(property(camelContext,
java.lang.String.class, value)); return true;
case "reportid":
@@ -307,8 +315,16 @@ public class SalesforceComponentConfigurer extends
PropertyConfigurerSupport imp
case "pkChunkingStartRow": return java.lang.String.class;
case "querylocator":
case "queryLocator": return java.lang.String.class;
+ case "rawhttpheaders":
+ case "rawHttpHeaders": return java.lang.String.class;
+ case "rawmethod":
+ case "rawMethod": return java.lang.String.class;
+ case "rawpath":
+ case "rawPath": return java.lang.String.class;
case "rawpayload":
case "rawPayload": return boolean.class;
+ case "rawqueryparameters":
+ case "rawQueryParameters": return java.lang.String.class;
case "refreshtoken":
case "refreshToken": return java.lang.String.class;
case "reportid":
@@ -469,8 +485,16 @@ public class SalesforceComponentConfigurer extends
PropertyConfigurerSupport imp
case "pkChunkingStartRow": return
getOrCreateConfig(target).getPkChunkingStartRow();
case "querylocator":
case "queryLocator": return
getOrCreateConfig(target).getQueryLocator();
+ case "rawhttpheaders":
+ case "rawHttpHeaders": return
getOrCreateConfig(target).getRawHttpHeaders();
+ case "rawmethod":
+ case "rawMethod": return getOrCreateConfig(target).getRawMethod();
+ case "rawpath":
+ case "rawPath": return getOrCreateConfig(target).getRawPath();
case "rawpayload":
case "rawPayload": return getOrCreateConfig(target).isRawPayload();
+ case "rawqueryparameters":
+ case "rawQueryParameters": return
getOrCreateConfig(target).getRawQueryParameters();
case "refreshtoken":
case "refreshToken": return target.getRefreshToken();
case "reportid":
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 23abe0a..031c963 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
@@ -89,8 +89,16 @@ public class SalesforceEndpointConfigurer extends
PropertyConfigurerSupport impl
case "pkChunkingStartRow":
target.getConfiguration().setPkChunkingStartRow(property(camelContext,
java.lang.String.class, value)); return true;
case "querylocator":
case "queryLocator":
target.getConfiguration().setQueryLocator(property(camelContext,
java.lang.String.class, value)); return true;
+ case "rawhttpheaders":
+ case "rawHttpHeaders":
target.getConfiguration().setRawHttpHeaders(property(camelContext,
java.lang.String.class, value)); return true;
+ case "rawmethod":
+ case "rawMethod":
target.getConfiguration().setRawMethod(property(camelContext,
java.lang.String.class, value)); return true;
+ case "rawpath":
+ case "rawPath":
target.getConfiguration().setRawPath(property(camelContext,
java.lang.String.class, value)); return true;
case "rawpayload":
case "rawPayload":
target.getConfiguration().setRawPayload(property(camelContext, boolean.class,
value)); return true;
+ case "rawqueryparameters":
+ case "rawQueryParameters":
target.getConfiguration().setRawQueryParameters(property(camelContext,
java.lang.String.class, value)); return true;
case "replayid":
case "replayId": target.setReplayId(property(camelContext,
java.lang.Long.class, value)); return true;
case "reportid":
@@ -194,8 +202,16 @@ public class SalesforceEndpointConfigurer extends
PropertyConfigurerSupport impl
case "pkChunkingStartRow": return java.lang.String.class;
case "querylocator":
case "queryLocator": return java.lang.String.class;
+ case "rawhttpheaders":
+ case "rawHttpHeaders": return java.lang.String.class;
+ case "rawmethod":
+ case "rawMethod": return java.lang.String.class;
+ case "rawpath":
+ case "rawPath": return java.lang.String.class;
case "rawpayload":
case "rawPayload": return boolean.class;
+ case "rawqueryparameters":
+ case "rawQueryParameters": return java.lang.String.class;
case "replayid":
case "replayId": return java.lang.Long.class;
case "reportid":
@@ -300,8 +316,16 @@ public class SalesforceEndpointConfigurer extends
PropertyConfigurerSupport impl
case "pkChunkingStartRow": return
target.getConfiguration().getPkChunkingStartRow();
case "querylocator":
case "queryLocator": return
target.getConfiguration().getQueryLocator();
+ case "rawhttpheaders":
+ case "rawHttpHeaders": return
target.getConfiguration().getRawHttpHeaders();
+ case "rawmethod":
+ case "rawMethod": return target.getConfiguration().getRawMethod();
+ case "rawpath":
+ case "rawPath": return target.getConfiguration().getRawPath();
case "rawpayload":
case "rawPayload": return target.getConfiguration().isRawPayload();
+ case "rawqueryparameters":
+ case "rawQueryParameters": return
target.getConfiguration().getRawQueryParameters();
case "replayid":
case "replayId": return target.getReplayId();
case "reportid":
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 c92251d..40da452 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<>(52);
+ Set<String> props = new HashSet<>(56);
props.add("initialReplayIdMap");
props.add("notifyForOperations");
props.add("sObjectQuery");
@@ -39,6 +39,7 @@ public class SalesforceEndpointUriFactory extends
org.apache.camel.support.compo
props.add("sObjectBlobFieldName");
props.add("backoffIncrement");
props.add("format");
+ props.add("rawHttpHeaders");
props.add("sObjectId");
props.add("defaultReplayId");
props.add("jobId");
@@ -54,6 +55,8 @@ public class SalesforceEndpointUriFactory extends
org.apache.camel.support.compo
props.add("notifyForOperationUndelete");
props.add("apexUrl");
props.add("updateTopic");
+ props.add("rawMethod");
+ props.add("rawPath");
props.add("instanceId");
props.add("notifyForFields");
props.add("sObjectIdValue");
@@ -69,6 +72,7 @@ public class SalesforceEndpointUriFactory extends
org.apache.camel.support.compo
props.add("exchangePattern");
props.add("operationName");
props.add("pkChunking");
+ props.add("rawQueryParameters");
props.add("notFoundBehaviour");
props.add("allOrNone");
props.add("topicName");
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 28ee224..f23c070 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
@@ -78,6 +78,10 @@
"apexUrl": { "kind": "property", "displayName": "Apex Url", "group":
"producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "config", "description": "APEX method URL" },
"compositeMethod": { "kind": "property", "displayName": "Composite
Method", "group": "producer", "label": "producer", "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." },
"lazyStartProducer": { "kind": "property", "displayName": "Lazy Start
Producer", "group": "producer", "label": "producer", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "Whether the producer
should be started lazy (on the first message). By starting lazy you can use
this to allow CamelContext and routes to startup in situations where a producer
may otherwise fail during star [...]
+ "rawHttpHeaders": { "kind": "property", "displayName": "Raw Http Headers",
"group": "producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "config", "description": "Comma separated list of message
headers to include as HTTP parameters for Raw operation." },
+ "rawMethod": { "kind": "property", "displayName": "Raw Method", "group":
"producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "config", "description": "HTTP method to use for the Raw
operation" },
+ "rawPath": { "kind": "property", "displayName": "Raw Path", "group":
"producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "config", "description": "The portion of the endpoint URL
after the domain name. E.g., '\/services\/data\/v52.0\/sobjects\/Account\/'" },
+ "rawQueryParameters": { "kind": "property", "displayName": "Raw Query
Parameters", "group": "producer", "label": "producer", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "config", "description": "Comma separated list of message
headers to include as query parameters for Raw operation. Do not url [...]
"autowiredEnabled": { "kind": "property", "displayName": "Autowired
Enabled", "group": "advanced", "label": "advanced", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": true, "description": "Whether autowiring is
enabled. This is used for automatic autowiring options (the option must be
marked as autowired) by looking up in the registry to find if there is a single
instance of matching type, which t [...]
"httpProxyExcludedAddresses": { "kind": "property", "displayName": "Http
Proxy Excluded Addresses", "group": "proxy", "label": "common,proxy",
"required": false, "type": "object", "javaType":
"java.util.Set<java.lang.String>", "deprecated": false, "autowired": false,
"secret": false, "description": "A list of addresses for which HTTP proxy
server should not be used." },
"httpProxyHost": { "kind": "property", "displayName": "Http Proxy Host",
"group": "proxy", "label": "common,proxy", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "Hostname of the HTTP proxy server to use." },
@@ -105,7 +109,7 @@
"userName": { "kind": "property", "displayName": "User Name", "group":
"security", "label": "common,security", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "Username used in OAuth flow to gain access to
access token. It's easy to get started with password OAuth flow, but in general
one should avoid it as it is deemed less secure than other flows." }
},
"properties": {
- "operationName": { "kind": "path", "displayName": "Operation Name",
"group": "producer", "label": "producer", "required": false, "type": "object",
"javaType": "org.apache.camel.component.salesforce.internal.OperationName",
"enum": [ "getVersions", "getResources", "getGlobalObjects", "getBasicInfo",
"getDescription", "getSObject", "createSObject", "updateSObject",
"deleteSObject", "getSObjectWithId", "upsertSObject", "deleteSObjectWithId",
"getBlobField", "query", "queryMore", "queryA [...]
+ "operationName": { "kind": "path", "displayName": "Operation Name",
"group": "producer", "label": "producer", "required": false, "type": "object",
"javaType": "org.apache.camel.component.salesforce.internal.OperationName",
"enum": [ "getVersions", "getResources", "getGlobalObjects", "getBasicInfo",
"getDescription", "getSObject", "createSObject", "updateSObject",
"deleteSObject", "getSObjectWithId", "upsertSObject", "deleteSObjectWithId",
"getBlobField", "query", "queryMore", "queryA [...]
"topicName": { "kind": "path", "displayName": "Topic Name", "group":
"consumer", "label": "consumer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "description": "The name of the topic\/channel to use" },
"apexMethod": { "kind": "parameter", "displayName": "Apex 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": "APEX method name" },
"apexQueryParams": { "kind": "parameter", "displayName": "Apex Query
Params", "group": "common", "label": "", "required": false, "type": "object",
"javaType": "java.util.Map<java.lang.String, java.lang.Object>", "deprecated":
false, "autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "Query params for APEX
method" },
@@ -156,6 +160,10 @@
"allOrNone": { "kind": "parameter", "displayName": "All Or None", "group":
"producer", "label": "producer", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "Composite API option to
indicate to rollback all records if any are not successful." },
"apexUrl": { "kind": "parameter", "displayName": "Apex Url", "group":
"producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "APEX method URL" },
"compositeMethod": { "kind": "parameter", "displayName": "Composite
Method", "group": "producer", "label": "producer", "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."
},
- "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start
Producer", "group": "producer", "label": "producer", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "Whether the producer
should be started lazy (on the first message). By starting lazy you can use
this to allow CamelContext and routes to startup in situations where a producer
may otherwise fail during sta [...]
+ "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start
Producer", "group": "producer", "label": "producer", "required": false, "type":
"boolean", "javaType": "boolean", "deprecated": false, "autowired": false,
"secret": false, "defaultValue": false, "description": "Whether the producer
should be started lazy (on the first message). By starting lazy you can use
this to allow CamelContext and routes to startup in situations where a producer
may otherwise fail during sta [...]
+ "rawHttpHeaders": { "kind": "parameter", "displayName": "Raw Http
Headers", "group": "producer", "label": "producer", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "Comma separated list of
message headers to include as HTTP parameters for Raw operation." },
+ "rawMethod": { "kind": "parameter", "displayName": "Raw Method", "group":
"producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "HTTP method to use for
the Raw operation" },
+ "rawPath": { "kind": "parameter", "displayName": "Raw Path", "group":
"producer", "label": "producer", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "The portion of the
endpoint URL after the domain name. E.g.,
'\/services\/data\/v52.0\/sobjects\/Account\/'" },
+ "rawQueryParameters": { "kind": "parameter", "displayName": "Raw Query
Parameters", "group": "producer", "label": "producer", "required": false,
"type": "string", "javaType": "java.lang.String", "deprecated": false,
"autowired": false, "secret": false, "configurationClass":
"org.apache.camel.component.salesforce.SalesforceEndpointConfig",
"configurationField": "configuration", "description": "Comma separated list of
message headers to include as query parameters for Raw operation. Do [...]
}
}
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 3bd5a27..8d2677f 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
@@ -168,6 +168,7 @@ Returns a list of UpsertSObjectResult objects.
the information about archived Task and Event records.
* getBlobField - Retrieves the specified blob field from an individual record.
* apexCall - Executes a user defined APEX REST API call.
+* raw - Send requests to salesforce and have full, raw control over endpoint,
parameters, body, etc.
For example, the following producer endpoint uses the upsertSObject API,
with the sObjectIdName parameter specifying 'Name' as the external id
@@ -674,6 +675,51 @@ With this approach, you have the complete control on the
Salesforce request.
`compositeMethod` option to override to the other supported value, `GET`,
which returns a list of
other available composite resources.
+== Using Raw Operation
+
+Send HTTP requests to salesforce with full, raw control of all aspects of the
call. Any serialization or deserialization of request and response bodies must
be performed in the route. The `Content-Type` HTTP
+header will be automatically set based on the `format` option, but this can be
overridden with the `rawHttpHeaders` option.
+
+|===
+| Parameter | Type | Description| Default| Required
+
+| request body | `String` or `InputStream` | Body of the HTTP request | |
+| rawPath | `String` | The portion of the endpoint URL after the domain name,
e.g., '/services/data/v51.0/sobjects/Account/' | | x
+| rawMethod | `String` | The HTTP method | | x
+| rawQueryParameters | `String` | Comma separated list of message headers to
include as query parameters. Do not url-encode values as this will be done
automatically. | |
+| rawHttpHeaders | `String` | Comma separated list of message headers to
include as HTTP headers | |
+|===
+
+=== Query example
+
+In this example we'll send a query to the REST API. The query must be passed
in a URL parameter called "q", so we'll create a message header called q and
tell the
+raw operation to include that message header as a URL parameter:
+----
+from("direct:queryExample")
+ .setHeader("q", "SELECT Id, LastName FROM Contact")
+
.to("salesforce:raw?format=JSON&rawMethod=GET&rawQueryParameters=q&rawPath=/services/data/v51.0/query")
+ // deserialize JSON results or handle in some other way
+----
+
+=== SObject example
+
+In this example, we'll pass a Contact the REST API in a `create` operation.
Since the `raw` operation does not perform any serialization,
+we make sure to pass XML in the message body
+
+----
+from("direct:createAContact")
+ .setBody(constant("<Contact><LastName>TestLast</LastName></Contact>"))
+
.to("salesforce:raw?format=XML&rawMethod=POST&rawPath=/services/data/v51.0/sobjects/Contact")
+----
+The response is:
+----
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Result>
+ <id>0034x00000RnV6zAAF</id>
+ <success>true</success>
+</Result>
+----
+
== Using Composite SObject Collections
The SObject Collections API executes actions on multiple records in one
request. Use sObject Collections to reduce the number of round-trips between
the client and server. The entire request counts as a single call toward your
API limits. This resource is available in API version 42.0 and later. `SObject`
records (aka DTOs) supplied to these operations must be instances of subclasses
of `AbstractDescribedSObjectBase`. See the Maven Plugin section for information
on generating these DTO c [...]
@@ -777,7 +823,7 @@ for details on how to generate the DTO.
== Options
// component options: START
-The Salesforce component supports 80 options, which are listed below.
+The Salesforce component supports 84 options, which are listed below.
@@ -839,6 +885,10 @@ The Salesforce component supports 80 options, which are
listed below.
| *apexUrl* (producer) | APEX method URL | | String
| *compositeMethod* (producer) | Composite (raw) method. | | String
| *lazyStartProducer* (producer) | Whether the producer should be started lazy
(on the first message). By starting lazy you can use this to allow CamelContext
and routes to startup in situations where a producer may otherwise fail during
starting and cause the route to fail being started. By deferring this startup
to be lazy then the startup failure can be handled during routing messages via
Camel's routing error handlers. Beware that when the first message is processed
then creating and [...]
+| *rawHttpHeaders* (producer) | Comma separated list of message headers to
include as HTTP parameters for Raw operation. | | String
+| *rawMethod* (producer) | HTTP method to use for the Raw operation | | String
+| *rawPath* (producer) | The portion of the endpoint URL after the domain
name. E.g., '/services/data/v52.0/sobjects/Account/' | | String
+| *rawQueryParameters* (producer) | Comma separated list of message headers to
include as query parameters for Raw operation. Do not url-encode values as this
will be done automatically. | | String
| *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used
for automatic autowiring options (the option must be marked as autowired) by
looking up in the registry to find if there is a single instance of matching
type, which then gets configured on the component. This can be used for
automatic configuring JDBC data sources, JMS connection factories, AWS Clients,
etc. | true | boolean
| *httpProxyExcludedAddresses* (proxy) | A list of addresses for which HTTP
proxy server should not be used. | | Set
| *httpProxyHost* (proxy) | Hostname of the HTTP proxy server to use. | |
String
@@ -891,12 +941,12 @@ with the following path and query parameters:
[width="100%",cols="2,5,^1,2",options="header"]
|===
| Name | Description | Default | Type
-| *operationName* | The operation to use. There are 64 enums and the value can
be one of: getVersions, getResources, getGlobalObjects, getBasicInfo,
getDescription, getSObject, createSObject, updateSObject, deleteSObject,
getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField, query,
queryMore, queryAll, search, apexCall, recent, createJob, getJob, closeJob,
abortJob, createBatch, getBatch, getAllBatches, getRequest, getResults,
createBatchQuery, getQueryResultIds, getQueryRe [...]
+| *operationName* | The operation to use. There are 65 enums and the value can
be one of: getVersions, getResources, getGlobalObjects, getBasicInfo,
getDescription, getSObject, createSObject, updateSObject, deleteSObject,
getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField, query,
queryMore, queryAll, search, apexCall, recent, createJob, getJob, closeJob,
abortJob, createBatch, getBatch, getAllBatches, getRequest, getResults,
createBatchQuery, getQueryResultIds, getQueryRe [...]
| *topicName* | The name of the topic/channel to use | | String
|===
-=== Query Parameters (50 parameters):
+=== Query Parameters (54 parameters):
[width="100%",cols="2,5,^1,2",options="header"]
@@ -952,6 +1002,10 @@ with the following path and query parameters:
| *apexUrl* (producer) | APEX method URL | | String
| *compositeMethod* (producer) | Composite (raw) method. | | String
| *lazyStartProducer* (producer) | Whether the producer should be started lazy
(on the first message). By starting lazy you can use this to allow CamelContext
and routes to startup in situations where a producer may otherwise fail during
starting and cause the route to fail being started. By deferring this startup
to be lazy then the startup failure can be handled during routing messages via
Camel's routing error handlers. Beware that when the first message is processed
then creating and [...]
+| *rawHttpHeaders* (producer) | Comma separated list of message headers to
include as HTTP parameters for Raw operation. | | String
+| *rawMethod* (producer) | HTTP method to use for the Raw operation | | String
+| *rawPath* (producer) | The portion of the endpoint URL after the domain
name. E.g., '/services/data/v52.0/sobjects/Account/' | | String
+| *rawQueryParameters* (producer) | Comma separated list of message headers to
include as query parameters for Raw operation. Do not url-encode values as this
will be done automatically. | | String
|===
// endpoint options: END
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
index d5b7ce2..33f4753 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceComponent.java
@@ -36,7 +36,9 @@ import
org.apache.camel.component.salesforce.api.utils.XStreamUtils;
import org.apache.camel.component.salesforce.internal.OperationName;
import org.apache.camel.component.salesforce.internal.PayloadFormat;
import org.apache.camel.component.salesforce.internal.SalesforceSession;
+import org.apache.camel.component.salesforce.internal.client.DefaultRawClient;
import org.apache.camel.component.salesforce.internal.client.DefaultRestClient;
+import org.apache.camel.component.salesforce.internal.client.RawClient;
import org.apache.camel.component.salesforce.internal.client.RestClient;
import
org.apache.camel.component.salesforce.internal.streaming.SubscriptionHelper;
import org.apache.camel.spi.Metadata;
@@ -788,6 +790,11 @@ public class SalesforceComponent extends DefaultComponent
implements SSLContextP
return new DefaultRestClient(httpClient, config.getApiVersion(),
config.getFormat(), session, loginConfig);
}
+ public RawClient createRawClientFor(SalesforceEndpoint endpoint) throws
SalesforceException {
+ SalesforceEndpointConfig endpointConfig = endpoint.getConfiguration();
+ return new DefaultRawClient(httpClient, "", session, loginConfig);
+ }
+
static SalesforceHttpClient createHttpClient(final SslContextFactory
sslContextFactory) throws Exception {
SecurityUtils.adaptToIBMCipherNames(sslContextFactory);
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
index 7070af0..3084597 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceEndpoint.java
@@ -54,7 +54,8 @@ public class SalesforceEndpoint extends DefaultEndpoint {
+
"bulk2GetAllJobs,bulk2CreateJob,bulk2GetJob,bulk2CreateBatch,bulk2CloseJob,"
+
"bulk2AbortJob,bulk2DeleteJob,bulk2GetSuccessfulResults,bulk2GetFailedResults,"
+
"bulk2GetUnprocessedRecords,bulk2CreateQueryJob,bulk2GetQueryJob,"
- +
"bulk2GetAllQueryJobs,bulk2GetQueryJobResults,bulk2AbortQueryJob,bulk2DeleteQueryJob")
+ +
"bulk2GetAllQueryJobs,bulk2GetQueryJobResults,bulk2AbortQueryJob,bulk2DeleteQueryJob,"
+ + "raw")
private final OperationName operationName;
//CHECKSTYLE:ON
@UriPath(label = "consumer", description = "The name of the topic/channel
to use")
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 0557b49..f0c6c81 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
@@ -94,6 +94,12 @@ public class SalesforceEndpointConfig implements Cloneable {
// parameters for Approval API
public static final String APPROVAL = "approval";
+ // parameters for the RAW operation
+ public static final String RAW_PATH = "rawPath";
+ public static final String RAW_METHOD = "rawMethod";
+ public static final String RAW_QUERY_PARAMETERS = "rawQueryParameters";
+ public static final String RAW_HTTP_HEADERS = "rawHttpHeaders";
+
// default maximum authentication retries on failed authentication or
// expired session
public static final int DEFAULT_MAX_AUTHENTICATION_RETRIES = 4;
@@ -199,6 +205,16 @@ public class SalesforceEndpointConfig implements Cloneable
{
// Approval API properties
private ApprovalRequest approval;
+ // RAW operation properties
+ @UriParam(label = "producer")
+ private String rawPath;
+ @UriParam(label = "producer")
+ private String rawMethod;
+ @UriParam(label = "producer")
+ private String rawQueryParameters;
+ @UriParam(label = "producer")
+ private String rawHttpHeaders;
+
// Salesforce Jetty9 HttpClient, set using reference
@UriParam
private SalesforceHttpClient httpClient;
@@ -744,6 +760,11 @@ public class SalesforceEndpointConfig implements Cloneable
{
valueMap.put(NOT_FOUND_BEHAVIOUR, notFoundBehaviour);
+ valueMap.put(RAW_PATH, rawPath);
+ valueMap.put(RAW_METHOD, rawMethod);
+ valueMap.put(RAW_HTTP_HEADERS, rawHttpHeaders);
+ valueMap.put(RAW_QUERY_PARAMETERS, rawQueryParameters);
+
return Collections.unmodifiableMap(valueMap);
}
@@ -959,4 +980,57 @@ public class SalesforceEndpointConfig implements Cloneable
{
public void setNotFoundBehaviour(final NotFoundBehaviour
notFoundBehaviour) {
this.notFoundBehaviour = notFoundBehaviour;
}
+
+ public String getRawPath() {
+ return rawPath;
+ }
+
+ /**
+ * The portion of the endpoint URL after the domain name. E.g., " +
"'/services/data/v52.0/sobjects/Account/'
+ *
+ * @param rawPath the path
+ */
+ public void setRawPath(String rawPath) {
+ this.rawPath = rawPath;
+ }
+
+ public String getRawMethod() {
+ return rawMethod;
+ }
+
+ /**
+ * HTTP method to use for the Raw operation
+ *
+ * @param rawMethod http method
+ */
+ public void setRawMethod(String rawMethod) {
+ this.rawMethod = rawMethod;
+ }
+
+ public String getRawQueryParameters() {
+ return rawQueryParameters;
+ }
+
+ /**
+ * Comma separated list of message headers to include as query parameters
for Raw operation. Do not url-encode
+ * values as this will be done automatically.
+ *
+ * @param rawQueryParameters
+ */
+ public void setRawQueryParameters(String rawQueryParameters) {
+ this.rawQueryParameters = rawQueryParameters;
+ }
+
+ public String getRawHttpHeaders() {
+ return rawHttpHeaders;
+ }
+
+ /**
+ * Comma separated list of message headers to include as HTTP parameters
for Raw operation.
+ *
+ * @param
+ */
+ public void setRawHttpHeaders(String rawHttpHeaders) {
+ this.rawHttpHeaders = rawHttpHeaders;
+ }
}
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
index 4569bfd..700cb31 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/SalesforceProducer.java
@@ -29,6 +29,7 @@ import
org.apache.camel.component.salesforce.internal.processor.BulkApiV2Process
import
org.apache.camel.component.salesforce.internal.processor.CompositeApiProcessor;
import
org.apache.camel.component.salesforce.internal.processor.CompositeSObjectCollectionsProcessor;
import
org.apache.camel.component.salesforce.internal.processor.JsonRestProcessor;
+import org.apache.camel.component.salesforce.internal.processor.RawProcessor;
import
org.apache.camel.component.salesforce.internal.processor.SalesforceProcessor;
import
org.apache.camel.component.salesforce.internal.processor.XmlRestProcessor;
import org.apache.camel.support.DefaultAsyncProducer;
@@ -63,6 +64,8 @@ public class SalesforceProducer extends DefaultAsyncProducer {
processor = new CompositeApiProcessor(endpoint);
} else if (isCompositeSObjectCollectionsOperation(operationName)) {
processor = new CompositeSObjectCollectionsProcessor(endpoint);
+ } else if (isRawOperation(operationName)) {
+ processor = new RawProcessor(endpoint);
} else {
// create an appropriate processor
if (payloadFormat == PayloadFormat.JSON) {
@@ -156,6 +159,10 @@ public class SalesforceProducer extends
DefaultAsyncProducer {
}
}
+ private static boolean isRawOperation(OperationName operationName) {
+ return operationName == OperationName.RAW;
+ }
+
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
SalesforceEndpoint endpoint = (SalesforceEndpoint) getEndpoint();
@@ -187,5 +194,4 @@ public class SalesforceProducer extends
DefaultAsyncProducer {
super.doStop();
}
-
}
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
index 086cef8..53811af 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/OperationName.java
@@ -102,7 +102,10 @@ public enum OperationName {
COMPOSITE_UPDATE_SOBJECT_COLLECTIONS("compositeUpdateSObjectCollections"),
COMPOSITE_UPSERT_SOBJECT_COLLECTIONS("compositeUpsertSObjectCollections"),
COMPOSITE_RETRIEVE_SOBJECT_COLLECTIONS("compositeRetrieveSObjectCollections"),
- COMPOSITE_DELETE_SOBJECT_COLLECTIONS("compositeDeleteSObjectCollections");
+ COMPOSITE_DELETE_SOBJECT_COLLECTIONS("compositeDeleteSObjectCollections"),
+
+ // Raw operation
+ RAW("raw");
private final String value;
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRawClient.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRawClient.java
new file mode 100644
index 0000000..c4483d4
--- /dev/null
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/DefaultRawClient.java
@@ -0,0 +1,109 @@
+/*
+ * 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.internal.client;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.SalesforceHttpClient;
+import org.apache.camel.component.salesforce.SalesforceLoginConfig;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.internal.PayloadFormat;
+import org.apache.camel.component.salesforce.internal.SalesforceSession;
+import org.apache.commons.io.IOUtils;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.client.util.InputStreamContentProvider;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.util.StringUtil;
+
+public class DefaultRawClient extends AbstractClientBase implements RawClient {
+
+ private static final String BULK_TOKEN_HEADER = "X-SFDC-Session";
+ private static final String REST_TOKEN_HEADER = "Authorization";
+ private static final String TOKEN_PREFIX = "Bearer ";
+
+ public DefaultRawClient(final SalesforceHttpClient httpClient, final
String version,
+ final SalesforceSession session,
+ final SalesforceLoginConfig loginConfig) throws
SalesforceException {
+ super(version, session, httpClient, loginConfig);
+ }
+
+ @Override
+ protected void setAccessToken(Request request) {
+ // replace old token
+ request.getHeaders().put(BULK_TOKEN_HEADER, accessToken);
+ request.getHeaders().put(REST_TOKEN_HEADER, TOKEN_PREFIX +
accessToken);
+ }
+
+ @Override
+ protected SalesforceException createRestException(Response response,
InputStream responseContent) {
+ String message = null;
+ try {
+ message = IOUtils.toString(responseContent,
StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ message = "Unable to read exception message: " + e.getMessage();
+ }
+ return new SalesforceException(message, response.getStatus());
+ }
+
+ /**
+ * Make a raw HTTP request to salesforce
+ *
+ * @param method HTTP method. "GET", "POST", etc.
+ * @param path The path of the URL. Must begin with a "/"
+ * @param format Encoding format
+ * @param body Optional HTTP body
+ * @param headers HTTP headers
+ * @param callback Callback instance that will be invoked when the HTTP
call returns
+ */
+ @Override
+ public void makeRequest(
+ String method, String path, PayloadFormat format, InputStream
body, Map<String, List<String>> headers,
+ ResponseCallback callback) {
+ final Request request = getRequest(method, instanceUrl + path,
headers);
+ final String contentType = PayloadFormat.JSON.equals(format) ?
APPLICATION_JSON_UTF8 : APPLICATION_XML_UTF8;
+ if (!request.getHeaders().contains(HttpHeader.ACCEPT)) {
+ request.header(HttpHeader.ACCEPT, contentType);
+ }
+ request.header(HttpHeader.ACCEPT_CHARSET, StringUtil.__UTF8);
+ if (!request.getHeaders().contains(HttpHeader.CONTENT_TYPE)) {
+ request.header(HttpHeader.CONTENT_TYPE, contentType);
+ }
+ if (body != null) {
+ request.content(new InputStreamContentProvider(body));
+ }
+ setAccessToken(request);
+ doHttpRequest(request, new DelegatingClientCallback(callback));
+ }
+
+ private static class DelegatingClientCallback implements
ClientResponseCallback {
+ private final ResponseCallback callback;
+
+ DelegatingClientCallback(ResponseCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void onResponse(InputStream response, Map<String, String>
headers, SalesforceException ex) {
+ callback.onResponse(response, headers, ex);
+ }
+ }
+}
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RawClient.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RawClient.java
new file mode 100644
index 0000000..7b9c20b
--- /dev/null
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/client/RawClient.java
@@ -0,0 +1,44 @@
+/*
+ * 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.internal.client;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.internal.PayloadFormat;
+
+public interface RawClient {
+
+ /**
+ * Make a raw HTTP request to salesforce
+ *
+ * @param method HTTP method. "GET", "POST", etc.
+ * @param path the path of the URL. Must begin with a "/"
+ * @param body Optional HTTP body
+ * @param headers HTTP headers
+ * @param callback callback instance that will be invoked when the HTTP
call returns
+ */
+ void makeRequest(
+ String method, String path, PayloadFormat format, InputStream
body, Map<String, List<String>> headers,
+ ResponseCallback callback);
+
+ interface ResponseCallback {
+ void onResponse(InputStream response, Map<String, String> headers,
SalesforceException exception);
+ }
+}
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/RawProcessor.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/RawProcessor.java
new file mode 100644
index 0000000..edf306b
--- /dev/null
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/RawProcessor.java
@@ -0,0 +1,126 @@
+/*
+ * 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.internal.processor;
+
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.AsyncCallback;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.component.salesforce.SalesforceComponent;
+import org.apache.camel.component.salesforce.SalesforceEndpoint;
+import org.apache.camel.component.salesforce.SalesforceEndpointConfig;
+import org.apache.camel.component.salesforce.api.SalesforceException;
+import org.apache.camel.component.salesforce.internal.PayloadFormat;
+import org.apache.camel.component.salesforce.internal.client.RawClient;
+import org.apache.camel.support.service.ServiceHelper;
+import org.eclipse.jetty.util.StringUtil;
+
+public class RawProcessor extends AbstractSalesforceProcessor {
+
+ private RawClient rawClient;
+ private final PayloadFormat format;
+
+ public RawProcessor(SalesforceEndpoint endpoint) throws
SalesforceException {
+ super(endpoint);
+ format = endpoint.getConfiguration().getFormat();
+ if (format == null) {
+ throw new IllegalArgumentException("format option must be
specified when using the raw operation.");
+ }
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ SalesforceComponent component = endpoint.getComponent();
+ rawClient = component.createRawClientFor(endpoint);
+ ServiceHelper.startService(rawClient);
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ ServiceHelper.stopService(rawClient);
+ super.doStop();
+ }
+
+ @Override
+ public boolean process(Exchange exchange, AsyncCallback callback) {
+ try {
+ StringBuilder path
+ = new
StringBuilder(getParameter(SalesforceEndpointConfig.RAW_PATH, exchange,
IGNORE_BODY, NOT_OPTIONAL));
+ String method = getParameter(SalesforceEndpointConfig.RAW_METHOD,
exchange, IGNORE_BODY, NOT_OPTIONAL);
+ String params = getParameter(
+ SalesforceEndpointConfig.RAW_QUERY_PARAMETERS, exchange,
IGNORE_BODY, IS_OPTIONAL);
+ if (params != null) {
+ path.append("?");
+ for (String p : params.split(",")) {
+ if (!path.toString().endsWith("?")) {
+ path.append("&");
+ }
+ path.append(p).append("=");
+
path.append(urlEncode(exchange.getIn().getHeader(p).toString()));
+ }
+ }
+
+ InputStream body = exchange.getIn().getBody(InputStream.class);
+ rawClient.makeRequest(method, path.toString(), format, body,
determineHeaders(exchange),
+ (response, headers, exception) -> {
+ Message in = exchange.getIn();
+ in.getHeaders().putAll(headers);
+ if (exception != null) {
+ exchange.setException(exception);
+ }
+ in.setBody(response);
+ callback.done(false);
+ });
+ } catch (Exception e) {
+ exchange.setException(e);
+ callback.done(true);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Map<String, List<String>> determineHeaders(Exchange exchange) {
+ try {
+ final Map<String, List<String>> headers =
super.determineHeaders(exchange);
+ String params = getParameter(
+ SalesforceEndpointConfig.RAW_HTTP_HEADERS, exchange,
IGNORE_BODY, IS_OPTIONAL);
+ if (params != null) {
+ for (String p : params.split(",")) {
+ headers.put(p,
Collections.singletonList(exchange.getIn().getHeader(p).toString()));
+ }
+ }
+ return headers;
+ } catch (SalesforceException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String urlEncode(String query) throws UnsupportedEncodingException
{
+ String encodedQuery = URLEncoder.encode(query, StringUtil.__UTF8);
+ // URLEncoder likes to use '+' for spaces
+ encodedQuery = encodedQuery.replace("+", "%20");
+ return encodedQuery;
+ }
+}
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawOperationIntegrationTest.java
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawOperationIntegrationTest.java
new file mode 100644
index 0000000..cd78f5f
--- /dev/null
+++
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RawOperationIntegrationTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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 org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class RawOperationIntegrationTest extends AbstractSalesforceTestBase {
+
+ @Test
+ public void testCreate() {
+ String body = "{\n" +
+ " \"LastName\" : \"TestLast\"\n" +
+ "}";
+
+ Exchange exchange = fluentTemplate.withBody(body)
+
.to("salesforce:raw?rawMethod=POST&rawPath=/services/data/v51.0/sobjects/Contact")
+ .send();
+
+ String response = exchange.getIn().getBody(String.class);
+ assertNull(exchange.getException());
+ assertTrue(response.contains("success"));
+ }
+
+ @Test
+ public void testCreateXml() {
+ String body = "<Contact>\n" +
+ " <LastName>TestLast</LastName>\n" +
+ "</Contact>";
+
+ Exchange exchange = fluentTemplate.withBody(body)
+
.to("salesforce:raw?format=XML&rawMethod=POST&rawPath=/services/data/v51.0/sobjects/Contact")
+ .send();
+
+ String response = exchange.getIn().getBody(String.class);
+ assertNull(exchange.getException());
+ assertTrue(response.contains("success"));
+ }
+
+ @Test
+ public void testQuery() {
+
+ Exchange exchange = fluentTemplate
+ .withHeader("q", "SELECT Id FROM Contact LIMIT 10")
+
.to("salesforce:raw?format=JSON&rawMethod=GET&rawQueryParameters=q&rawPath=/services/data/v51.0/query")
+ .send();
+
+ String response = exchange.getIn().getBody(String.class);
+ assertTrue(response.contains("done"));
+ assertTrue(response.contains("totalSize"));
+ }
+
+ @Override
+ protected RouteBuilder doCreateRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ }
+ };
+ }
+}
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 56bdcfd..7a4a8c6 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
@@ -942,6 +942,68 @@ public interface SalesforceComponentBuilderFactory {
return this;
}
/**
+ * Comma separated list of message headers to include as HTTP
parameters
+ * for Raw operation.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawHttpHeaders the value to set
+ * @return the dsl builder
+ */
+ default SalesforceComponentBuilder rawHttpHeaders(
+ java.lang.String rawHttpHeaders) {
+ doSetProperty("rawHttpHeaders", rawHttpHeaders);
+ return this;
+ }
+ /**
+ * HTTP method to use for the Raw operation.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawMethod the value to set
+ * @return the dsl builder
+ */
+ default SalesforceComponentBuilder rawMethod(java.lang.String
rawMethod) {
+ doSetProperty("rawMethod", rawMethod);
+ return this;
+ }
+ /**
+ * The portion of the endpoint URL after the domain name. E.g.,
+ * '/services/data/v52.0/sobjects/Account/'.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawPath the value to set
+ * @return the dsl builder
+ */
+ default SalesforceComponentBuilder rawPath(java.lang.String rawPath) {
+ doSetProperty("rawPath", rawPath);
+ return this;
+ }
+ /**
+ * Comma separated list of message headers to include as query
+ * parameters for Raw operation. Do not url-encode values as this will
+ * be done automatically.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawQueryParameters the value to set
+ * @return the dsl builder
+ */
+ default SalesforceComponentBuilder rawQueryParameters(
+ java.lang.String rawQueryParameters) {
+ doSetProperty("rawQueryParameters", rawQueryParameters);
+ return this;
+ }
+ /**
* Whether autowiring is enabled. This is used for automatic autowiring
* options (the option must be marked as autowired) by looking up in
the
* registry to find if there is a single instance of matching type,
@@ -1443,6 +1505,10 @@ public interface SalesforceComponentBuilderFactory {
case "apexUrl": getOrCreateConfiguration((SalesforceComponent)
component).setApexUrl((java.lang.String) value); return true;
case "compositeMethod":
getOrCreateConfiguration((SalesforceComponent)
component).setCompositeMethod((java.lang.String) value); return true;
case "lazyStartProducer": ((SalesforceComponent)
component).setLazyStartProducer((boolean) value); return true;
+ case "rawHttpHeaders":
getOrCreateConfiguration((SalesforceComponent)
component).setRawHttpHeaders((java.lang.String) value); return true;
+ case "rawMethod": getOrCreateConfiguration((SalesforceComponent)
component).setRawMethod((java.lang.String) value); return true;
+ case "rawPath": getOrCreateConfiguration((SalesforceComponent)
component).setRawPath((java.lang.String) value); return true;
+ case "rawQueryParameters":
getOrCreateConfiguration((SalesforceComponent)
component).setRawQueryParameters((java.lang.String) value); return true;
case "autowiredEnabled": ((SalesforceComponent)
component).setAutowiredEnabled((boolean) value); return true;
case "httpProxyExcludedAddresses": ((SalesforceComponent)
component).setHttpProxyExcludedAddresses((java.util.Set) value); return true;
case "httpProxyHost": ((SalesforceComponent)
component).setHttpProxyHost((java.lang.String) value); return true;
diff --git
a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
index 0404053..0d69c80 100644
---
a/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
+++
b/core/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/StaticEndpointBuilders.java
@@ -12596,7 +12596,7 @@ public class StaticEndpointBuilders {
*
* Path parameter: operationName
* The operation to use
- * There are 64 enums and the value can be one of: getVersions,
+ * There are 65 enums and the value can be one of: getVersions,
* getResources, getGlobalObjects, getBasicInfo, getDescription,
getSObject,
* createSObject, updateSObject, deleteSObject, getSObjectWithId,
* upsertSObject, deleteSObjectWithId, getBlobField, query, queryMore,
@@ -12613,7 +12613,7 @@ public class StaticEndpointBuilders {
* bulk2DeleteJob, bulk2GetSuccessfulResults, bulk2GetFailedResults,
* bulk2GetUnprocessedRecords, bulk2CreateQueryJob, bulk2GetQueryJob,
* bulk2GetAllQueryJobs, bulk2GetQueryJobResults, bulk2AbortQueryJob,
- * bulk2DeleteQueryJob
+ * bulk2DeleteQueryJob, raw
*
* Path parameter: topicName
* The name of the topic/channel to use
@@ -12637,7 +12637,7 @@ public class StaticEndpointBuilders {
*
* Path parameter: operationName
* The operation to use
- * There are 64 enums and the value can be one of: getVersions,
+ * There are 65 enums and the value can be one of: getVersions,
* getResources, getGlobalObjects, getBasicInfo, getDescription,
getSObject,
* createSObject, updateSObject, deleteSObject, getSObjectWithId,
* upsertSObject, deleteSObjectWithId, getBlobField, query, queryMore,
@@ -12654,7 +12654,7 @@ public class StaticEndpointBuilders {
* bulk2DeleteJob, bulk2GetSuccessfulResults, bulk2GetFailedResults,
* bulk2GetUnprocessedRecords, bulk2CreateQueryJob, bulk2GetQueryJob,
* bulk2GetAllQueryJobs, bulk2GetQueryJobResults, bulk2AbortQueryJob,
- * bulk2DeleteQueryJob
+ * bulk2DeleteQueryJob, raw
*
* Path parameter: topicName
* The name of the topic/channel to use
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 ed5654c..1ea7580 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
@@ -2395,6 +2395,68 @@ public interface SalesforceEndpointBuilderFactory {
doSetProperty("lazyStartProducer", lazyStartProducer);
return this;
}
+ /**
+ * Comma separated list of message headers to include as HTTP
parameters
+ * for Raw operation.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawHttpHeaders the value to set
+ * @return the dsl builder
+ */
+ default SalesforceEndpointProducerBuilder rawHttpHeaders(
+ String rawHttpHeaders) {
+ doSetProperty("rawHttpHeaders", rawHttpHeaders);
+ return this;
+ }
+ /**
+ * HTTP method to use for the Raw operation.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawMethod the value to set
+ * @return the dsl builder
+ */
+ default SalesforceEndpointProducerBuilder rawMethod(String rawMethod) {
+ doSetProperty("rawMethod", rawMethod);
+ return this;
+ }
+ /**
+ * The portion of the endpoint URL after the domain name. E.g.,
+ * '/services/data/v52.0/sobjects/Account/'.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawPath the value to set
+ * @return the dsl builder
+ */
+ default SalesforceEndpointProducerBuilder rawPath(String rawPath) {
+ doSetProperty("rawPath", rawPath);
+ return this;
+ }
+ /**
+ * Comma separated list of message headers to include as query
+ * parameters for Raw operation. Do not url-encode values as this will
+ * be done automatically.
+ *
+ * The option is a: <code>java.lang.String</code> type.
+ *
+ * Group: producer
+ *
+ * @param rawQueryParameters the value to set
+ * @return the dsl builder
+ */
+ default SalesforceEndpointProducerBuilder rawQueryParameters(
+ String rawQueryParameters) {
+ doSetProperty("rawQueryParameters", rawQueryParameters);
+ return this;
+ }
}
/**
@@ -3518,7 +3580,7 @@ public interface SalesforceEndpointBuilderFactory {
*
* Path parameter: operationName
* The operation to use
- * There are 64 enums and the value can be one of: getVersions,
+ * There are 65 enums and the value can be one of: getVersions,
* getResources, getGlobalObjects, getBasicInfo, getDescription,
* getSObject, createSObject, updateSObject, deleteSObject,
* getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField,
@@ -3536,7 +3598,7 @@ public interface SalesforceEndpointBuilderFactory {
* bulk2GetSuccessfulResults, bulk2GetFailedResults,
* bulk2GetUnprocessedRecords, bulk2CreateQueryJob, bulk2GetQueryJob,
* bulk2GetAllQueryJobs, bulk2GetQueryJobResults, bulk2AbortQueryJob,
- * bulk2DeleteQueryJob
+ * bulk2DeleteQueryJob, raw
*
* Path parameter: topicName
* The name of the topic/channel to use
@@ -3559,7 +3621,7 @@ public interface SalesforceEndpointBuilderFactory {
*
* Path parameter: operationName
* The operation to use
- * There are 64 enums and the value can be one of: getVersions,
+ * There are 65 enums and the value can be one of: getVersions,
* getResources, getGlobalObjects, getBasicInfo, getDescription,
* getSObject, createSObject, updateSObject, deleteSObject,
* getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField,
@@ -3577,7 +3639,7 @@ public interface SalesforceEndpointBuilderFactory {
* bulk2GetSuccessfulResults, bulk2GetFailedResults,
* bulk2GetUnprocessedRecords, bulk2CreateQueryJob, bulk2GetQueryJob,
* bulk2GetAllQueryJobs, bulk2GetQueryJobResults, bulk2AbortQueryJob,
- * bulk2DeleteQueryJob
+ * bulk2DeleteQueryJob, raw
*
* Path parameter: topicName
* The name of the topic/channel to use
diff --git a/docs/components/modules/ROOT/pages/salesforce-component.adoc
b/docs/components/modules/ROOT/pages/salesforce-component.adoc
index 7819e8d..e486848 100644
--- a/docs/components/modules/ROOT/pages/salesforce-component.adoc
+++ b/docs/components/modules/ROOT/pages/salesforce-component.adoc
@@ -170,6 +170,7 @@ Returns a list of UpsertSObjectResult objects.
the information about archived Task and Event records.
* getBlobField - Retrieves the specified blob field from an individual record.
* apexCall - Executes a user defined APEX REST API call.
+* raw - Send requests to salesforce and have full, raw control over endpoint,
parameters, body, etc.
For example, the following producer endpoint uses the upsertSObject API,
with the sObjectIdName parameter specifying 'Name' as the external id
@@ -676,6 +677,51 @@ With this approach, you have the complete control on the
Salesforce request.
`compositeMethod` option to override to the other supported value, `GET`,
which returns a list of
other available composite resources.
+== Using Raw Operation
+
+Send HTTP requests to salesforce with full, raw control of all aspects of the
call. Any serialization or deserialization of request and response bodies must
be performed in the route. The `Content-Type` HTTP
+header will be automatically set based on the `format` option, but this can be
overridden with the `rawHttpHeaders` option.
+
+|===
+| Parameter | Type | Description| Default| Required
+
+| request body | `String` or `InputStream` | Body of the HTTP request | |
+| rawPath | `String` | The portion of the endpoint URL after the domain name,
e.g., '/services/data/v51.0/sobjects/Account/' | | x
+| rawMethod | `String` | The HTTP method | | x
+| rawQueryParameters | `String` | Comma separated list of message headers to
include as query parameters. Do not url-encode values as this will be done
automatically. | |
+| rawHttpHeaders | `String` | Comma separated list of message headers to
include as HTTP headers | |
+|===
+
+=== Query example
+
+In this example we'll send a query to the REST API. The query must be passed
in a URL parameter called "q", so we'll create a message header called q and
tell the
+raw operation to include that message header as a URL parameter:
+----
+from("direct:queryExample")
+ .setHeader("q", "SELECT Id, LastName FROM Contact")
+
.to("salesforce:raw?format=JSON&rawMethod=GET&rawQueryParameters=q&rawPath=/services/data/v51.0/query")
+ // deserialize JSON results or handle in some other way
+----
+
+=== SObject example
+
+In this example, we'll pass a Contact the REST API in a `create` operation.
Since the `raw` operation does not perform any serialization,
+we make sure to pass XML in the message body
+
+----
+from("direct:createAContact")
+ .setBody(constant("<Contact><LastName>TestLast</LastName></Contact>"))
+
.to("salesforce:raw?format=XML&rawMethod=POST&rawPath=/services/data/v51.0/sobjects/Contact")
+----
+The response is:
+----
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Result>
+ <id>0034x00000RnV6zAAF</id>
+ <success>true</success>
+</Result>
+----
+
== Using Composite SObject Collections
The SObject Collections API executes actions on multiple records in one
request. Use sObject Collections to reduce the number of round-trips between
the client and server. The entire request counts as a single call toward your
API limits. This resource is available in API version 42.0 and later. `SObject`
records (aka DTOs) supplied to these operations must be instances of subclasses
of `AbstractDescribedSObjectBase`. See the Maven Plugin section for information
on generating these DTO c [...]
@@ -779,7 +825,7 @@ for details on how to generate the DTO.
== Options
// component options: START
-The Salesforce component supports 80 options, which are listed below.
+The Salesforce component supports 84 options, which are listed below.
@@ -841,6 +887,10 @@ The Salesforce component supports 80 options, which are
listed below.
| *apexUrl* (producer) | APEX method URL | | String
| *compositeMethod* (producer) | Composite (raw) method. | | String
| *lazyStartProducer* (producer) | Whether the producer should be started lazy
(on the first message). By starting lazy you can use this to allow CamelContext
and routes to startup in situations where a producer may otherwise fail during
starting and cause the route to fail being started. By deferring this startup
to be lazy then the startup failure can be handled during routing messages via
Camel's routing error handlers. Beware that when the first message is processed
then creating and [...]
+| *rawHttpHeaders* (producer) | Comma separated list of message headers to
include as HTTP parameters for Raw operation. | | String
+| *rawMethod* (producer) | HTTP method to use for the Raw operation | | String
+| *rawPath* (producer) | The portion of the endpoint URL after the domain
name. E.g., '/services/data/v52.0/sobjects/Account/' | | String
+| *rawQueryParameters* (producer) | Comma separated list of message headers to
include as query parameters for Raw operation. Do not url-encode values as this
will be done automatically. | | String
| *autowiredEnabled* (advanced) | Whether autowiring is enabled. This is used
for automatic autowiring options (the option must be marked as autowired) by
looking up in the registry to find if there is a single instance of matching
type, which then gets configured on the component. This can be used for
automatic configuring JDBC data sources, JMS connection factories, AWS Clients,
etc. | true | boolean
| *httpProxyExcludedAddresses* (proxy) | A list of addresses for which HTTP
proxy server should not be used. | | Set
| *httpProxyHost* (proxy) | Hostname of the HTTP proxy server to use. | |
String
@@ -893,12 +943,12 @@ with the following path and query parameters:
[width="100%",cols="2,5,^1,2",options="header"]
|===
| Name | Description | Default | Type
-| *operationName* | The operation to use. There are 64 enums and the value can
be one of: getVersions, getResources, getGlobalObjects, getBasicInfo,
getDescription, getSObject, createSObject, updateSObject, deleteSObject,
getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField, query,
queryMore, queryAll, search, apexCall, recent, createJob, getJob, closeJob,
abortJob, createBatch, getBatch, getAllBatches, getRequest, getResults,
createBatchQuery, getQueryResultIds, getQueryRe [...]
+| *operationName* | The operation to use. There are 65 enums and the value can
be one of: getVersions, getResources, getGlobalObjects, getBasicInfo,
getDescription, getSObject, createSObject, updateSObject, deleteSObject,
getSObjectWithId, upsertSObject, deleteSObjectWithId, getBlobField, query,
queryMore, queryAll, search, apexCall, recent, createJob, getJob, closeJob,
abortJob, createBatch, getBatch, getAllBatches, getRequest, getResults,
createBatchQuery, getQueryResultIds, getQueryRe [...]
| *topicName* | The name of the topic/channel to use | | String
|===
-=== Query Parameters (50 parameters):
+=== Query Parameters (54 parameters):
[width="100%",cols="2,5,^1,2",options="header"]
@@ -954,6 +1004,10 @@ with the following path and query parameters:
| *apexUrl* (producer) | APEX method URL | | String
| *compositeMethod* (producer) | Composite (raw) method. | | String
| *lazyStartProducer* (producer) | Whether the producer should be started lazy
(on the first message). By starting lazy you can use this to allow CamelContext
and routes to startup in situations where a producer may otherwise fail during
starting and cause the route to fail being started. By deferring this startup
to be lazy then the startup failure can be handled during routing messages via
Camel's routing error handlers. Beware that when the first message is processed
then creating and [...]
+| *rawHttpHeaders* (producer) | Comma separated list of message headers to
include as HTTP parameters for Raw operation. | | String
+| *rawMethod* (producer) | HTTP method to use for the Raw operation | | String
+| *rawPath* (producer) | The portion of the endpoint URL after the domain
name. E.g., '/services/data/v52.0/sobjects/Account/' | | String
+| *rawQueryParameters* (producer) | Comma separated list of message headers to
include as query parameters for Raw operation. Do not url-encode values as this
will be done automatically. | | String
|===
// endpoint options: END