# Camel Salesforce component #

This component supports producer and consumer endpoints to communicate with Salesforce using Java DTOs. 
There is a companion maven plugin [camel-salesforce-plugin](https://github.com/dhirajsb/camel-salesforce-maven-plugin) that generates these DTOs. 

The component supports the following Salesforce APIs

## REST API ##

Producer endpoints can use the following APIs. Most of the APIs process one record at a time, the Query API can retrieve multiple Records. 

* getVersions - Gets supported Salesforce REST API versions
* getResources - Gets available Salesforce REST Resource endpoints
* getGlobalObjects - Gets metadata for all available SObject types
* getBasicInfo - Gets basic metadata for a specific SObject type
* getDescription - Gets comprehensive metadata for a specific SObject type
* getSObject - Gets an SObject using its Salesforce Id
* createSObject - Creates an SObject
* updateSObject - Updates an SObject using Id
* deleteSObject - Deletes an SObject using Id
* getSObjectWithId - Gets an SObject using an external (user defined) id field
* upsertSObject - Updates or inserts an SObject using an external id
* deleteSObjectWithId - Deletes an SObject using an external id
* query - Runs a Salesforce SOQL query
* queryMore - Retrieves more results (in case of large number of results) using result link returned from the 'query' API
* search - Runs a Salesforce SOSL query

For example, the following producer endpoint uses the upsertSObject API, with the sObjectIdName parameter specifying 'Name' as the external id field. 
The request message body should be an SObject DTO generated using the maven plugin. 
The response message will either be NULL if an existing record was updated, or [CreateSObjectResult] with an id of the new record, or a list of errors while creating the new object.

	...to("force:upsertSObject?sObjectIdName=Name")...

## Bulk API ##

Producer endpoints can use the following APIs. All Job data formats, i.e. xml, csv, zip/xml, and zip/csv are supported. 
The request and response have to be marshalled/unmarshalled by the route. Usually the request will be some stream source like a CSV file, 
and the response may also be saved to a file to be correlated with the request. 

* createJob - Creates a Salesforce Bulk Job
* getJob - Gets a Job using its Salesforce Id
* closeJob - Closes a Job
* abortJob - Aborts a Job
* createBatch - Submits a Batch within a Bulk Job
* getBatch - Gets a Batch using Id
* getAllBatches - Gets all Batches for a Bulk Job Id
* getRequest - Gets Request data (XML/CSV) for a Batch
* getResults - Gets the results of the Batch when its complete
* createBatchQuery - Creates a Batch from an SOQL query
* getQueryResultIds - Gets a list of Result Ids for a Batch Query
* getQueryResult - Gets results for a Result Id

For example, the following producer endpoint uses the createBatch API to create a Job Batch. 
The in message must contain a body that can be converted into an InputStream (usually UTF-8 CSV or XML content from a file, etc.) and header fields 'jobId' for the Job and 'contentType' for the Job content type, which can be XML, CSV, ZIP\_XML or ZIP\_CSV. The put message body will contain [BatchInfo] on success, or throw a [SalesforceException] on error.

	...to("force:createBatchJob")..

## Streaming API ##

Consumer endpoints can use the following sytax for streaming endpoints to receive Salesforce notifications on create/update. 

To create and subscribe to a topic

	from("force:CamelTestTopic?notifyForFields=ALL&notifyForOperations=ALL&sObjectName=Merchandise__c&updateTopic=true&sObjectQuery=SELECT Id, Name FROM Merchandise__c")...

To subscribe to an existing topic

	from("force:CamelTestTopic&sObjectName=Merchandise__c")...

## Developing the Camel Salesforce component

### Running the integration tests

**Note:** These instructions are only for running integration tests, they use permissions and IP restrictions that should be reconsidered for production use. 

**Note:** Running the tests you will quickly use up your API allowance, 15000 requests/day in the free developer account, make sure that you won't deny your other applications/users access by running them.

In order to run the integration tests you need a Salesforce Developer account. You can get a Salesforce Developer account by visiting [developer.salesforce.com](https://developer.salesforce.com/) and sign up for one.

As of 2.19 we maintain any Salesforce setup needed to run the integration tests in the `it/resources/salesforce` directory, the files there are generated by the _Salesforce Migration Tool_ that you can freely download from [Force.com Migration Tool](https://developer.salesforce.com/page/Force.com_Migration_Tool). This is an Apache Ant extension, by which you get additional Ant tasks to retrieve and to upload configuration, classes, schema changes and such. Download it and place the `ant-salesforce.jar` from the downloaded ZIP file into `components/camel-salesforce/it/resources/migration-tool/`.

We have integrated _Salesforce Migration Tool_ into the Maven _integration-test_ lifecycle phase and it should run and update your Salesforce instance to a state capable of running integration tests. Start by creating `test-salesforce-login.properties` in the parent Maven module (`camel-salesforce`), you can use `test-salesforce-login.properties.sample` as reference.

**Note:** Remember that if you do not relax IP restrictions, by default you'll need to append the security token on the password you place in the `test-salesforce-login.properties` file.

Before running the tests for the first time run the migration by invoking Maven from the `camel-salesforce-component` Maven module directory:

    $ mvn -Pintegration antrun:run@setup-salesforce-instance

This will create a _Connected App_ with predefined Consumer Key (the one mentioned in the comment one in `test-salesforce-login.properties.sample`) and a name of `CamelSalesforceIntegrationTests`. After running the migration access your Salesforce instance and provide _Consumer Secret_ (`clientSecret`) property to `test-salesforce-login.properties.sample`.

This however is run every time when you run the integration tests by issuing from the `camel-salesforce-component` Maven module directory:

    $ mvn -Pintegration verify

If you need any custom fields, Apex classes or other configuration changes done, make sure to download them using the _Salesforce Migration Tool_ and include them in `it/resources/salesforce` directory.

If your tests cannot be run alongside other tests you can use `@Category(Standalone.class)` to mark them as such.

#### Manual Salesforce instance setup for integration tests

This is include for those that wish to setup the Salesforce instance manually for integration tests.

Besides that account you'll need a _test user_ account that has `Bulk API Hard Delete` permission. You can create one by going to _My Developer Account_ (link from [developer.salesforce.com](https://login.salesforce.com/?lt=de)). Under _Administer_ expand _Manage Users_  and select _Profiles_ find _System Administrator_ profile and select _Clone_. Use `System Administrator With Hard Delete` as the profile name, and after saving under _Administrative Permissions_ click edit and tick _Bulk API Hard Delete_ and save. Next, create a new user under _Administer_ expand _Manage Users_  and select _Users_ and then click on _New User_. Fill in the required fields, and select _Salesforce_ for _User License_ and newly created profile for _Profile_. You get two user _Salesforce_ licenses so the newly created user will put you at a maximum.

Install the Warehouse package, tested with _Spring 2013_ (version 1.2) that can be installed from the [https://login.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000Pj8s](https://login.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000Pj8s), and make the following modifications manually:
 - add custom field `Description` of type `Text` with maxumum length of `100` on the `Merchandise` object
 - add custom **required** field `Total_Inventory` of type `Number` with maximum length of `18` without default value on the `Merchandise` object
 - add custom field `Shipping_Location` of type `GeoLocation` on the `Account` object
 - add custom field `Units_Sold` of `Number` type with maximum length of `18` on the `Line_Item` object
 - delete custom fields `Quantity`, `Invoice`, `Line_Item_Total` from the `Line_Item` object
 - delete custom field `Quantity` from the `Merchanidise` object, you will need to delete dependencies (ApexClass and Visualforce Page)
 - create new ApexClass named `MerchandiseRestResource` with the content of `MerchandiseRestResource.apxc`

You'll need to access a Merchandise record and run a `Test Report` in order for them to appear in _Recent Items_ and _Recent Reports_. Do this by accessing _Warehouse_ application from the menu in the top right, and selecting _Merchandise_ click _Go!_ (preselected is View: _All_) and click on the single Merchandise item available. Next go to Reports and select and run _Test Report_ from _Test Reports_. This is needed by the integration tests as they access recent items and recently run reports.

Create `Camel` connected application by selecting under _Apps_ in _Build_ and _Create_ sections by clicking _New_ in _Connected Apps_ section. Fill in the required fields and in the _API (Enable OAuth Settings)_ section thick _Enable OAuth Settings_ and move all scopes from _Available OAuth Scopes_ to _Selected OAuth Scopes_. For _Callback URL_ you can use any URL it's not needed by the REST API used by the Camel Salesforce component. Make note of _Consumer Key_ and _Consumer Secret_, or if your partner provide just _Consumer Refresh Token_ you'll need to specify them in `test-salesforce-login.properties`,  more on that below.

Next enable relaxed IP restrictions, by editing the policy of the _Camel_ connected application in _Connected Apps_ under _Administer_ and _Manage Apps_ pick _Relax IP restrictions_ for _IP Relaxation_.  

Create `test-salesforce-login.properties` in `camel-salesforce` directory (one up from the directory this file resides in) with the content:

    clientId=<Consumer Key of the `Camel` connected App>
    clientSecret=<Consumer Secret of the `Camel` connected app>
    refreshToken=<Consumer Refresh Token of the `Camel` connected app>
    userName=<Username of the user with the `System Administrator With Hard Delete` profile>
    password=<Password of the above user>
    loginUrl=https://login.salesforce.com/
    report.0=Test_Report


