Integration Workbook
Integration Workbook
Integration Workbook
© Copyright 2000–2013 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.
Table of Contents
Table of Contents
Tutorial #2: Connect the Warehouse App with an External Service ........................................................6
Step 1: Create an External ID Field on Invoice........................................................................................................................6
Step 2: Create a Remote Site Record........................................................................................................................................6
Step 3: Create an Integration Apex Class..................................................................................................................................7
Step 4: Test the @future Method..............................................................................................................................................9
Step 5: Create a Trigger to Call the @future Method...............................................................................................................9
Step 6: Test the Complete Integration Path...........................................................................................................................10
Summary.................................................................................................................................................................................11
i
Force.com Integration Workbook
Intended Audience
This workbook is intended for developers new to the Force.com platform but have basic working knowledge in Java.
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 an
optional 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.
1
Before You Begin
Note: After you’ve gone through this workbook, you can un-install the Warehouse data model and sample data from
your organization by navigating to Installed Packages under Setup and deleting the Warehouse package.
2
Tutorial #1: Create a New Heroku Application Step 1: Clone the Github Project
1. Open a command line terminal. For Mac OS X users, this can be done by going to the Terminal program, under
Applications/Utilities. For PC users, this can be done by going to the Start Menu, and typing cmd into the Run
dialog.
2. Once in the command line terminal, change to a directory where you want to download the example app. For example, if
your directory is “development,” type cd development.
3. Execute the following command:
1. In the command line terminal, change directory to the spring-mvc-fulfillment-base folder you created in the last
step:
cd spring-mvc-fulfillment-base
2. Execute the following command to login to Heroku (followed by Heroku login credentials, if necessary):
heroku login
heroku create
Heroku creates a local git repository as well as a new repository on its hosting framework, where you can push applications,
and adds the definition for that remote deployment for your local git repository to understand. This makes it easy to leverage
git for source control, make local edits, and deploy your application to the Heroku cloud.
3
Tutorial #1: Create a New Heroku Application Step 3: Test the Application
All application names on Heroku must be unique, so you’ll see messages like the following when Heroku creates a new
app:
Important: The output above shows that the new application name is quiet-planet-3215. You might want
to copy and paste the generated name into a text file or otherwise make a note of it. Throughout this workbook,
there are references to the application name that look like {appname} that should be replaced with your application
name. So, if your application name is quiet-planet-3215, when a tutorial step prompts you to enter a URL
with the format https://{appname}.herokuapp.com/_auth, use:
https://quiet-planet-3215.herokuapp.com/_auth.
The process will take a while as it copies files, grabs any required dependencies, compiles, and then deploys your application.
5. Once the process is complete, you can preview the existing application by executing:
heroku open
Tell Me More...
Look carefully as the git push happens and you’ll see some magic. Early on, Heroku detects that the push is a Spring MVC
app, so it installs Maven, builds the app, and then gets it running for you, all with just a single command.
4
Tutorial #1: Create a New Heroku Application Summary
5. In the browser URL bar, select the invoice record ID, which is everything after salesforce.com in the URL. It should
look something like a01E0000000diKc. Copy the ID to your clipboard.
6. Return to the browser window or tab showing your Heroku application.
7. Paste the invoice record ID into the field under Id.
8. Click Create. An order is created with the Invoice ID. Your page looks something like:
Summary
Heroku’s polyglot design lets you easily deploy your applications with industry-standard tools, such as git. Typically, teams
use local development environments, like Eclipse, and in fact Heroku has released an Eclipse plugin for seamless integration
with Eclipse. You can also interact with Heroku on the command line and directly access logs and performance tools for your
applications.
5
Tutorial #2: Connect the Warehouse App with an External Step 1: Create an External ID Field on Invoice
Service
6
Tutorial #2: Connect the Warehouse App with an External Step 3: Create an Integration Apex Class
Service
Now any Apex code in your app can call the fulfillment Web service.
Tell Me More...
Just for fun, you can skip Step 2 and create and test the callout in Step 3 and Step 4 below to observe the error message that
is generated when an app attempts to callout to a URL without permission. Don't forget to come back and add the remote
site record, though!
// 1) see above
7
Tutorial #2: Connect the Warehouse App with an External Step 3: Create an Integration Apex Class
Service
// 2) see above
// 3) see above
This code collects the necessary data for the remote service, makes the remote service HTTP call, and processes any data
returned by the remove service to update local invoices with the corresponding external IDs. See the embedded comments in
the code for more information.
8
Tutorial #2: Connect the Warehouse App with an External Step 4: Test the @future Method
Service
This small snippet of Apex code retrieves the ID for a single invoice and calls your @future method using this ID.
3. Click the Open Log checkbox.
4. Click Execute. You should see two entries appear in the logs. Double click the second line — it should have Future
Handler as its operation and a status of Success.
5. Click the Filter checkbox under the Execution Log and type DEBUG as the filter text. Scroll down and double click the
last line of the execution log. You should see a popup with the response from the fulfillment Web service that looks
something like:
Now that you have a functional @future method that can call the fulfillment Web service, it's time to tie things together
with a trigger.
1. Go to the Invoice custom object from Setup by clicking Create > Objects > Invoice.
2. Scroll down to Triggers, click New, and paste the following code in place of the trigger skeleton:
9
Tutorial #2: Connect the Warehouse App with an External Step 6: Test the Complete Integration Path
Service
3. Click Save.
The comments in the code explain what is happening. In particular, understand that Force.com triggers must be able to handle
both single row and bulk updates because of the varying types of calls that can fire them (single row or bulk update calls). The
trigger creates a list of invoice IDs that have been closed in this update, and then calls the @future method once, passing the
list of IDs.
The following screen shows the Invoices tab before any changes have been made:
10
Tutorial #2: Connect the Warehouse App with an External Summary
Service
The following screen shows the Invoices tab after the asynchronous call has returned the new order ID:
Summary
Congratulations! Your app is sending invoices for fulfillment. You have successfully created an asynchronous Apex class that
posted invoice details to your fulfillment app hosted on Heroku. Of course, your external application could reside anywhere
11
Tutorial #2: Connect the Warehouse App with an External Summary
Service
as long as you have access via Web services. Your class uses open standards including JSON and REST to transmit data, and
a trigger on Invoices to execute the process.
12
Tutorial #3: Update the Heroku App Step 1: Configure Your Connected App
Note: Be sure to replace {appname} with your actual Heroku app name.
1. Return to the command line, and make sure you’re in the spring-mvc-fulfillment-base folder.
2. Enter the following command to fetch the “full” branch and merge it with your master branch, all in one step:
13
Tutorial #3: Update the Heroku App Step 3: Update the User Interface with Invoice Information
3. You need to set your Access keys to your Heroku application. Enter:
Replace PUBLICKEY with the Consumer Key. Similarly, replace PRIVATEKEY with the Consumer Key. It may be
helpful to do this in a text editor before putting it on the command line.
4. Execute the following command to push the local changes to Heroku:
5. In a browser tab or window, navigate to https://{appname}.herokuapp.com to see the changes (refresh your browser
if needed).
By adding an OAuth flow to your app, your app can get a user’s permission to have session information without requiring the
third-party server to handle the user’s credentials. With this added to the project, the fulfillment application can use the
Force.com REST API to access information directly from the user’s instance.
Tell Me More...
You can review all of the changes brought in by this branch on github at:
https://github.com/sbob-sfdc/spring-mvc-fulfillment-base/compare/master...full. Notice that the
changes use the Force.com REST API to manipulate Invoice records. Look at InvoiceServiceImpl.java in particular
to see how it creates, queries, retrieves and deletes invoices. This tutorial only uses the findOrder() method. The others
are included for your reference.
add:
<h3>Invoice</h3>
<p>Number: <c:out value="${invoice.number}"/></p>
<p>Status: <c:out value="${invoice.status}"/></p>
14
Tutorial #3: Update the Heroku App Step 3: Update the User Interface with Invoice Information
7. Wait for the push to finish, and navigate to your fulfillment app in the browser (refreshing if necessary) to see the changes.
Notice that, given an ID, this code retrieves the corresponding invoice record. Because there might be mock ID's in the
database that are not in Force.com, the app handles the corresponding exception by showing default data. Adding the invoice
to the model makes it available to the view. Now when you test the fulfillment application, it will show the invoice information
currently in your Force.com instance by grabbing the information via the REST API using the record ID. Your order detail
page might look something like:
Tell Me More...
To really see the application in motion, you can edit information on Force.com (like the Description of the Invoice) and
see it represented the next time you load that order in your Heroku app.
Notice that the Web service call from Force.com to create orders is not secured. Securing this call goes beyond the scope of
this workbook, but a simple solution would be to set up a shared secret between the Force.com app and the fulfillment app.
The Force.com app would create an HMAC of the parameters in the request, using the secret, and the fulfillment app would
verify the HMAC.
15
Tutorial #4: Add Your App to Salesforce Using Force.com Step 1: Update your Canvas App with a New Branch
Canvas
1. Return to the command line, and make sure you’re in the spring-mvc-fulfillment-base folder.
2. Enter the following command to fetch the canvas branch and merge it with your master branch, all in one step:
4. In a browser tab or window, navigate to https://{appname}.herokuapp.com to see the changes (refresh your browser
if needed).
Tell Me More...
You can review all of the changes brought in by this branch on GitHub at
https://github.com/sbob-sfdc/spring-mvc-fulfillment-base/compare/full...canvas.
Notice that the changes use the signed request from the Force.com Canvas API and not the Heroku-initiated OAuth from
Tutorial 3, Step 2 and also use the Force.com REST API to manipulate invoice records. Look at CanvasUiController.java
in particular to see how it retrieves, parses, and sets the signed request for use by the app. Also, order.jsp has changed to
present an easier-to-use screen on the invoice page layout. This tutorial has only set the signed request for use on the canvasui
page and the orders page in the app.
16
Tutorial #4: Add Your App to Salesforce Using Force.com Step 2: Edit The Connected App Details and Enable it for
Canvas Force.com Canvas
If you look at CanvasUiController.java, you’ll see something like the following, which shows Heroku obtaining a signed
request and validating it. We’re leveraging the OAUTH_CLIENT_SECRET Heroku key set in Tutorial 3, Step 2 to validate the
signed request. After the validation, the signed request is passed to order.jsp where the browser can access it.
@Controller
@RequestMapping(value="/canvasui")
public class CanvasUIController {
@Autowired
private OrderService orderService;
@Autowired
private InvoiceService invoiceService;
@Autowired
public CanvasUIController(Validator validator) {
this.validator = validator;
}
@RequestMapping(method= RequestMethod.POST)
public String postSignedRequest(Model model,
@RequestParam(value="signed_request")String signedRequest, HttpServletRequest request){
Invoice invoice;
try {
invoice = invoiceService.findInvoice(order.getId());
} catch (ApiException ae) {
// No match
invoice = new Invoice();
}
model.addAttribute("invoice", invoice);
return "order";
}
}
return getOrdersPage(model);
}
@RequestMapping(method=RequestMethod.GET)
public String getOrdersPage(Model model) {
model.addAttribute("order", new Order());
model.addAttribute("orders", orderService.listOrders());
return "orders";
}
17
Tutorial #4: Add Your App to Salesforce Using Force.com Step 2: Edit The Connected App Details and Enable it for
Canvas Force.com Canvas
<html>
<head>
<title>Order</title>
<link rel="stylesheet" href="<c:url value="/resources/blueprint/screen.css" />
" type="text/css" media="screen, projection">
<link rel="stylesheet" href="<c:url value="/resources/blueprint/print.css" />"
type="text/css" media="print">
<!--[if lt IE 8]>
<link rel="stylesheet" href="<c:url value="/resources/blueprint/ie.css" />
" type="text/css" media="screen, projection">
<![endif]-->
<script type="text/javascript" src="<c:url value="/resources/jquery-1.4.min.js" /> ">
</script>
<script type="text/javascript" src="<c:url value="/resources/json.min.js" /> ">
</script>
<script type="text/javascript" src="<c:url value="/resources/canvas-all.js" /> ">
</script>
<script>
// Get the Signed Request from the CanvasUIController
var sr = JSON.parse('${not empty signedRequestJson?signedRequestJson:"{}"}');
// This function will be called when the "Delete Order" button is clicked.
// It will delete the record from the Heroku database.
function deleteHandler(){
$.deleteJSON("/order/${order.orderId}", function(data) {
alert("Deleted order ${order.orderId}");
18
Tutorial #4: Add Your App to Salesforce Using Force.com Step 3: Configure Access to Your Force.com Canvas App
Canvas
location.href = "/orderui";
}, function(data) {
alert("Error deleting order ${order.orderId}");
});
return false;
}
// This function gets the instance the user is on for a page referesh
function getRoot() {
return sr.client.instanceUrl;
}
</script>
</head>
<body>
<div id="bodyDiv" style="width:inherit;">
<div id="myPageBlockTable">
<h2 id="OrderTitle">
Order Number: <c:out value="${order.orderId}"/>
</h2>
<table id="myTable" width="100%">
<col width="20%">
<tr><td class="myCol">Invoice Id:</td><td class="valueCol">
<c:out value="${invoice.id}"/></td></tr>
<tr><td class="myCol">Invoice Number:</td><td class="valueCol">
<c:out value="${invoice.number}"/></td></tr>
<tr><td class="myCol">Status:</td><td class="valueCol" valign="center">
<c:out value="${invoice.status}"/>
<!-- Display a green check if the order is Shipped, or a red x if
not shipped -->
<c:choose>
<c:when test="${invoice.status == 'Shipped'}">
<img src="/resources/images/shipped.png" />
</c:when>
<c:otherwise>
<img src="/resources/images/pending.png" />
</c:otherwise>
</c:choose>
</td></tr>
</table>
<!-- Display the Back and Delete Order Button if viewed outside
of salesforce (no signed request). -->
<!-- Display the Finalize Button if viewed inside of salesforce and
the Status is not Shipped. -->
<c:choose>
<c:when test="${empty signedRequestJson}">
<button onclick="location.href='/orderui'">Back</button>
<button id="deleteButton">Delete Order</button>
</c:when>
<c:otherwise>
<c:if test="${invoice.status ne 'Shipped'}">
<button id="finalizeButton">Finalize</button>
</c:if>
</c:otherwise>
</c:choose>
</div>
</div>
</body>
</html>
19
Tutorial #4: Add Your App to Salesforce Using Force.com Step 4: Make Your Force.com Canvas App Available from the
Canvas Chatter Tab
Your app is now available to anyone with the System Administrator profile.
The values you selected in the Locations field when creating the connected app in Step 2: Edit The Connected App Details
and Enable it for Force.com Canvas on page 16 determine where an installed canvas app appears. When an app is made
available to the Chatter tab, there’s nothing we need to do for this step. If you log into your Salesforce org and select the
Chatter tab, you’ll see that your canvas app appears in the app navigation list.
Note: When displaying the list of orders on the Chatter Tab, remember that orders.jsp has been set up to handle
the signed request POST. However, if you click into a record from this page, you are redirected to orderui, which
uses the OAuth. If the Heroku OAuth flow is inactive, you may receive an error when viewing the individual order.
20
Tutorial #4: Add Your App to Salesforce Using Force.com Step 5: Use Visualforce to Display the Canvas App on a Record
Canvas
<apex:page standardController="Invoice__c">
<apex:canvasApp developerName="CanvasFulfillment"
parameters="{'orderId':'{!Invoice__c.OrderId__c}'}" width="100%"/>
</apex:page>
21
Tutorial #4: Add Your App to Salesforce Using Force.com Summary
Canvas
Now when users go to an invoice record, they’ll see the canvas app right on the record detail page:
Notice the Finalize button in the canvas app. If the invoice is not in a shipped status, the red “X” and Finalize will show in
the app. If you click Finalize, Heroku uses the Force.com Canvas API to call the REST API and update the invoice status
field. Once the status is set to 'Shipped', the red “X” is replaced and Finalize is hidden.
Summary
Congratulations! With a combination of OAuth authentication, the REST API, Apex triggers, @future callouts, the polyglot
framework of the Heroku platform, Force.com Canvas, and Visualforce, you created and deployed a bi-directional integration
between two clouds.
This workbook touches upon just one example of the many ways to integrate your applications with Salesforce. One integration
technology not touched on is the Streaming API that lets your application receive notifications from Force.com whenever a
user changes Salesforce data. You can use this in the fulfillment application to monitor when a user updates invoices and to
automatically update the application pages accordingly. Visit http://developer.force.com to learn more about all the
ways you can integrate your application with Force.com.
22