Since we're on a major migration process of this website, some component documents here are out of sync right now. In the meantime you may want to look at the early version of the new website
https://camel.apache.org/staging/
We would very much like to receive any feedback on the new site, please join the discussion on the Camel user mailing list.
Salesforce componentAvailable as of Camel 2.12 This component supports producer and consumer endpoints to communicate with Salesforce using Java DTOs. Maven users will need to add the following dependency to their <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-salesforce</artifactId> <version>x.x.x</version> <!-- use the same version as your Camel core version --> </dependency> URI formatThe URI scheme for a salesforce component is as follows salesforce:topic?options You can append query options to the URI in the following format, Supported Salesforce APIsThe component supports the following Salesforce APIs Producer endpoints can use the following APIs. Most of the APIs process one record at a time, the Query API can retrieve multiple Records. Rest API
For example, the following producer endpoint uses the upsertSObject API, with the sObjectIdName parameter specifying 'Name' as the external id field. ...to("salesforce:upsertSObject?sObjectIdName=Name")... Rest Bulk APIProducer endpoints can use the following APIs. All Job data formats, i.e. xml, csv, zip/xml, and zip/csv are supported.
For example, the following producer endpoint uses the createBatch API to create a Job Batch. ...to("salesforce:createBatchJob").. Rest Streaming APIConsumer endpoints can use the following sytax for streaming endpoints to receive Salesforce notifications on create/update. To create and subscribe to a topic from("salesforce:CamelTestTopic?notifyForFields=ALL¬ifyForOperations=ALL&sObjectName=Merchandise__c&updateTopic=true&sObjectQuery=SELECT Id, Name FROM Merchandise__c")... To subscribe to an existing topic from("salesforce:CamelTestTopic&sObjectName=Merchandise__c")... ExamplesUploading a document to a ContentWorkspaceCreate the ContentVersion in Java, using a Processor instance: public class ContentProcessor implements Processor { public void process(Exchange exchange) throws Exception { Message message = exchange.getIn(); ContentVersion cv = new ContentVersion(); ContentWorkspace cw = getWorkspace(exchange); cv.setFirstPublishLocationId(cw.getId()); cv.setTitle("test document"); cv.setPathOnClient("test_doc.html"); byte[] document = message.getBody(byte[].class); ObjectMapper mapper = new ObjectMapper(); String enc = mapper.convertValue(document, String.class); cv.setVersionDataUrl(enc); message.setBody(cv); } protected ContentWorkspace getWorkSpace(Exchange exchange) { // Look up the content workspace somehow, maybe use enrich() to add it to a // header that can be extracted here .... } } Give the output from the processor to the Salesforce component: from("file:///home/camel/library") .to(new ContentProcessor()) // convert bytes from the file into a ContentVersion SObject // for the salesforce component .to("salesforce:createSObject"); Using Salesforce Limits APIWith salesforce:limits operation you can fetch of API limits from Salesforce and then act upon that data received. The result of salesforce:limits operation is mapped to org.apache.camel.component.salesforce.api.dto.Limits class and can be used in a custom processors or expressions. For instance, consider that you need to limit the API usage of Salesforce so that 10% of daily API requests is left for other routes. The body of output message contains an instance of org.apache.camel.component.salesforce.api.dto.Limits object that can be used in conjunction with Content Based Router and Spring Expression Language (SpEL) to choose when to perform queries. Notice how multiplying 1.0 with the integer value held in body.dailyApiRequests.remaining makes the expression evaluate as with floating point arithmetic, without it - it would end up making integral division which would result with either 0 (some API limits consumed) or 1 (no API limits consumed). from("direct:querySalesforce") .to("salesforce:limits") .choice() .when(spel("#{1.0 * body.dailyApiRequests.remaining / body.dailyApiRequests.max < 0.1}")) .to("salesforce:query?...") .otherwise() .setBody(constant("Used up Salesforce API limits, leaving 10% for critical routes")) .endChoice() Working with approvalsAll the properties are named exactly the same as in the Salesforce REST API prefixed with approval. You can set approval properties by setting approvalPropertyName of the Endpoint these will be used as template -- meaning that any property not present in either body or header will be taken from the Endpoint configuration. Or you can set the approval template on the Endpoint by assigning approval property to a reference onto a bean in the Registry You can also provide header values using the same approvalPropertyName in the incoming message headers. And finally body can contain one AprovalRequest or an java.util.Iterable of ApprovalRequest objects to process as a batch. The important thing to remember is the priority of the values specified in these three mechanisms:
For example to send one record for approval using values in headers use: Given a route: from("direct:example1") .setHeader("approval.ContextId", simple("${body['contextId']}")) .setHeader("approval.NextApproverIds", simple("${body['nextApproverIds']}")) .to("salesforce:approval?" + "approval.actionType=Submit" + "&approval.comments=this is a test" + "&approval.processDefinitionNameOrId=Test_Account_Process" + "&approval.skipEntryCriteria=true"); You could send a record for approval using: final Map<String, String> body = new HashMap<>(); body.put("contextId", accountIds.iterator().next()); body.put("nextApproverIds", userId); final ApprovalResult result = template.requestBody("direct:example1", body, ApprovalResult.class); Using Salesforce Recent Items APITo fetch the recent items use salesforce:recent operation. This operation returns an java.util.List of org.apache.camel.component.salesforce.api.dto.RecentItem objects (List<RecentItem>) that in turn contain the Id, Name and Attributes (with type and url properties). You can limit the number of returned items by specifying limit parameter set to maximum number of records to return. For example: from("direct:fetchRecentItems") to("salesforce:recent") .split().body() .log("${body.name} at ${body.attributes.url}"); Using Salesforce Composite API to submit SObject treeTo create up to 200 records including parent-child relationships use Note that for some records operation can succeed and for some it can fail — so you need to manually check for errors. Easiest way to use this functionality is to use the DTOs generated by the camel-salesforce-maven-plugin , but you also have the option of customizing the references that identify the each object in the tree, for instance primary keys from your database.Lets look at an example:
Account account = ... Contact president = ... Contact marketing = ... Account anotherAccount = ... Contact sales = ... Asset someAsset = ... // build the tree SObjectTree request = new SObjectTree(); request.addObject(account).addChildren(president, marketing); request.addObject(anotherAccount).addChild(sales).addChild(someAsset); final SObjectTree response = template.requestBody("salesforce:composite-tree", tree, SObjectTree.class); final Map<Boolean, List<SObjectNode>> result = response.allNodes() .collect(Collectors.groupingBy(SObjectNode::hasErrors)); final List<SObjectNode> withErrors = result.get(true); final List<SObjectNode> succeeded = result.get(false); final String firstId = succeeded.get(0).getId(); Using Salesforce Composite API to submit multiple requests in a batchThe Composite API batch operation (
Lets look at an example: final String acountId = ... final SObjectBatch batch = new SObjectBatch("38.0"); final Account updates = new Account(); updates.setName("NewName"); batch.addUpdate("Account", accountId, updates); final Account newAccount = new Account(); newAccount.setName("Account created from Composite batch API"); batch.addCreate(newAccount); batch.addGet("Account", accountId, "Name", "BillingPostalCode"); batch.addDelete("Account", accountId); final SObjectBatchResponse response = template.requestBody("salesforce:composite-batch?format=JSON", batch, SObjectBatchResponse.class); boolean hasErrors = response.hasErrors(); // if any of the requests has resulted in either 4xx or 5xx HTTP status final List<SObjectBatchResult> results = response.getResults(); // results of three operations sent in batch final SObjectBatchResult updateResult = results.get(0); // update result final int updateStatus = updateResult.getStatusCode(); // probably 204 final Object updateResultData = updateResult.getResult(); // probably null final SObjectBatchResult createResult = results.get(1); // create result @SuppressWarnings("unchecked") final Map<String, Object> createData = (Map<String, Object>) createResult.getResult(); final String newAccountId = createData.get("id"); // id of the new account, this is for JSON, for XML it would be createData.get("Result").get("id") final SObjectBatchResult retrieveResult = results.get(2); // retrieve result @SuppressWarnings("unchecked") final Map<String, Object> retrieveData = (Map<String, Object>) retrieveResult.getResult(); final String accountName = retrieveData.get("Name"); // Name of the retrieved account, this is for JSON, for XML it would be createData.get("Account").get("Name") final String accountBillingPostalCode = retrieveData.get("BillingPostalCode"); // Name of the retrieved account, this is for JSON, for XML it would be createData.get("Account").get("BillingPostalCode") final SObjectBatchResult deleteResult = results.get(3); // delete result final int updateStatus = deleteResult.getStatusCode(); // probably 204 final Object updateResultData = deleteResult.getResult(); // probably null Camel Salesforce Maven PluginThis Maven plugin generates DTOs for the Camel Salesforce. UsageThe plugin configuration has the following properties.
For obvious security reasons it is recommended that the clientId, clientSecret, userName and password fields be not set in the pom.xml. mvn camel-salesforce:generate -DclientId=<clientid> -DclientSecret=<clientsecret> -DuserName=<username> -Dpassword=<password> The generated DTOs use Jackson and XStream annotations. All Salesforce field types are supported. Date and time fields are mapped to Joda DateTime, and picklist fields are mapped to generated Java Enumerations. |