First Impressions with Platform Events and the Salesforce Enterprise Messaging Platform

There’s something new and exciting coming with our Summer 17 release: Platform Events! They have nothing to do with your calendar or Activities in Salesforce. Instead, Platform Events is a new native feature that, when paired with the enterprise messaging platform, enables near real-time integrations in the spirit of event-driven architecture. Salesforce is known for its custom metadata platform, and now we’re delivering a custom messaging platform so our customers can build and publish their own events.  

The vision for Platform Events is simple: Empower our customers to increase business productivity and efficiency through integrations via events. We want to enable customers to create more integrations between Salesforce and their systems. Using Platform Events, customers can support more interaction between Salesforce and their data. The goal is to reduce the number of point-to-point integrations and expand on the existing capabilities of our other integration options such as Outbound Messaging, Apex Callouts, and the Streaming API.

The pipe, the window, and the event

So what are Platform Events? Platform Events are comparable to other publish-subscribe messaging systems like Kafka. There are five main components: the pipe, a window of time, the events themselves, publishers, and consumers.  

 

A message bus with sliding window

 

The pipe serves as a message bus that enables events to be added in chronological order with replay IDs. The window slides with time, and any events within the window can be replayed. Publishers are internal or external apps that push new events into the pipe. Internal events can be published declaratively with Flows or Process Builder and programmatically with Apex. External apps can use our native APIs (SOAP, REST, Bulk) to publish events. Consumers can subscribe to events via CometD/Bayeux protocols and with Apex. We have plans to add declarative support (Flows and Process Builder) for subscribing to events in future releases.

 

Salesforce Message Bus

Is this starting to look similar to an enterprise service bus (ESB)? Well it should, the new message bus enables you to use Salesforce like a kind of ESB. Let’s get hands-on with platform events and play around with this new feature, shall we?

Hands on: Platform Events

To get access to Platform Events you can sign up for a Summer 17 Pre-Release org here. In Setup, use the quick find to locate the Platform Events node where you can start creating custom events.

The first thing you notice is that creating a custom event is almost identical to creating a custom object. “Event” is now a first-class object in Salesforce with the same strongly typed, versioned, and customizable schema you have come to expect from Salesforce’s metadata platform. You had me at custom objectI’m already in love! 

 

Custom Platform Event Setup

In this example, I accessed Platform Events from Setup and created an “Order Event” to be used to signal that something has happened with an Order. I was able to add custom fields: “Order Number” to store the Salesforce Order number and “Type” to record the type of change that has been made to the order.

There are some differences between custom objects and events. The obvious one is that the API name ends with “__e” instead of “__c”.  A bigger difference is that event records are immutable—meaning that once an event has been published, it can’t be updated or deleted by a user—and they’re not queryable using SOQL or SOSL. Instead, to receive events, you subscribe to a channel. OK, now that we have our own custom event, let’s start publishing!

In my example I want Salesforce to publish an event when an Order has been “Placed.” This notifies my external shipping app to send out a shipment. Now that we’ve configured the event, I create a trigger on the standard order object to do just that.

trigger OrderTrigger on Order (after update) {
    List<Order_Event__e> OrdEvents = New List<Order_Event__e>();
    for (Order o: Trigger.new) {
        if(o.Status == 'Placed' && Trigger.oldMap.get(o.Id).Status <> 'Placed'){
           OrdEvents.add(new Order_Event__e(Order_Number__c = o.OrderNumber, Type__c=o.Status));
        }
    }
    if(OrdEvents.size()>0) EventBus.publish(OrdEvents);    	  
}

This Apex code creates a new event for each Order whose status has been updated to “Placed” and publishes it to the event messaging bus, or the pipe as we referred to it earlier. The key method is the EventBus.publish()method that pushes the messages in the pipe. Pretty simple right? Well it gets even easier, because you can use Process Builder to publish an event as well. Events can be created like any other sObject in the Process Builder.

How does my external shipping app get the event? First the app needs to subscribe to the event’s channel. To consume the events externally, subscribe to the Salesforce API using the Bayeaux wire protocol built on CometD. CometD is the highly scalable HTTP-based event-routing bus, and Bayeaux is a protocol for transporting asynchronous messages, primarily over HTTP.  See an example Java app on GitHub that can handle subscription management and event replay.

So let’s do that. The process of subscribing to platform event notifications through CometD is similar to subscribing to our Streaming API’s PushTopics or generic events. The only difference is the channel name. Here is the format of the Platform Event topic (channel) for my event:

/event/Order_Event__e

Here is what an event message looks like when it’s received by the app:

{
   "data": {
      "schema": "7cBPcbWRGAqoVPAYeCcC2w", 
      "payload": {
        "CreatedDate": "2017-04-14T13:35:23Z", 
        "CreatedById": "005B00000031mqb", 
        "Order_Number__c": "10013", 
        "Type__c": "Placed"
      }, 
      "event": {
        "replayId": 1
      }
    }, 
    "channel": "/event/Order_Event__e"
}

My external shipping app, subscribed to Order Event channel, is notified in near real-time when an order is placed thanks to my Apex trigger. Once my shipping app completes sending the shipment, does it let Salesforce know? Of courseideally by publishing another event. Your app can publish an event to Salesforce using our SOAP, REST, or Bulk APIs. Publishing events uses the same process as inserting sObject records. Using the REST API, the endpoint looks like:

/services/data/v40.0/sobjects/Order_Event__e/

And the request body is:

{
  "Order_Number__c" : "10013",
  "Type__c" : "Shipped"
}

Awesome! We just published another event. Now I want to consume that event and take some action in Salesforce. More specifically, I want to update the Order Status to “Shipped.” Internally, this can be done using a simple trigger on the event. That’s right, you can create a trigger on an event! Note that there is only one type of trigger on events, and that is an after insert trigger that fires after the event has been published. Remember, events are immutable, which means they can’t be changed once inserted. So before triggers, after update and after delete triggers aren’t supported.

trigger OrderEventTrigger on Order_Event__e (after insert) {
     List<String> OrderNums = New List<String>();
     for(Order_Event__e orEvent: trigger.New){
         if(orEvent.Type__c == 'Shipped') OrderNums.add(orEvent.Order_Number__c);
     }
     List<Order> OrderShipped= [Select Id, Status, OrderNumber from Order where OrderNumber in :OrderNums];
     for(Order o : OrderShipped) o.Status='Shipped';
     if (OrderShipped.size() > 0) Update OrderShipped;
 }

The above trigger looks for Order Events with the type of “Shipped” and updates the corresponding Order records in Salesforce. After this trigger runs and updates an Order, you notice the Order History in Salesforce shows the action has been completed by an “Automated Process” user.

 

Order History updated by the Trigger

So to sum it all up, we defined a Platform Event, used a trigger to fire an event, had an external app subscribed to the event’s channel, had that external app publish a new event, and had Salesforce listen for that event to update an Order. Phewthat was a lot of work!

 

Integration process using Platform Events and the Message Bus

Using Platform Events: integration and orchestration

While there are myriad ways Platform Events can help simplify integration, we highlight a few core use cases: order and durability, long-running processes, and orchestration of multiple actors.

Some developers may wonder why they couldn’t use a trigger, an @future method, and a web service callout to accomplish the example scenario above. While this can work, the @future callout isn’t sequenced (can come out of order), requires custom error handling (not durable), and has is subject to  governor limits. In the cases where order and durability matter, Platform Events let you replay events that were sent in the last 24 hours in sequence. Apps can pass the replay ID of the last event received to retrieve all the events that occurred after that replay ID.

Platform Events are also a great way to decouple long-running processes. While Outbound Messaging or the Streaming API are other possible solutions, they were designed for slightly different use cases. Outbound Messaging is a contract-first, SOAP-only technology, and the Streaming API was designed for UI updates and isn’t as customizable as Platform Events.

The real power of Platform Events is revealed when processing is required by multiple actors. In the previous example, there are only two actors: Salesforce and an external shipping app. What if there are more actors? For example, say when the shipping app publishes the “Shipped” event, and you want your ERP to recognize the revenue from the order. Perhaps we also want our Marketing Cloud instance to listen for the same event in order to kick off a personalized new product email journey for a customer. Platform Events shines in these orchestration scenarios, since one event can be published to many subscribers who can all take appropriate action. Ultimately, the long-term goal for Platform Events is to turn a spaghetti-like point-to-point integration mess like this:

 

Spaghetti-like point-to-point integration mess

Into something much more manageable with a common messaging-driven architecture like this:

 

Messaging-driven architecture with Platform Events

Cool right? It makes my little architect heart swoon with happiness.  

As we approach the Summer ’17 release and Dreamforce ’17, you will hear more about the general release of Platform Events and its capabilities. Platform Events will be available in Summer ’17 for all customers with Enterprise Edition or higher. There will be limits based on event volume with add ons available to extend these limits. As for what the future holds for Platform Eventswe’re looking to add additional protocols, and we want to support High Volume Platform Events. Think tens or hundreds of millions of Events per day. In addition, we’re planning deep integration with Heroku via Heroku Connect where you can plug Heroku into Salesforce to provide additional processing power!

With Platform Events, we enable our customers to increase business productivity and efficiency through integrations via events. In this post, we’ve shown you how using the event message bus can make it easier for you to build new integrations and simplify existing integrations using a publish/subscribe model, and reduce the number of point-to-point integrations. We’ve outlined when to use Platform Events and given you a glimpse into what’s coming for Summer ’17 and beyond. For more detailed information, check out the Summer ‘17 release notes and Platform Events Developer Guide.

About the author

Christopher Marzilli is a platform success specialist director at Salesforce; he spends his days driving customer success on the Salesforce Platform and his evenings playing video games with his son.

Resources:

Leave your comments...

First Impressions with Platform Events and the Salesforce Enterprise Messaging Platform