Integration Workbook

25
Integration Workbook: Spring '12 Integration Workbook Last updated: March 7 2012 © Copyright 20002012 salesforce.com, inc. All rights reserved. Salesforce.com is a registered trademark of salesforce.com, inc., as are other names and marks. Other marks appearing herein may be trademarks of their respective owners.

Transcript of Integration Workbook

Page 1: Integration Workbook

Integration Workbook: Spring '12

Integration Workbook

Last updated: March 7 2012

© Copyright 2000–2012 salesforce.com, inc. All rights reserved. Salesforce.com is a registered trademark of salesforce.com, inc., as are othernames and marks. Other marks appearing herein may be trademarks of their respective owners.

Page 2: Integration Workbook
Page 3: Integration Workbook

Table of Contents

Force.com Integration Workbook.........................................................................................................2

Before You Begin.................................................................................................................................3

Tutorial #1: Configure Remote Access Settings.....................................................................................5

Tutorial #2: Create a Merchandise Item Using Java................................................................................7Step 1: Update the Properties File.............................................................................................................................................7Step 2: Read the Properties File................................................................................................................................................8Step 3: Log In with OAuth.......................................................................................................................................................8Step 4: Add Data Via the API..................................................................................................................................................9Step 5: Compile and Run the App..........................................................................................................................................10Java Integration Summary.......................................................................................................................................................11

Tutorial #3: Create a Merchandise Item Using C#................................................................................12Step 1: Update the Properties File...........................................................................................................................................12Step 2: Read the Properties File..............................................................................................................................................12Step 3: Log In with OAuth.....................................................................................................................................................13Step 4: Add Data Via the API................................................................................................................................................14Step 5: Compile and Run the App..........................................................................................................................................15C# Summary...........................................................................................................................................................................15

Tutorial #4: Connecting the Warehouse App with an External Service .................................................17Step 1: Create an External ID Field on Invoice Statement.....................................................................................................17Step 2: Create a Remote Site Record for the Fulfillment Web Service...................................................................................17Step 3: Create an @future Method to Post Invoice Statements to the Fulfillment Web Service............................................18Step 4: Test the @future Method............................................................................................................................................20Step 5: Create a Trigger to Call the @future Method.............................................................................................................21Step 6: Test the Integration.....................................................................................................................................................22Summary.................................................................................................................................................................................23

i

Table of Contents

Page 4: Integration Workbook

Force.com Integration WorkbookOne of the most frequent tasks Force.com developers undertake is integrating Force.com apps with existing applications. Thetutorials within this workbook are designed to introduce the technologies and concepts required to achieve this functionality.

The Force.com Integration Workbook is intended to be the companion to the Force.com Workbook. The series of tutorialsprovided here extend the Warehouse application by connecting it with an on-premise buyer application, and a cloud-basedfulfillment app.

Intended AudienceThis workbook is intended for developers new to the Force.com platform but have existing experience in Java or C#.

Tell Me More....This workbook is designed so that you can go through the steps as quickly as possible. At the end of some steps, there is anoptional Tell Me More section with supporting information.

• You can find the latest version of this and other workbooks at developer.force.com/workbooks.• To learn more about Force.com and to access a rich set of resources, visit Developer Force at

http://developer.force.com.

2

Force.com Integration Workbook

Page 5: Integration Workbook

Before You BeginBefore you begin the tutorials, you must have completed at least tutorials 1 through 8 in the Force.com Workbook. You’ll alsoneed Administrator privileges to your local machine. In addition, this workbook requires you to install some software components(either the Java SDK, or .NET Framework depending on the tutorials you complete) and download the necessary tutorialfiles.

Java Tutorial Files1. Download this file: http://bit.ly/aw2012-java.2. Unzip the files to a folder you can find easily. Putting it on your desktop is a convenient place.3. You should see a folder with the following:

4. To verify that your system can build Java projects, run the appropriate checkinstall program for your configuration:

• For Windows, double click checkinstall.bat.• For OS X, double click checkinstall.command.

5. If the check is successful, you’ll get a success message, and you can close the window and proceed with the tutorials. Ifnot, a Web browser will open to the Oracle download page for the Java SDK. Follow the online download instructionsfor your version of Windows. Once you’ve installed the Java SDK, you can test your installation by re-running the checkinstallprogram.

Note: For most Windows based PCs, you should download the Windows x86 version of the Java SDK.

3

Before You Begin

Page 6: Integration Workbook

C# Tutorial Files1. Download this file: http://bit.ly/aw2012-csharp.2. Unzip the files to a folder you can find easily.3. You should see a folder with the following:

4. Verify that your system can compile C# projects by double clicking checkinstall.bat (the file extension may notappear in the folder view).

5. If the check is successful, you’ll see a command window displaying a success message: SUCCESS: csc.exe file found.You can then close the window and proceed with the tutorials. If unsuccessful, the script will open an Internet Explorerwindow to the download page for the required .NET Framework. Follow the online download instructions for your versionof Windows. Once you have installed the .NET Framework, you can test your installation by re-runningcheckinstall.bat.

4

Before You Begin

Page 7: Integration Workbook

Tutorial #1: Configure Remote Access SettingsExternal applications must authenticate remotely before they may access data. Force.com supports OAuth 2.0 (hereafterreferred to as OAuth) as an authentication mechanism.

With OAuth, a client application delegates the authentication to a provider, in this case Force.com, which in turn issues anaccess token if the user successfully authenticates. As a result, your application doesn't need to handle authentication explicitly;it simply needs to ensure that a valid access token accompanies all interactions with the API. You can typically download anOAuth library to do the heavy lifting.

Before an application can use OAuth, you have to configure your environment. Log in to your Force.com organization as anadministrator and configure a remote access application.

1. Navigate to App > Setup > Develop > Remote Access.2. Click New.3. For Application, enter Buyer Client.4. For Callback URL, enter warehouse://success5. For Email, enter your email address.6. Click Save.

The detail page for your remote access configuration will display a consumer key as well as a consumer secret (which you haveto click to reveal). You'll need these in later tutorials.

5

Tutorial #1: Configure Remote Access Settings

Page 8: Integration Workbook

Tell Me More....If you're familiar with OAuth, you'll understand that the callback URL is traditionally the URL that a user's browser isredirected to after a successful authentication transaction. For our sample application, however, we’ll use the user/passwordflow of OAuth. Our application doesn’t have a user interface so we can’t present a login screen to delegate authentication backto Force.com. The user/password flow is often used for existing on-premise apps, while delegated authentication is morecommon in mobile application scenarios.

6

Tutorial #1: Configure Remote Access Settings

Page 9: Integration Workbook

Tutorial #2: Create a Merchandise Item Using JavaBuyers, in our fictitious scenario, use a mix of mobile apps and existing systems to buy products. Once a buy has been completed,the new Merchandise item needs to be reflected in the Warehouse app.

In this tutorial, we use Java to create an application for entering a new Merchandise item into our Warehouse app. Our samplebuyer app will use a properties file to hold the information specific to your Force.com organization and to describe the itembeing entered. This is a simple example of using an application to integrate with the Force.com platform. While, in this case,we’ll be entering the information about the item manually, the text file may in the real world be updated by a different processwhich could then use this sample application to automatically keep the warehouse inventory updated.

Step 1: Update the Properties FileBefore the app can communicate with the server, you’ll need to let the application know a few things about the Force.comorganization it will be communicating with.

1. Navigate to the folder where you unzipped the Java tutorial files.2. Open AddMerchandise.properties in a text editor.3. Replace {USERNAME} with your Force.com username. Be sure to replace all of {USERNAME}, including the curly bracket

characters.4. Log into your Force.com organization.5. Go to Setup > My Personal Information > Reset My Security Token and press Reset Security Token. A new security

token will be sent to the email address registered with your user account.6. In AddMerchandise.properties, replace {PASSWORD} with your Force.com password and the security token sent to

your email address. If your password is “mypassword” and your security token is “AAAA1111”, you would replace{PASSWORD} with “mypasswordAAAA1111”. Again, be sure to replace all of {PASSWORD}, including the curly bracketcharacters.

7. Go to Setup > Develop > Remote Access and open the Remote Access application you created earlier.8. Click Click to Reveal.9. Copy the text next to client.id and replace {PUBLICKEY} with the text.10. Similarly, copy the text next to client.secret and replace {PRIVATEKEY} with the text.11. Where it reads merchandise.name, enter Tiny Top after the = sign.12. Where it reads merchandise.inventory, enter 5 after the = sign.13. Where it reads merchandise.description, enter Shiny Top after the = sign.14. For now, leave merchandise.price intentionally blank.15. Save the file.

You may remember that Price was a required field for the Merchandise object. We’re keeping that field blank for now toshow how the API reacts when an application using the API attempts to insert an object that doesn’t meet the validation rulesspecified in your app.

7

Tutorial #2: Create a Merchandise Item Using Java

Page 10: Integration Workbook

Step 2: Read the Properties FileNow let’s take a look at the Java code to see how these properties are read.

1. Navigate to src/com/samples/onpremise from where you unzipped the Java tutorial files.2. Open AddMerchandise.java in your text editor.3. Scroll down to the main() function.

The main() function acts as the starting point for our application, and is executed when it’s run from the command line. Thefollowing code snippet loads the username and password information.

public static void main(String [] args){Properties props = new Properties();try {

props.load(new FileInputStream("AddMerchandise.properties"));String username = props.getProperty("username");String password = props.getProperty("password");

if (username == null || username.trim().equals("") ||password == null || password.trim().equals("")){throw new IllegalArgumentException("Provide a username and password in the properties file");

...}

Tell Me More....The function first loads in the properties file and attempts to read the username and password into variables. If the usernameor password information in the properties file is invalid, an error exception is thrown. After the function reads all the properties,it’s ready to log in by calling login2ForceDotCom.

ForceLogin login = login2ForceDotCom(username, passsword, clientId, clientSecret, loginURL);

In the next tutorial we’ll take a look at this function and how OAuth works.

Step 3: Log In with OAuthSince OAuth is based on HTTP protocols, all we need to do to communicate with it is set up the correct HTTP GET andPOST calls and then parse the JSON (JavaScript Object Notation) results. To get this functionality in our application, we’lluncomment some existing code.

• AddMerchandise.java should still be open in your text editor, so scroll down to login2ForceDotCom and uncommentthe function. To do so, remove the “/*” and “*/” characters shown here:

/* private static ForceLogin login2ForceDotCom(String uName,String pwd,String id,String secret,String url){

...e.printStackTrace();

}return null;

} */

8

Tutorial #2: Create a Merchandise Item Using Java

Page 11: Integration Workbook

The following code snippet shows where the function makes the actual callout to OAuth:

postURL+="/services/oauth2/token?grant_type=password&client_id="+id+"&client_secret="+secret+"&username="+uName+"&password="+pwd;

DefaultHttpClient httpclient = new DefaultHttpClient();HttpPost post = new HttpPost(postURL);

try {HttpResponse response = httpclient.execute(post);final int statusCode = response.getStatusLine().getStatusCode();if (statusCode != HttpStatus.SC_OK) {

System.out.println("Error authenticating to Force.com:"+statusCode);System.out.println("Error is:"+EntityUtils.toString(response.getEntity()));return null;

}

This method creates the URL with the correct parameters, including the consumer public and private keys to correctly identifythe application and the user’s username and password. Normally, an authentication flow with OAuth would use the browserto redirect the user without requiring the application to know the username and password, so that the user only needs to sharetheir credentials with the first party provider of them.

In this case we’re designing an application for your internal use which might be automated later and have no human intervention.We’re going to use the “password” grant type of OAuth in order to authenticate with the username and password.

Upon receiving a successful response, the application will need to get the access token from OAuth. This access token providesaccess to a valid session against the Force.com platform and will allow us to start manipulating data. We also need to knowthe specific pod the user is using, for example https://na1.salesforce.com versus https://na8.salesforce.com.

To get this, the JSON library will parse the result:

String result = EntityUtils.toString(response.getEntity());

JSONObject object = (JSONObject) new JSONTokener(result).nextValue();ForceLogin login = new AddMerchandise().new ForceLogin();login.accessToken = object.getString("access_token");login.instanceUrl = object.getString("instance_url");return login;

It stores the result as a ForceLogin object for easier access. Now that we have a valid ForceLogin with the access tokenand the user’s instance URL, we can start adding in some data.

Step 4: Add Data Via the APILike OAuth, REST also utilizes standard HTTP protocols for communication. This makes it very easy to format data thatthe API will understand. Since we want to insert new data, we’re going to use the corresponding HTTP POST method to senddata to a specific endpoint (a RESTful resource) for our Merchandise object.

• In your text editor, scroll down to addMerchandise and uncomment the function. To do so, remove the “/*” and “*/”characters shown here:

/* private static String addMerchandise(ForceLogin login,String name,String price,String desc,String inventory){

...

9

Tutorial #2: Create a Merchandise Item Using Java

Page 12: Integration Workbook

e.printStackTrace();}return null;

} */

The first step is to create a JSON representation of the data retrieved from the AddMerchandise.properties file:

JSONObject mechandise = new JSONObject()'

try {if (name != null && !name.trim().equals("")) mechandise.put("Name", name);if (price != null && !price.trim().equals("")) mechandise.put("Price__c", price);if (desc != null && !desc.trim().equals("")) mechandise.put("Description__c", desc);if (inventory != null && !inventory.trim().equals(""))

mechandise.put("Total_Inventory__c", inventory);

We then submit this information to the REST API with the OAuth login information embedded in the header. This allowsfor a secure transaction of information for the API to work with; and without it, the API would refuse the request.

String restResourceURI = login.instanceUrl +"/services/data/v23.0/sobjects/Merchandise__c/";

HttpPost post = new HttpPost(restResourceURI);StringEntity se = new StringEntity(mechandise.toString());post.setEntity(se);post.setHeader("Authorization", "OAuth " + login.accessToken);post.setHeader("Content-type", "application/json");

DefaultHttpClient client = new DefaultHttpClient();HttpResponse resp = client.execute(post);String result = EntityUtils.toString(resp.getEntity());

if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED){JSONObject ret = ((JSONArray) new JSONTokener(result).nextValue()).getJSONObject(0);

System.out.println("Could not create new Merchandise record:"+resp.getStatusLine().getStatusCode());

System.out.println("Error code:"+ret.getString("errorCode"));System.out.println("Error message:"+ret.getString("message"));return null;

}else{

return ((JSONObject) new JSONTokener(result).nextValue()).getString("id");}

} catch (Exception e) {e.printStackTrace();

}

We’ll then post this to the Merchandise endpoint of the REST API. Notice that even though the Merchandise object is acustom object created through the declarative process, there was no step needed to expose it through the API. We’re nowready to compile and run the application.

Step 5: Compile and Run the AppDepending on whether you’re developing on a PC or Mac, the steps required to compile and run the application are different.Follow the correct steps for your platform.

1. Go to the folder where you downloaded the Java tutorial files.

10

Tutorial #2: Create a Merchandise Item Using Java

Page 13: Integration Workbook

2. For Windows, double-click compileandrun.bat. For OS X, double-click compileandrun.command.

Note: Depending on your machine performance, the app may take approximately 30 seconds to compile. If thisis the first run, you may see a warning indicating that the classes folder doesn’t exist. This folder will be createdfor you upon first execution.

3. You’ll see a Classes Compiled message indicating that your local app has been built successfully, and will now attempt toadd the new Merchandise item to the Warehouse app. If any errors exist in the application, they’ll be displayed after theClasses Compiled message.

Note: If you received any compilation errors, go ahead and debug and fix those now.

4. If your local app has compiled successfully and has connected to Force.com, you’ll see an error message like the following.Don’t worry, this is what we were expecting!

Error code:REQUIRED_FIELD_MISSINGError message:Required fields are missing: [Price__c]

So what’s going on with our app? At this point, your application is going to authenticate with Force.com, and attempt to insertyour new merchandise item via the REST API. Unfortunately for us, it’ll fail. Your app failed because the API enforces allthe validation rules put in place by the data model on the Force.com platform, regardless of how you connect. The API returnsa helpful error message indicating that a required field, Price__c, is missing. That’s right, we didn’t enter price into theAddMerchandise.properties file. Let’s remedy that now.

1. Open AddMerchandise.properties in a text editor.2. Where it reads merchandise.price, add 5.99 after the = sign.3. Save the file.4. Return to the folder with the Java project files.5. For Windows, double click run.bat. For OS X, double click run.command.

Now you’ll receive a message that the item was entered correctly and give you the resulting ID of that item. You can use thisunique ID within your application any time you want to work with your new merchandise item. Right now, our sample apponly supports inserts, though.

Java Integration SummaryYou just created a small application and a properties file to simulate our on-premise buyer application written in Java. Thisapp was able to communicate with the Force.com platform in a secure manner using OAuth for authentication, and standardRESTful calls and JSON to transport data. Using the standard HTTP libraries with Java, it’s easy to integrate between thirdparty systems and the Warehouse app we created on the Force.com platform.

11

Tutorial #2: Create a Merchandise Item Using Java

Page 14: Integration Workbook

Tutorial #3: Create a Merchandise Item Using C#In this tutorial we will use the C# (pronounced C-sharp) language to create an application for entering a new Merchandiseitem into our warehouse app. Buyers, in our fictitious scenario, use a mix of mobile apps and existing systems to buy products.Once a buy has been completed, the new Merchandise item needs to be reflected in the Warehouse. Our sample buyer appwill use a properties file to hold the information specific to your Force.com organization and to describe the item being entered. While in this case we’ll be entering the information about the item manually, the text file may in the real world be updatedby a different process which could then use this sample application to automatically keep the warehouse inventory updated.

Step 1: Update the Properties FileBefore the app can communicate with the server, we’ll need to provide the application with some information about theForce.com organization it’s communicating with.

1. Navigate to the folder where you unzipped the C# tutorial files.2. Open AddMerchandise.txt in a text editor.3. Replace {USERNAME} with your Force.com username. Be sure to replace all of {USERNAME}, including the curly bracket

characters.4. Log into your Force.com organization.5. If you have already reset your security token when you did the Java tutorial, you can skip the following step. Otherwise,

go to Setup > My Personal Information > Reset My Security Token and press Reset Security Token. A new securitytoken will be sent to the email address registered with your user account.

6. In AddMerchandise.txt, replace {PASSWORD} with your Force.com password and the security token sent to your emailaddress. If your password is “mypassword” and your security token is “AAAA1111”, you would replace {PASSWORD} with“mypasswordAAAA1111”. Again, be sure to replace all of {PASSWORD}, including the curly bracket characters.

7. Go to Setup > Develop > Remote Access and open the Remote Access application you created earlier.8. Click Click to Reveal.9. Copy the text next to client.id and replace {PUBLICKEY} with the text.10. Similarly, copy the text next client.secret and replace {PRIVATEKEY} with the text.11. Where it reads merchandise.name, enter Tiny Top after the = sign.12. Where it reads merchandise.inventory, enter 5 after the = sign.13. Where it reads merchandise.description, enter Shiny Top after the = sign.14. For now, leave merchandise.price intentionally blank.15. Save the file.

You may remember that Price was a required field for the Merchandise object - we are keeping that blank for now to showhow the API will react when an application using the API attempts to insert an object which doesn’t meet the validation rulesspecified in your app.

Step 2: Read the Properties FileNow let’s take a look at the actual C# code to see how these properties will be read.

12

Tutorial #3: Create a Merchandise Item Using C#

Page 15: Integration Workbook

1. Navigate to where you unzipped the C# tutorial files.2. Open AddMerchandise.cs in a text editor.3. Scroll down to the main() function.

The main() function acts as the starting point for our application, and is executed when it’s run from the command line. Themain() function calls the constructor AddMerchandise method, which reads the properties we defined inAddMerchandise.txt by running through the lines and parsing the information into an array:

public AddMerchandise() {properties = new Dictionary<string, string>();foreach (String row in File.ReadAllLines("AddMerchandise.txt")){

properties.Add(row.Split('=')[0], row.Split('=')[1]);}

}

The application now has a record of the information you entered into AddMerchandise.txt and is ready to log in to theAPI using OAuth.

Step 3: Log In with OAuthSince OAuth is based on HTTP protocols, all we need to do to communicate with it is set up the correct HTTP GET andPOST calls and then parse the JSON (JavaScript Object Notation) results. To get this functionality in our application, we’lluncomment some existing code.

• In your text editor, scroll down and uncomment the login() function. To do so, remove the “/*” and “*/” charactersshown here:

/*public Boolean login(){

...}

*/

This is where the function makes the actual callout to OAuth:

try {string login_params = oauthoptions + "&client_id=" + properties["consumerkey"] +

"&client_secret=" + properties["privatekey"] + "&username=" +properties["username"] + "&password=" + properties["password"];

string responseFromServer = doHTTPRequest(properties["login_url"] + oauthendpoint,login_params, "", false);

string[] data = responseFromServer.Split(':');token = data[7];token = token.Substring(1, token.Length - 1);token = token.Replace("\"}", "");

instance_url = data[5];instance_url = instance_url.Substring(2, instance_url.Length - 2);instance_url = instance_url.Substring(0, instance_url.IndexOf("\""));

It creates the URL with the correct parameters, including the consumer public and private keys to correctly identify theapplication and the user’s username and password. Normally, an authentication flow with OAuth would use the browser to

13

Tutorial #3: Create a Merchandise Item Using C#

Page 16: Integration Workbook

redirect the user without requiring the application to know the username and password, so that the user only needs to sharetheir credentials with the first party provider of them.

In this case, though, we’re designing an application for your internal use which might be automated later and have no humanintervention. For this use case, it make sense to use the “password” grant type of OAuth in order to authenticate with theusername and password.

Upon getting a successful response, the application will need to get the access token from OAuth. This access token providesaccess to a valid session against the Force.com platform and allows us to start working with data. We also need to know thespecific instance the user is using, for example, https://na1.salesforce.com versus https://na8.salesforce.com.

Step 4: Add Data Via the APILike OAuth, REST also utilizes standard HTTP protocols for communication. This makes it very easy to format data thatthe API understands. Since we want to insert new data, we’ll use the corresponding HTTP POST method to send data to aspecific endpoint (a RESTful resource) for our Merchandise object.

• In your text editor, scroll down and uncomment the insertItem function. To do so, remove the “/*” and “*/” charactersshown here:

/*public void insertItem(){

...}

*/

The first step is to create a JSON representation of the data entered into the AddMerchandise.txt file:

string postData = "{\"Name\" : \"" + properties["merchandise.name"] + "\"";if(properties["merchandise.price"] != "") {

postData += ", \"Price__c\" : " + properties["merchandise.price"];}if(properties["merchandise.inventory"] != "") {

postData += ", \"Total_Inventory__c\" : " + properties["merchandise.inventory"];}if(properties["merchandise.description"] != "") {

postData += ", \"Description__c\" : \"" + properties["merchandise.description"]+"\"";

}postData += "}";

We’ll then post this to the Merchandise endpoint of the REST API, using the OAuth information embedded in headers.This allows for the secure transaction of information; and without it, the API would refuse the request. Notice that eventhough the Merchandise object is a custom object created through the declarative process, there was no step needed to exposeit through the API. We can send data just by creating an HTTP POST request, sending it to the endpoint, and then parsingthe string for results to show to the user.

string endpoint = "https://" + instance_url + "/services/data/v" + properties["api"] +

"/sobjects/Merchandise__c";

string responseFromServer = doHTTPRequest(endpoint, postData, token, true);

14

Tutorial #3: Create a Merchandise Item Using C#

Page 17: Integration Workbook

We’re now ready to compile and run the application.

Step 5: Compile and Run the AppNow that the code is constructed, let’s compile and test out the application.

1. Navigate to where you unzipped the C# tutorial files.2. Double click compileandrun.bat.3. The application will be compiled, and if this is the first run, you may see a warning indicating that the classes folder doesn’t

exist. This folder is created for you upon first execution. Depending on your machine performance, the app may takeapproximately 30 seconds to compile. If all goes well, you’ll see a Compile Complete message indicating your local apphas been built successfully and will now attempt to add the new Merchandise item to the Warehouse app. If any errorsexist in the application, they’ll be displayed above the Compile Complete message.

4. If you received any compilation errors, go ahead and debug and fix those now. When you’re ready, re-runcompileandrun.bat.

5. If your local app has compiled successfully and connected to Force.com, you’ll see an error message like this. Don’t worry,this is what we were expecting!

"message":"Required fields are missing: Price__c"

So what’s going on with our app? At this point, your application is going to authenticate with Force.com and attempt to insertyour new merchandise item via REST API. Unfortunately for us, it’ll fail. Your app failed because the API enforces all thevalidation rules put in place by the data model on the Force.com platform, regardless on how you connect. The API returnsa helpful error message indicating a required field, Price__c, is missing. That’s right, we didn’t enter price into theAddMerchandise.txt file. Let’s remedy that now.

1. Open AddMerchandise.txt in a text editor.2. Where it reads merchandise.price, add 5.99 after the = sign.3. Save the file.4. Return to Windows Explorer and double-click run.bat.5. You’ll see a success message with an ID:

"id":"a0KC000000065pOhMAI""errors":"""success":"true"

The message indicates the item was entered correctly and gives you the resulting ID of that item. You can use this unique IDwithin your application any time you want to work with your new merchandise item (for example, to update the descriptionor price). Right now, our sample app only supports inserts though.

C# SummaryYou just created a small application and a properties file to simulate our on-premise buyer application written in C#. This appwas able to communicate with the Force.com platform in a secure manner using OAuth for authentication, and standard

15

Tutorial #3: Create a Merchandise Item Using C#

Page 18: Integration Workbook

RESTful calls and JSON to transport data. Using the standard HTTP libraries with Java, it is easy to create integrationsbetween third party systems and the Warehouse app we created on the Force.com platform.

16

Tutorial #3: Create a Merchandise Item Using C#

Page 19: Integration Workbook

Tutorial #4: Connecting the Warehouse App with anExternal Service

Force.com offers several ways to integrate with external systems; for example, Workflow allows configuration of outboundemail alerts and simple Web Service calls, while more complex scenarios can be implemented programmatically in Apex code.

In this tutorial you will integrate the warehouse app with an existing fulfillment system via a Web Service callout. Thisfulfillment system, written in Node.js is hosted on Heroku, but it could be any application with a Web Service interfaceaccessible via the cloud. Our requirements are pretty straight-forward: When an invoice statement's status changes to 'Closed',a JSON-formatted message will be sent to an order fulfillment service, which will return an order ID. This order ID must besaved on the invoice statement. Let’s get started.

Step 1: Create an External ID Field on Invoice StatementYou will need to create a custom field on the Invoice Statement custom object to hold the order ID. Since the field will be anindex into an external system, you will mark it as an External ID.

1. Go to the Invoice Statement custom object by clicking Your Name > Setup > Create > Create > Objects > InvoiceStatement.

2. Scroll down to Custom Fields & Relationships, click New and fill in the field settings.3. Select the Text field type and click Next.4. Enter OrderId as the field label, and enter 6 as the field length. Leave the field name as the default OrderId.5. Click the External ID checkbox and click Next.6. Click Next to accept the defaults, then click Save.

Step 2: Create a Remote Site Record for the Fulfillment Web ServiceThe Force.com platform implements very conservative security controls. By default, calls to external sites are prohibited. Beforeany Apex callout can call an external site, that site must be registered in the Remote Site Settings page, or the call will fail.

Note: Creating a Remote Site is not the same as configuring Remote Access (that we did in Tutorial 1). RemoteAccess allows authenticated access to Salesforce from external clients, whereas Remote Sites are external sites thatSalesforce needs access to.

1. Click Your Name > Setup > Security Controls > Remote Site Settings.2. Click New Remote Site and fill in the site settings.3. In the Remote Site Name field, enter FulfillmentWebService (no spaces).4. In the Remote Site URL field, enter https://fulfillment.herokuapp.com.5. Leave all other values as they are and click Save.

Now any Apex code in your app will be able to call the fulfillment Web Service.

17

Tutorial #4: Connecting the Warehouse App with an External Service

Page 20: Integration Workbook

Tell Me More....If you like, you can skip Step 2 and create and test the callout in Step 3 and Step 4 below to observe the error message that isgenerated when an app attempts to callout to a URL without permission. Don't forget to come back and add the remote siterecord, though!

Step 3: Create an @future Method to Post Invoice Statements to theFulfillment Web Service

Now that your app is allowed to access an external URL, it's time to implement the callout. Apex Triggers are not permittedto make synchronous Web Service calls. This restriction is to ensure a long running Web Service does not hold a lock on arecord within your app. In order to achieve our requirements, we'll create an asynchronous method with the @futureannotation. When the Trigger calls the asynchronous method, the call will be queued, and execution of the Trigger willcomplete. Some short time later, the queued method will execute and post the invoice to the order fulfillment Web Service.

1. Go to Apex Classes by clicking Your Name > Setup > Develop > Apex Classes.2. Click New and paste in the following code.

Note: You can also download the code here, http://bit.ly/aw2012-apexint

public class Integration {public class IntegrationException extends Exception {}public class ExternalOrder {

public String id {get; set;}public String order_number {get; set;}

}// Post an array of invoices to the fulfillment service// This method is designed such that there are only two// queries regardless of the number of invoice IDs passed@future (callout=true)public static void postOrder(List<Id> invoiceIds) {

// Get all the line items we'll needList<Line_Item__c> lineItems =[SELECT Name, Merchandise__c, Invoice_Statement__c, Units_Sold__cFROM Line_Item__c

WHERE Invoice_Statement__c IN :invoiceIds];

// Now group the line items by invoiceMap<Id, Map<String, Line_Item__c>> lineItemsByInvoice =new Map<Id, Map<String, Line_Item__c>>();

for (Line_Item__c lineItem : lineItems) {Map<String, Line_Item__c> lineItemMap =lineItemsByInvoice.get(lineItem.Invoice_Statement__c);if (lineItemMap == null ) {

lineItemMap = new Map<String, Line_Item__c>();lineItemsByInvoice.put(lineItem.Invoice_Statement__c, lineItemMap);

}lineItemMap.put(lineItem.Name, lineItem);

}// Create the JSON stringJSONGenerator gen = JSON.createGenerator(true);gen.writeStartArray();for (Id invoiceId : invoiceIds) {

18

Tutorial #4: Connecting the Warehouse App with an External Service

Page 21: Integration Workbook

// Get the invoice name. We'll also need the invoice record// later to set the order ID and update itgen.writeStartObject();gen.writeStringField('id', invoiceId);// Make a list of the line item names and sort itMap<String, Line_Item__c> lineItemMap = lineItemsByInvoice.get(invoiceId);List<String> lineItemNames = new List<String>(lineItemMap.keySet());lineItemNames.sort();// Now we can write the line itemsgen.writeFieldName('line_items');gen.writeStartArray();for ( String name : lineItemNames ) {gen.writeObject(lineItemMap.get(name));

}gen.writeEndArray();gen.writeEndObject();

}gen.writeEndArray();String jsonOrders = gen.getAsString();System.debug('jsonOrders: ' + jsonOrders);// Send the JSON data to the web service

HttpRequest req = new HttpRequest();req.setMethod('POST');

req.setEndpoint('https://fulfillment.herokuapp.com/order');req.setHeader('Content-Type', 'application/json');req.setBody(jsonOrders);

Http http = new Http();HTTPResponse res = http.send(req);// Get all the invoices - we'll need to update them

List<Invoice_Statement__c> invoices =[SELECT Id FROM Invoice_Statement__c WHERE Id IN :invoiceIds];

// Did it work?if (res.getStatusCode() != 200) {

System.debug('Error from ' + req.getEndpoint() + ' : ' +res.getStatusCode() + ' ' + res.getStatus());

// Set all the invoice order IDs to '000000'for ( Invoice_Statement__c invoice : invoices ) {

invoice.OrderId__c = '000000';}

} else {// Parse out the external order numbersSystem.debug('Fulfillment service returned '+res.getBody());List<ExternalOrder> orders=(List<ExternalOrder>)JSON.deserialize(res.getBody(),

List<ExternalOrder>.class);Map<Id, Invoice_Statement__c> invoiceMap = new Map<Id,Invoice_Statement__c>(invoices);// Set the order numbers in the invoicesfor ( ExternalOrder order : orders ) {

Invoice_Statement__c invoice = invoiceMap.get(order.id);invoice.OrderId__c = order.order_number;

}}update invoices;

}}

Save the file and then examine the above code, you will see that it collects the data it needs to invoke the fulfillment WebService - an array of invoice objects each containing an array of list items - and generates a JSON-formatted request using theSystem.JSONGenerator class. After calling the Web Service, the order IDs are parsed out of the response and persisted.

Tell Me More....Note that the @future method makes only two queries, one for invoices and one for line items, regardless of the number ofinvoice IDs that are passed in. This pattern, typically called ‘bulkifying’ makes the code a little more complex, it is a best

19

Tutorial #4: Connecting the Warehouse App with an External Service

Page 22: Integration Workbook

practice to avoid hitting the database once for each incoming record, therefor making your code much more scalable andefficient.

Step 4: Test the @future MethodYou can test the @future class you just created via the new Developer Console. Testing the class in isolation allows you toensure that remote site settings are configured correctly before creating a Trigger.

1. Go to an invoice statement by selecting the Warehouse app, clicking the Invoice Statements tab, and clicking one of therecent invoices.

2. Copy the 15 character alphanumeric ID at the end of the URL.

3. Go to the Developer Console by clicking Your Name > Developer Console.

20

Tutorial #4: Connecting the Warehouse App with an External Service

Page 23: Integration Workbook

4. Click the box marked Click here to enter Apex Code and enter the following code, with the ID you copied in step 1 inplace of the ID in the code.

Integration.postOrder(new List<Id>{'a01E0000000Bs5P'});

5. Click the Execute. You should see two entries appear in the logs. Double click the second line - it should have FutureHandler as its operation and a status of Success.

6. Click the Filter checkbox under the Execution Log and type DEBUG as the filter text. Scroll down and double click thelast line of the execution log - you should see a popup with the response from the fulfillment Web Service - for example

14:19:18:576 USER_DEBUG [99]|DEBUG|Fulfillment service returned[{"id":"a01E0000000Bs5PIAS","order_number":"524090"}]

Now you have a @future method that is able to call the fulfillment Web Service, it's time to tie things together with a Trigger.

Step 5: Create a Trigger to Call the @future MethodBy default, a trigger executes on every update to Invoice Statement records. We need to add logic to ensure that orders areonly submitted for fulfillment when an invoice is closed. Go ahead and create the trigger:

1. Go to the Invoice Statement custom object by clicking Your Name > Setup > Create > Objects > Invoice Statement.

21

Tutorial #4: Connecting the Warehouse App with an External Service

Page 24: Integration Workbook

2. Scroll down to Triggers, click New and paste the following code in place of the trigger skeleton: (You can also downloadthe code here: http://bit.ly/aw2012-ordertrigger )

trigger HandleOrderUpdate on Invoice_Statement__c (after update) {Map<ID, Invoice_Statement__c> oldMap = new Map<ID,Invoice_Statement__c>(Trigger.old);// Make a list of invoice IDs to post, so we can do it in one hitList<Id> invoiceIds = new List<Id>();for (Invoice_Statement__c invoice: Trigger.new) {// Only post order when status is changing from not closed to closedif (invoice.status__c == 'Closed' && oldMap.get(invoice.Id).status__c != 'Closed'){

invoiceIds.add(invoice.Id);}

}if (invoiceIds.size() > 0) {

Integration.postOrder(invoiceIds);}

}

Notice that the trigger creates a list of IDs for invoices that have been closed in this update - that is, their new status is Closed,but their old status was something other than Closed - and calls the @future method just once, passing the list of IDs. Thisbulkified pattern is a best practice for triggers — you should not assume that there will be only a few updates and make a callto the @future method for each one.

Step 6: Test the IntegrationNow all the pieces are in place, it's time to test the integration.

1. Go to an invoice statement by selecting the Warehouse app, clicking the Invoice Statements tab, and clicking one of therecent invoices.

2. If the Status is already Closed, double click the word Closed, change it to Open and click Save.3. Double click the Status value, change it to Closed and click Save.4. Refresh the page in the browser.5. You should see a six digit number appear in the OrderId field. You can repeat steps 2-4 above and see the order ID

change.

22

Tutorial #4: Connecting the Warehouse App with an External Service

Page 25: Integration Workbook

SummaryCongratulations! Your app is sending invoices for fulfillment. You have successfully created an asynchronous Apex class whichposted invoice details to another app hosted in the cloud. Of course, your external application could reside anywhere as longas you have access via Web Services. Your class used open standards including JSON and REST to transmit data, and a triggeron Invoice Statements to execute the process. Sit back, and celebrate. You have now completed the Integration tutorials. Yourwarehouse app is now complete!

23

Tutorial #4: Connecting the Warehouse App with an External Service