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 c2b6f494f6a CAMEL-16642: camel-salesforce: Detect SObject type (#8275)
c2b6f494f6a is described below
commit c2b6f494f6a89ec7ab85925ea735f570a12a64b2
Author: Jeremy Ross <[email protected]>
AuthorDate: Mon Sep 5 14:25:07 2022 -0500
CAMEL-16642: camel-salesforce: Detect SObject type (#8275)
CAMEL-16642: camel-salesforce: Detect SObject type
Sniff the response to detect SObject type.
Implemented for query* and apexcall operations.
---
.../src/main/docs/salesforce-component.adoc | 32 +++++++++++++--------
.../salesforce/api/SalesforceException.java | 4 +++
.../internal/processor/AbstractRestProcessor.java | 32 +++++++++++++--------
.../processor/AbstractSalesforceProcessor.java | 27 ++++++++++++++----
.../CompositeSObjectCollectionsProcessor.java | 2 +-
.../internal/processor/JsonRestProcessor.java | 33 +++++++++++++++++++++-
.../salesforce/RestApiIntegrationTest.java | 32 +++++++++++++++++++--
7 files changed, 129 insertions(+), 33 deletions(-)
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 fbb608cb786..7b7e6961839 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
@@ -522,15 +522,16 @@ Deletes a record in salesforce by External ID.
`query`
-Runs a Salesforce SOQL query.
+Runs a Salesforce SOQL query. If neither `sObjectClass` nor `sObjectName` are
set, Camel will attempt to determine
+the correct `AbstractQueryRecordsBase` sublcass based on the response.
|===
| Parameter | Type | Description | Default | Required
| Body or `sObjectQuery` | `String` | SOQL query | | x
| streamQueryResult | `Boolean` | If true, returns a streaming `Iterator` and
transparently retrieves all pages as needed. The `sObjectClass` option must
reference an `AbstractQueryRecordsBase` subclass. | false |
-| `sObjectClass` | `String` | Fully qualified name of class to deserialize
response to. Usually a subclass of `AbstractQueryRecordsBase`, e.g.
`org.my.dto.QueryRecordsAccount`| | One of sObjectClass or sObjectName is
required
-| `sObjectName` | `String` | Simple name of class to deserialize response to.
Usually a subclass of `AbstractQueryRecordsBase`, e.g. `QueryRecordsAccount`.
Requires the `package` option be set.| |One of sObjectClass or sObjectName is
required
+| `sObjectClass` | `String` | Fully qualified name of class to deserialize
response to. Usually a subclass of `AbstractQueryRecordsBase`, e.g.
`org.my.dto.QueryRecordsAccount`| |
+| `sObjectName` | `String` | Simple name of class to deserialize response to.
Usually a subclass of `AbstractQueryRecordsBase`, e.g. `QueryRecordsAccount`.
Requires the `package` option be set.| |
|===
*Output*
@@ -542,14 +543,16 @@ Type: Instance of class supplied in `sObjectClass`, or
`Iterator<SomeSObject>` i
`queryMore`
-Retrieves more results (in case of large number of results) using result link
returned from the `query` and `queryAll` operations.
+Retrieves more results (in case of large number of results) using result link
returned from the `query` and `queryAll`
+operations. If neither `sObjectClass` nor `sObjectName` are set, Camel will
attempt to determine the correct
+`AbstractQueryRecordsBase` sublcass based on the response.
|===
| Parameter | Type | Description | Default | Required
| Body or `sObjectQuery` | `String` | `nextRecords` value. Can be found in a
prior query result in the `AbstractQueryRecordsBase.nextRecordsUrl` property |
| X
-| `sObjectClass` | `String` | Fully qualified name of class to deserialize
response to. Usually a subclass of `AbstractQueryRecordsBase`, e.g.
`org.my.dto.QueryRecordsAccount`| |One of sObjectClass or sObjectName is
required
-| `sObjectName` | `String` | Simple name of class to deserialize response to.
Usually a subclass of `AbstractQueryRecordsBase`, e.g. `QueryRecordsAccount`.
Requires the `package` option be set. | |One of sObjectClass or sObjectName is
required
+| `sObjectClass` | `String` | Fully qualified name of class to deserialize
response to. Usually a subclass of `AbstractQueryRecordsBase`, e.g.
`org.my.dto.QueryRecordsAccount`| |
+| `sObjectName` | `String` | Simple name of class to deserialize response to.
Usually a subclass of `AbstractQueryRecordsBase`, e.g. `QueryRecordsAccount`.
Requires the `package` option be set. | |
|===
@@ -562,15 +565,18 @@ Type: Instance of class supplied in `sObjectClass`
`queryAll`
-Executes the specified SOQL query. Unlike the `query` operation , `queryAll`
returns records that are deleted because of a merge or delete. It also returns
information about archived task and event records.
+Executes the specified SOQL query. Unlike the `query` operation , `queryAll`
returns records that are deleted because
+of a merge or delete. It also returns information about archived task and
event records. If neither `sObjectClass` nor
+`sObjectName` are set, Camel will attempt to determine the correct
`AbstractQueryRecordsBase` sublcass based on the
+response.
|===
| Parameter | Type | Description | Default | Required
| Body or `sObjectQuery` | `String` | SOQL query | | x
| streamQueryResult | `Boolean` | If true, returns a streaming `Iterable` and
transparently retrieves all pages as needed. The `sObjectClass` option must
reference an `AbstractQueryRecordsBase` subclass. | false |
-| `sObjectClass` | `String` | Fully qualified name of class to deserialize
response to. Usually a subclass of `AbstractQueryRecordsBase`, e.g.
`org.my.dto.QueryRecordsAccount`| |One of sObjectClass or sObjectName is
required
-| `sObjectName` | `String` | Simple name of class to deserialize response to.
Usually a subclass of `AbstractQueryRecordsBase`, e.g. `QueryRecordsAccount`.
Requires the `package` option be set.| |One of sObjectClass or sObjectName is
required
+| `sObjectClass` | `String` | Fully qualified name of class to deserialize
response to. Usually a subclass of `AbstractQueryRecordsBase`, e.g.
`org.my.dto.QueryRecordsAccount`| |
+| `sObjectName` | `String` | Simple name of class to deserialize response to.
Usually a subclass of `AbstractQueryRecordsBase`, e.g. `QueryRecordsAccount`.
Requires the `package` option be set.| |
|===
*Output*
@@ -1008,7 +1014,9 @@ salesforce:apexCall[/yourApexRestUrl][?options]
You can supply the apexUrl either in the endpoint (see above), or as the
`apexUrl` option as listed in the table below.
In either case the Apex URL can contain placeholders in the format of
`\{headerName}`. E.g., for the Apex URL `MyApexClass/\{id}`,
-the value of the header named `id` will be used to replace the placeholder.
+the value of the header named `id` will be used to replace the placeholder. If
`rawPayload` is false and neither
+`sObjectClass` nor `sObjectName` are set, Camel will attempt to determine the
correct `AbstractQueryRecordsBase`
+sublcass based on the response.
|===
| Parameter | Type | Description| Default| Required
@@ -1019,8 +1027,8 @@ is transformed into query parameters. For other HTTP
methods, the body is used f
| `apexMethod` | `String` | The HTTP method (e.g. `GET`, `POST`) to use. |
`GET` |
| `rawPayload` | `Boolean` | If true, Camel will not serialize the request or
response bodies. | false |
| Header: `apexQueryParam.[paramName]` | Object | Headers that override apex
parameters passed in the endpoint. | |
-| `sObjectName` | `String` | Name of sObject (e.g. `Merchandise__c`) used to
deserialize the response | | If `rawPayload` is false and `sObjectClass` not
supplied
-| `sObjectClass` | `String` | Fully qualified class name used to deserialize
the response | | If `rawPayload` is false and `sObjectName` not supplied
+| `sObjectName` | `String` | Name of sObject (e.g. `Merchandise__c`) used to
deserialize the response | |
+| `sObjectClass` | `String` | Fully qualified class name used to deserialize
the response | |
|===
*Output*
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
index 529c094fe9b..356ee7eee7f 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/api/SalesforceException.java
@@ -31,6 +31,10 @@ public class SalesforceException extends CamelException {
private final int statusCode;
private final InputStream responseContent;
+ public SalesforceException(String message) {
+ this(message, null);
+ }
+
public SalesforceException(Throwable cause) {
this(null, 0, null, cause);
}
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
index df4b4efd642..cc6d3699c9f 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractRestProcessor.java
@@ -63,6 +63,10 @@ import static
org.apache.camel.component.salesforce.SalesforceEndpointConfig.STR
public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor {
protected static final String RESPONSE_CLASS =
AbstractRestProcessor.class.getName() + ".responseClass";
+ protected static final String RESPONSE_CLASS_DEFERRED =
AbstractRestProcessor.class.getName()
+ +
".responseClassDeferred";
+ protected static final String RESPONSE_CLASS_PREFIX =
AbstractRestProcessor.class.getName()
+ +
".responseClassPrefix";
protected static final String RESPONSE_TYPE =
JsonRestProcessor.class.getName() + ".responseType";
private static final Pattern URL_TEMPLATE =
Pattern.compile("\\{([^\\{\\}]+)\\}");
@@ -332,7 +336,7 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
final String sObjectId = determineSObjectId(exchange);
// use sObject name to load class
- setResponseClass(exchange, sObjectName);
+ setResponseClass(exchange);
// get optional field list
String fieldsValue = getParameter(SOBJECT_FIELDS, exchange,
IGNORE_BODY, IS_OPTIONAL);
@@ -403,7 +407,7 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
}
// use sObject name to load class
- setResponseClass(exchange, sObjectName);
+ setResponseClass(exchange);
final Object finalOldValue = oldValue;
restClient.getSObjectWithId(sObjectName, sObjectExtIdName,
sObjectExtIdValue, determineHeaders(exchange),
@@ -492,10 +496,10 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
private void processQuery(final Exchange exchange, final AsyncCallback
callback) throws SalesforceException {
final String sObjectQuery = getParameter(SOBJECT_QUERY, exchange,
USE_BODY, NOT_OPTIONAL);
final boolean streamQueryResults = getParameter(STREAM_QUERY_RESULT,
exchange, IGNORE_BODY, IS_OPTIONAL, Boolean.class);
- final String sObjectName = getParameter(SOBJECT_NAME, exchange,
IGNORE_BODY, IS_OPTIONAL);
// use custom response class property
- setResponseClass(exchange, sObjectName);
+ setResponseClass(exchange);
+ exchange.setProperty(RESPONSE_CLASS_PREFIX, "QueryRecords");
if (streamQueryResults) {
restClient.query(sObjectQuery, determineHeaders(exchange),
processWithStreamResultCallback(exchange, callback));
@@ -507,10 +511,10 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
private void processQueryMore(final Exchange exchange, final AsyncCallback
callback) throws SalesforceException {
// reuse SOBJECT_QUERY parameter name for nextRecordsUrl
final String nextRecordsUrl = getParameter(SOBJECT_QUERY, exchange,
USE_BODY, NOT_OPTIONAL);
- final String sObjectName = getParameter(SOBJECT_NAME, exchange,
IGNORE_BODY, IS_OPTIONAL);
// use custom response class property
- setResponseClass(exchange, sObjectName);
+ setResponseClass(exchange);
+ exchange.setProperty(RESPONSE_CLASS_PREFIX, "QueryRecords");
restClient.queryMore(nextRecordsUrl, determineHeaders(exchange),
processWithResponseCallback(exchange, callback));
}
@@ -518,10 +522,10 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
private void processQueryAll(final Exchange exchange, final AsyncCallback
callback) throws SalesforceException {
final String sObjectQuery = getParameter(SOBJECT_QUERY, exchange,
USE_BODY, NOT_OPTIONAL);
final boolean streamQueryResults = getParameter(STREAM_QUERY_RESULT,
exchange, IGNORE_BODY, IS_OPTIONAL, Boolean.class);
- final String sObjectName = getParameter(SOBJECT_NAME, exchange,
IGNORE_BODY, IS_OPTIONAL);
// use custom response class property
- setResponseClass(exchange, sObjectName);
+ setResponseClass(exchange);
+ exchange.setProperty(RESPONSE_CLASS_PREFIX, "QueryRecords");
if (streamQueryResults) {
restClient.queryAll(sObjectQuery, determineHeaders(exchange),
processWithStreamResultCallback(exchange, callback));
@@ -549,7 +553,7 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
final Map<String, Object> queryParams = getQueryParams(exchange);
// set response class
- setResponseClass(exchange, getParameter(SOBJECT_NAME, exchange,
IGNORE_BODY, IS_OPTIONAL));
+ setResponseClass(exchange);
// set request stream
final Object requestBody = exchange.getIn().getBody();
@@ -731,15 +735,19 @@ public abstract class AbstractRestProcessor extends
AbstractSalesforceProcessor
*/
protected abstract InputStream getRequestStream(Message in, Object object)
throws SalesforceException;
- private void setResponseClass(Exchange exchange, String sObjectName)
throws SalesforceException {
+ protected void setResponseClass(Exchange exchange) throws
SalesforceException {
// nothing to do if using rawPayload
if (rawPayload) {
return;
}
- Class<?> sObjectClass = getSObjectClass(sObjectName, exchange);
- exchange.setProperty(RESPONSE_CLASS, sObjectClass);
+ Class<?> sObjectClass = getSObjectClass(exchange);
+ if (sObjectClass != null) {
+ exchange.setProperty(RESPONSE_CLASS, sObjectClass);
+ } else {
+ exchange.setProperty(RESPONSE_CLASS_DEFERRED, true);
+ }
}
final ResponseCallback processWithResponseCallback(final Exchange
exchange, final AsyncCallback callback) {
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
index d028ed62c91..773733222ec 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/AbstractSalesforceProcessor.java
@@ -175,18 +175,35 @@ public abstract class AbstractSalesforceProcessor extends
ServiceSupport impleme
}
}
- protected Class<?> getSObjectClass(String sObjectName, Exchange exchange)
throws SalesforceException {
+ protected Class<?> getSObjectClass(Exchange exchange) throws
SalesforceException {
+ final String sObjectName =
getParameter(SalesforceEndpointConfig.SOBJECT_NAME, exchange, IGNORE_BODY,
IS_OPTIONAL);
+ final String className =
getParameter(SalesforceEndpointConfig.SOBJECT_CLASS, exchange, IGNORE_BODY,
IS_OPTIONAL);
+ return getSObjectClass(sObjectName, className);
+ }
+
+ /**
+ *
+ * @param sObjectName if provided, will attempt to look up class
by simple name
+ * @param className if provided, will attempt to look up class
by fully qualified name
+ * @return Class, if found.
+ * @throws SalesforceException if unable to find class by whichever
parameter was non-null
+ */
+ protected Class<?> getSObjectClass(String sObjectName, String className)
throws SalesforceException {
Class<?> sObjectClass = null;
if (sObjectName != null) {
sObjectClass = classMap.get(sObjectName);
+ if (sObjectClass == null) {
+ throw new SalesforceException(
+ String.format("SObject class not found for
sObjectName: %s", sObjectName));
+ }
}
- if (sObjectClass == null) {
- final String className =
getParameter(SalesforceEndpointConfig.SOBJECT_CLASS, exchange, IGNORE_BODY,
NOT_OPTIONAL);
+ if (className != null) {
try {
- sObjectClass =
endpoint.getComponent().getCamelContext().getClassResolver().resolveMandatoryClass(className);
+ sObjectClass
+ =
endpoint.getComponent().getCamelContext().getClassResolver().resolveMandatoryClass(className);
} catch (ClassNotFoundException e) {
throw new SalesforceException(
- String.format("SObject class not found %s or by
sObjectName %s", className, sObjectName), e);
+ String.format("SObject class not found %s",
className), e);
}
}
return sObjectClass;
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeSObjectCollectionsProcessor.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeSObjectCollectionsProcessor.java
index 03d6a20d111..979c2d4708b 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeSObjectCollectionsProcessor.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/CompositeSObjectCollectionsProcessor.java
@@ -98,7 +98,7 @@ public class CompositeSObjectCollectionsProcessor extends
AbstractSalesforceProc
String sObjectName =
getParameter(SalesforceEndpointConfig.SOBJECT_NAME, exchange, IGNORE_BODY,
IS_OPTIONAL);
// gets class by sObjectName if not null, otherwise tries the
SOBJECT_CLASS option
- Class<?> sObjectClass = getSObjectClass(sObjectName, exchange);
+ Class<?> sObjectClass = getSObjectClass(exchange);
RetrieveSObjectCollectionsDto request = new
RetrieveSObjectCollectionsDto(ids, fields);
compositeClient.submitRetrieveCompositeCollections(request,
determineHeaders(exchange),
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
index fd8bf7094f1..b3e4d02c1bc 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/main/java/org/apache/camel/component/salesforce/internal/processor/JsonRestProcessor.java
@@ -23,6 +23,9 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.camel.AsyncCallback;
@@ -196,6 +199,9 @@ public class JsonRestProcessor extends
AbstractRestProcessor {
// do we need to un-marshal a response
final Object response;
Class<?> responseClass = exchange.getProperty(RESPONSE_CLASS,
Class.class);
+ if (responseClass == null &&
exchange.getProperty(RESPONSE_CLASS_DEFERRED, false, Boolean.class)) {
+ responseClass = detectResponseClass(exchange,
responseEntity);
+ }
if (!rawPayload && responseClass != null) {
response = objectMapper.readValue(responseEntity,
responseClass);
} else {
@@ -203,7 +209,7 @@ public class JsonRestProcessor extends
AbstractRestProcessor {
if (!rawPayload && responseType != null) {
response = objectMapper.readValue(responseEntity,
responseType);
} else {
- // return the response as a stream, for getBlobField
+ // return the response as a stream, for getBlobField
and rawPayload
response = responseEntity;
}
}
@@ -231,6 +237,29 @@ public class JsonRestProcessor extends
AbstractRestProcessor {
}
+ private Class<?> detectResponseClass(Exchange exchange, InputStream
responseEntity) throws IOException {
+ Class<?> responseClass;
+ try {
+ final JsonParser parser = new
JsonFactory().createParser(responseEntity);
+ String type = null;
+ while (parser.nextToken() != JsonToken.END_OBJECT) {
+ String propName = parser.getCurrentName();
+ if ("type".equals(propName)) {
+ parser.nextToken();
+ type = parser.getText();
+ break;
+ }
+ }
+ String prefix = exchange.getProperty(RESPONSE_CLASS_PREFIX, "",
String.class);
+ responseClass = getSObjectClass(prefix + type, null);
+ } catch (IOException | SalesforceException exc) {
+ throw new RuntimeException(exc);
+ } finally {
+ responseEntity.reset();
+ }
+ return responseClass;
+ }
+
@Override
protected void processStreamResultResponse(
Exchange exchange, InputStream responseEntity, Map<String, String>
headers, SalesforceException ex,
@@ -265,6 +294,8 @@ public class JsonRestProcessor extends
AbstractRestProcessor {
exchange.setException(new SalesforceException(msg, e));
} finally {
exchange.removeProperty(RESPONSE_CLASS);
+ exchange.removeProperty(RESPONSE_CLASS_DEFERRED);
+ exchange.removeProperty(RESPONSE_CLASS_PREFIX);
exchange.removeProperty(RESPONSE_TYPE);
try {
diff --git
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java
index 6ea82df1142..0966e5ee092 100644
---
a/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java
+++
b/components/camel-salesforce/camel-salesforce-component/src/test/java/org/apache/camel/component/salesforce/RestApiIntegrationTest.java
@@ -227,6 +227,15 @@ public class RestApiIntegrationTest extends
AbstractSalesforceTestBase {
assertEquals("test response",
IOUtils.toString(exception.getResponseContent(), StandardCharsets.UTF_8));
}
+ @Test
+ public void testApexCallDetectResponseType() throws Exception {
+ // request merchandise with id in URI template
+ Merchandise__c merchandise
+ =
template().requestBodyAndHeader("direct:apexCallGetDetectResponseType", null,
"id", merchandiseId,
+ Merchandise__c.class);
+ assertNotNull(merchandise);
+ }
+
@Test
public void returnsHttpResponseStatusAndText() {
Exchange exchange = new DefaultExchange(context);
@@ -512,6 +521,14 @@ public class RestApiIntegrationTest extends
AbstractSalesforceTestBase {
assertNotNull(lineItem.getRecordType());
}
+ @Test
+ public void testQueryDetectResponseClass() throws Exception {
+ createLineItem();
+ final QueryRecordsLine_Item__c queryRecords
+ = template().requestBody("direct:queryDetectResponseClass",
null, QueryRecordsLine_Item__c.class);
+ assertNotNull(queryRecords);
+ }
+
@Test
public void testQueryWithSObjectName() throws Exception {
createLineItem();
@@ -823,6 +840,13 @@ public class RestApiIntegrationTest extends
AbstractSalesforceTestBase {
from("direct:getBlobField")
.to("salesforce:getBlobField?sObjectName=Document&sObjectBlobFieldName=Body");
+ // testQuery
+ from("direct:queryDetectResponseClass")
+ .to("salesforce:query?sObjectQuery=SELECT Id, name,
Typeof Owner WHEN User Then Username End, recordTypeId, RecordType.Name "
+ + "from Line_Item__c "
+ + "ORDER BY CreatedDate DESC "
+ + "LIMIT 1");
+
// testQuery
from("direct:query")
.to("salesforce:query?sObjectQuery=SELECT Id, name,
Typeof Owner WHEN User Then Username End, recordTypeId, RecordType.Name "
@@ -833,8 +857,8 @@ public class RestApiIntegrationTest extends
AbstractSalesforceTestBase {
// testQuery
from("direct:queryWithSObjectName")
- .to("salesforce:query?sObjectQuery=SELECT Id, name,
Typeof Owner WHEN User Then Username End, recordTypeId, RecordType.Name from
Line_Item__c&sObjectName="
- + "QueryRecordsLine_Item__c");
+ .to("salesforce:query?sObjectQuery=SELECT Id, name,
Typeof Owner WHEN User Then Username End, recordTypeId, RecordType.Name from
Line_Item__c"
+ + "&sObjectName=QueryRecordsLine_Item__c");
// testQuery
from("direct:queryStreamResult")
@@ -885,6 +909,10 @@ public class RestApiIntegrationTest extends
AbstractSalesforceTestBase {
from("direct:apexCallGet")
.to("salesforce:apexCall?apexMethod=GET&apexUrl=Merchandise/{id}&sObjectName=Merchandise__c");
+ // testApexCall
+ from("direct:apexCallGetDetectResponseType")
+
.to("salesforce:apexCall?apexMethod=GET&apexUrl=Merchandise/{id}");
+
from("direct:apexCallGetWithId")
.to("salesforce:apexCall/Merchandise/?apexMethod=GET&id=dummyId" +
"&sObjectClass="
+ Merchandise__c.class.getName());