Pure Aloe Sample App Part 2: Integration with Platform Events

Unlike API-based integrations which result in tightly coupled applications, platform event-based integrations keep applications decoupled and are therefore more versatile and easier to maintain. In this blog post, we use the Pure Aloe sample application to demonstrate the benefits of the platform event publish and subscribe model in the context of a Salesforce/Node.js integration.

In my previous post, I shared the Pure Aloe sample application that was first showcased during the developer keynote at Dreamforce ’17. Pure Aloe, a fictional non-profit inspired by The Karibu Centre, uses Salesforce to manage its three core activities: education, agriculture, and retail. In part 1 of this series, we focused on agriculture, and specifically on how Pure Aloe uses Salesforce to manage its aloe fields. In this blog post, we examine how Pure Aloe uses platform events to integrate with its distributors that sell its aloe soaps and lotions.

Use case 1: Salesforce to third-party app communication

Pure Aloe creates product bundles that it offers to its distributors. Our first integration requirement is to notify the distributor app when a new product bundle becomes available. The distributor app is written in Node.js app and runs on Heroku.

To support this requirement, we create a platform event called Bundle_Submitted__e with fields like: Bundle Id, Bundle Name, and Qty. The communication between Salesforce and the distributor app then works as follows:

  1. A Process Builder process is used to publish a Bundle_Submitted__e event when the status of a product bundle changes to Submitted to Distributors.
  2. The distributor app subscribes to the Bundle_Submitted__e event and is automatically notified when a new bundle becomes available.

The illustration below shows how this integration materializes in the UI: when a bundle is submitted to distributors in Salesforce, the distributor app is automatically notified and the list of available bundles is updated in real time.

Let’s take a closer look at the two sides of this integration.

Publishing the Bundle_Submitted__e event in Salesforce

The Pure Aloe application publishes the Bundle_Submitted__e event using Process Builder.
To publish a platform event in Process Builder, you use a Create Record action, and you select your platform event as the Record Type. For example, the Bundle Submitted process is defined as follows:

Although using the no-code option when available is considered a best practice, you could also publish platform events programmatically in Apex. The code would look like this:

Bundle_Submitted__e event = new Bundle_Submitted__e();
event.Bundle_Id__c = bundle.Id;
event.Bundle_Name__c = bundle.Name;
event.Description__c = bundle.Description__c;
event.Qty__c = bundle.Qty__c;
EventBus.publish(event);

Subscribing to the Bundle_Submitted__e event in the distributor app

Third-party apps subscribe to platform events using CometD. CometD libraries are available for different platforms including Java and JavaScript. The distributor app is a Node.js app running on Heroku and uses the Faye Node.js module to subscribe to CometD events. Using Faye, the code to subscribe to the Bundle_Submitted__e platform event looks like this:

var client = new faye.Client(org.oauth.instance_url + '/cometd/41.0/');
client.setHeader('Authorization', 'OAuth ' + org.oauth.access_token);
client.subscribe('/event/Bundle_Submitted__e', function(message) {
    // Implementation code here. For example, persist the new bundle.
});

Updating the UI in real time

In the distributor app, the integration consists in processing the event data (for example, persisting the new bundle) upon reception of a Bundle_Submitted__e event. For a better user experience (and a better demo), you may also want to update the UI in real time. For example, if a distributor is looking at a list of bundles in the client app, and the server app receives an event with a new bundle, you may want to add that bundle to the list the distributor is looking at. In the distributor app, the server app uses socket.io to push the new bundle to the client app upon reception of a new platform event.

Use case 2: Third-party app to Salesforce communication

Our second integration requirement is to notify the Salesforce app when the distributor orders a product bundle.

To support this requirement, we create another platform event called Bundle_Ordered__e with fields like Bundle Id and Account Id. The communication between the distributor app and Salesforce then works as follows:

  1. The distributor app publishes a Bundle_Ordered__e event when the product bundle is ordered.
  2. A Process Builder process subscribes to the Bundle_Ordered__e event and, when an event is received, changes the status of the corresponding bundle to Ordered by Distributor.

The illustration below shows the results of this integration in the UI: when a bundle is ordered in the distributor app, the bundle status is automatically updated in Salesforce and the bundle record page is updated in real time.

Let’s take a closer look at the two sides of this integration.

Publishing the Bundle_Ordered__e event in the distributor app

You publish a platform event the same way you create a custom object. In a third-party application, this means you call the Salesforce REST API create record endpoint, or the facility provided by your Salesforce REST API toolkit to create a custom object. The distributor app uses the nforce library. The code to publish the Bundle_Ordered__e platform event in Node.js looks like this:

let event = nforce.createSObject('Bundle_Ordered__e');
event.set('Bundle_Id__c', bundleId);
event.set('Account_Id__c', accountId);
org.insert({sobject: event}, err => {
    if (err) {
        console.error(err);
    } else {
        console.log("Bundle_Ordered__e published");
    }
});

Subscribing to the Bundle_Ordered__e event in Salesforce

Starting in Winter’18, you can subscribe to platform events using Process Builder.

When the platform event occurs, the process changes the bundle status to Ordered by Distributor, and sets the account id of the distributor that ordered the bundle.

Although using the no-code option when available is considered a best practice, you could also subscribe to the platform event programmatically using an Apex trigger. The code would look like this:

trigger onBundleOrdered on Bundle_Ordered__e (after insert) {
    List bundles = new List();
    for (Bundle_Ordered__e event : Trigger.New) {
        Bundle__c bundle = new Bundle__c();
        bundle.Id = event.Bundle_Id__c;
        bundle.Status__c = 'Ordered by Distributor';
        bundle.Account = event.Account_Id__c;
        mixes.add(bundle);
    }
    update bundles;
}

Updating the UI in real time

As described above, this integration consists primarily in updating bundle record fields upon reception of a Bundle_Ordered__e event. For a better user experience, you may also want to update the UI in real time with the event data. For example, if a user is looking at a bundle record page, you may want to update the UI in real time upon reception of the platform event to reflect the new status of the bundle. A first approach would be to have a Lightning Component on the page subscribe to the Bundle_Ordered__e event (see this post for an example). But this approach may lead to inconsistencies between the UI and the database in case the database update performed by the Bundle Ordered process fails (because of a failing validation rule for example). The alternative approach used in the Pure Aloe app is to use the Streaming API to update the UI when the record data changes in the database. That way, the UI updates in real time, but only after the record successfully updates in the database.

Source code

Summary

Platform events facilitate integration between applications by allowing them to communicate while keeping them entirely decoupled.This blog post demonstrates to use platform events to integrate a Salesforce app with a Node.js app running on Heroku. Try it out today. And because both the retail app (with Salesforce DX) and the manufacturing app are under version control in Github, it’s easier than ever to contribute to the project and submit pull requests!

Resources

About the author

Christophe Coenraets is a Developer Evangelist at Salesforce where he focuses on the Salesforce Platform, JavaScript frameworks, mobile, and enterprise architecture. Prior to joining Salesforce, Christophe held senior technical positions at Adobe, Macromedia, Sybase and Powersoft where he helped Enterprise customers design, architect and implement strategic applications. Christophe has been a regular speaker at conferences worldwide for the last 15 years. You can follow him on Twitter @ccoenraets.

Leave your comments...

Pure Aloe Sample App Part 2: Integration with Platform Events