Platform Events (new in Summer ’17) provide a powerful publish/subscribe infrastructure that facilitates the integration between Salesforce and other applications. In this blog post, I demonstrate how to use platform events to integrate a Salesforce app with a Node.js app running on Heroku.
In my previous post, I shared a sample retail application called Northern Trail Outfitters (NTO). The application allows NTO to manage their relationship with retailers. For example, NTO reps can create “merchandise mixes” for their large retailers. A merchandise mix is a collection of products a retailer carries for a season.
In this post, we examine how the NTO retail app (built on force.com) integrates with their manufacturing app (built on Node.js). Here are the simple integration requirements:
Watch the video to see the integration in action:
Without platform events, you typically implement this kind of integration with API calls between apps. For example:
The downside of this approach is that it tightly couples the two applications:
If you change a REST service endpoint in one app, you’ll have to change code in the app that calls it. It gets worse when the integration involves more than two systems. Imagine for example that when a merchandise mix is approved in the manufacturing app, you have to do the following:
These service calls can be orchestrated in different ways, but in general this API-based approach leads to tightly coupled apps, and harder to maintain integrations.
Platform events allow you to communicate between applications while keeping them entirely decoupled. For example, in the NTO scenario, the platform events-based integration works as follows:
The retail app isn’t even aware of the existence of the manufacturing app, and the manufacturing app doesn’t know about the retail app either. Using the platform events approach, it doesn’t matter how many apps you need to integrate. You can add applications to the integration without having to change code in other apps. This generally leads to more versatile and easier to maintain integrations.
A platform event looks like a custom object with a few differences:
Publishing a platform event is very similar to creating a custom object. You can do it in Apex like this:
Mix_Submitted__e event = new Mix_Submitted__e(); event.Mix_Id__c = mix.Id; event.Mix_Name__c = mix.Name; EventBus.publish(event);
You can also do it entirely declaratively using a Create Record action in Process Builder. For example, in the NTO application, the Mix Status Change process creates a Mix_Submitted__e event when the status of a merchandise mix is changed to “Submitted to Manufacturing”.
Third-party apps subscribe to platform events using CometD. CometD libraries and toolkits are available for different platforms including Java and JavaScript. The manufacturing app is a Node.js app running on Heroku. It uses the Faye Node.js module to subscribe to CometD events (Mix_Submitted__e and Mix_Unsubmitted__e). Using Faye, the code to subscribe to a platform event in Node.js looks like this:
var client = new faye.Client(org.oauth.instance_url + '/cometd/40.0/'); client.setHeader('Authorization', 'OAuth ' + org.oauth.access_token); client.subscribe('/event/Mix_Submitted__e', function(message) { console.log('Got Mix_Submitted__e'); });
When a merchandise mix is approved, the manufacturing app publishes a Mix_Approved__e platform event to notify interested parties. 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 manufacturing app uses the nforce library. The code to publish the Mix_Approved__e platform event in Node.js looks like this:
let event = nforce.createSObject('Mix_Approved__e'); event.set('Mix_Id__c', mixId); event.set('Confirmation_Number__c', confirmationNumber); org.insert({sobject: event}, err => { if (err) { console.error(err); } else { console.log("Mix_Approved__e published"); } });
The retail app “listens” to the Mix_Approved__e event so it knows when a merchandise mix has been approved and can change its status accordingly. To subscribe to a platform event in Apex, you create an “after insert” trigger for the event type. The code to subscribe to the Mix_Approved__e platform event in Apex looks like this:
trigger onMixApproved on Mix_Approved__e (after insert) { List mixes = new List(); for (Mix_Approved__e event : Trigger.New) { Merchandising_Mix__c mix = new Merchandising_Mix__c(); mix.Id = event.Mix_Id__c; mix.Status__c = 'Approved by Manufacturing'; mix.Confirmation_Number__c = event.Confirmation_Number__c; mixes.add(mix); } update mixes; }
Lightning Components can also subscribe to platform events to update the UI in real time when events are fired. For example, if you are looking at a merchandise mix record page, it may be important to see that the mix has been approved in real time rather than having to constantly refresh the page or implement a polling mechanism. To subscribe to a Platform Event in a Lightning Component, you use the JavaScript CometD library. The code looks like this:
cometd.subscribe('/event/' + eventName, $A.getCallback( function(message) { console.log(message); } ));
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!