Platform Events in Lightning (Emp API)

We can use Platform Events in Lightning (Emp API) to connect business processes in Salesforce and external sources through the exchange of real-time event data.  Platform events are secure and scalable. We can create a Platform Event and add custom fields as per the business needs. Platform event messages are published to the Event Bus. Messages are stored in Event Bus temporarily which can be retrieved by components that subscribe to these events. Let’s get into the implementation.

Implementation

In this implementation, we will create a Rest Resource that will create a Case and publish a Platform Event. External Application will call this web service. Lightning Component in Utility Bar will subscribe to this event and open a Case automatically in Salesforce.

Platform Events in Lightning (Emp API)
Platform Events in Lightning (Emp API)

Create Connected App

Create a Connected App and enable OAuth Settings. Check this post to know how to create and set up a Connected App. Consumer Key and Secret will be generated. Connected App should look something like below:

Connected App
Connected App

Create Platform Event

Platform Events and fields are created in the same way we create Objects and fields.

  • Type Platform Event in Quick Find box and click on Platform Events under Integrations.
  • Click on the New Platform Event and provide Label and Plural Label. For Publish Behaviour, select Publish After Commit to publish the event only after the transaction is successful. Click Save.
  • Under Custom Fields & Relationships, click New and add CaseId field of type Text.
Platform Event - Emp API in Lightning
Platform Event – Emp API in Lightning

Publish Platform Event from REST Resource

We can publish the event messages from a Salesforce app using Processes, Flows, Apex, or an External App using Salesforce APIs. In the implementation, we will publish from Apex Rest Resource.

To publish an event message from Apex Class, we just need to create an instance of Platform Event we created earlier. Add it in the list and use EventBus.publish() to publish the event messages.

Below is the simple Rest Resource that accepts the subject and description from the HTTP Request and creates a Case. It also publishes the Platform event with the Id of the Case.

CaseResource.apxc

@RestResource(urlMapping='/CaseService/')
global class CaseResource {
	
    @HttpPost
    global static String createCase(String subject, String description){
        Case objCase = new Case(Subject = subject, Description = description, 
                                AccountId = [SELECT Id FROM Account WHERE Name = 'Niks Developer' LIMIT 1].Id);
        insert objCase;
        
        // Creating a Platform event.
        list<New_Case__e> newCaseList = new list<New_Case__e>{new New_Case__e(CaseId__c = objCase.Id)};
            
        // Calling method to publish events
        List<Database.SaveResult> newCaseResults = EventBus.publish(newCaseList);
        
        // Error Handling
        for (Database.SaveResult sr : newCaseResults) {
            if (sr.isSuccess()) {
                System.debug('Successfully published event.');
            } else {
                for(Database.Error err : sr.getErrors()) {
                    System.debug('Error returned: ' +err.getStatusCode() +' - ' +err.getMessage());
                }
            }       
        }
        return objCase.Id;
    }
}

Subscribe to Platform Event

We can subscribe and receive event messages in Processes, Flows, Apex triggers, or CometD clients. In this implementation, we will subscribe from Lightning Aura Component.

First, we need to add lightning:empApi utility in the component. In doInit handler of JS Controller, we have to call a subscribe method of empApi utility and pass the channel and replayId. Channel contains the name of Event and replayId is used to get the new events. There is more to replayId but we will cover that later. For now, just assign -1 to it. Add the logic to open a new case from the Case Id retrieved from event.data.payload. Then() is used to perform post subscription logic like saving the subscriptions to unsubscribe it later.

We have to keep this component in Utility Bar. Because it should stay subscribed to Platform Event all the time so that every time a Case is created by External Application, it should open in Salesforce application. Only Utility Bar is available on all the pages in the Salesforce application.

subscribeCmp.cmp

<aura:component implements="flexipage:availableForAllPageTypes, lightning:utilityItem" access="global" >
	<lightning:empApi aura:id="empApi"/>
    
     <!-- Calls the onInit controller function on component initalization -->
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    
    <!-- Holds the streaming event subscription -->
    <aura:attribute name="subscription" type="Map" />

    <!-- Form for subscribing/unsubscribing to/from events -->
    <lightning:input aura:id="channel" label="channel" name="channel" type="text" value="/event/New_Case__e"/>
</aura:component>

subscribeCmpController.js

({
	doInit : function(component, event, helper) {
        
		// Get the empApi component
        const empApi = component.find('empApi');
        // Get the channel from the input box
        const channel = '/event/New_Case__e';
        // Replay option to get new events
        const replayId = -1;

        // Subscribe to an event
        empApi.subscribe(channel, replayId, $A.getCallback(eventReceived => {
            var casePayload = eventReceived.data.payload;
            
            // Process event
            var navEvt = $A.get("e.force:navigateToSObject");
            navEvt.setParams({
              "recordId": casePayload.CaseId__c
            });
    		navEvt.fire();
        }))
        .then(subscription => {
    		// Post Subscription Logic.
            console.log('Subscription request sent to: ', subscription.channel);
            // Save subscription to unsubscribe later
            component.set('v.subscription', subscription);
        });
	}
})

Go to App Manager from Quick Find box. Edit the App, Click on Utility Items in the sidebar. Click on Add Utility Item and select our component. For Panel Width and Panel Height, enter 1 and click on Start automatically checkbox. Click Save. It will add the component in Utility Bar but it will not popup after clicking as the width and height are 1. Still, It will still execute all the code written inside. That is all we needed to run our implementation. Let’s test it.

Platform Events in Lightning (Emp API)

To test this, we just need to call our Web Service and pass the subject and description. We will test this using Username and Password flow from Postman.

  • First hit the Token URL with username, password, client_id, client_secret, and grant_type (password) as query parameters with the POST method. Make sure to append the Security token to password.
  • We will get the access_token. Use this access_token to call our Web Service with Authorization and Content-Type header. Pass the subject and description in the request body.

Note: & in below Endpoints might be replaced with &amp;

Token Endpoint:

https://<your domain>/services/oauth2/token?username=<username>&password=<password+securitytoken>&grant_type=password&client_id=<clientid from connected app>&client_secret=<clientsecret from connected app>

Web Service Endpoint:

https://<your domain>/services/apexrest/CaseService/
Calling the Access Token Endpoint
Calling the Access Token Endpoint
Calling the Web Service to create Case
Calling the Web Service to create Case

If you get an authentication failure error, just add your user’s profile in the Connected App.

This is how we can use Platform Events in Lightning (Emp API). Check official Salesforce documentation here to know more about Platform Events. If you like this implementation, you may want to check the following hand-picked implementations for you.

If you don’t want to miss new implementations, please Subscribe here. Thanks!

12 thoughts on “Platform Events in Lightning (Emp API)”

  1. Hi Nikhil, This is really cool post. I have one question, once we published then its creating records in sf so where we can see all these published records in sf?

    Reply
    • Hi Mani, Thank you for reading. Record is created as soon as we hit the Web Service (Rest Resource) and the event will be published which will open the created Case automatically in Salesforce as shown in the output. There are multiple ways to view these cases. While hitting the Web Service, we are fetching access token using Username and Password of particular SF user. You can create a list view in Salesforce for Cases where the Owner is that user. Another way is to create a Boolean field on Case and you can mark it True from the Rest Resource while inserting. Then you can just create a List View or Report based on that field.

      Reply
      • Thanks for replay Nikhil, I was asking about once we publish then it stores into event bus right so can we see all those events?

        Reply
        • Platform event messages are published to the event bus and they are stored temporarily. You can retrieve stored event messages from the event bus using a CometD (Streaming API) client. We cannot see those events in Salesforce directly.

          Reply
  2. Greetings Nikhil!
    I have added the lightning component which subscribes the event as component of Sales home page rather than utility bar. When I have the home page opened and do a httppost through work bench, new opened case is navigated. but if I have some other tab opened and do httppost, when I move to home page navigation to case doesn’t have happen. Can you please explain this?

    how long a published event will remain in event bus? Also can the event be subscribed by multiple components?

    Reply
    • Hi Udayakumar,
      1. When you open another Tab, the lightning component which subscribes to the event is not in the DOM at all. So basically that component is not subscribed. That is why I mentioned in the post that, We should keep this component in Utility Bar which is available on all the pages/tabs in the application. The component should subscribe before the event is published to listen to that event.
      2. Published Event can remain in Event Bus for 24 hours and we can increase it up to 72 hours using High-Volume Platform Event.
      3. Yes.

      Reply
        • Hi Nikhil
          I tried to test it through post man but not getting desired result. This is the first time I am using Postman. I was able to get access token using http post. Under Headers, I have given key as Content-type and for the value I gave the access token returned in previous step and did a post to https://udayhome-dev-ed.lightning.force.com/services/apexrest/CaseService/
          but it was giving me the below error.

          [
          {
          “message”: “Session expired or invalid”,
          “errorCode”: “INVALID_SESSION_ID”
          }
          ]

          I tried regenerating the access token but still same issue.

          Reply
          • For Content-Type, you have to provide application/JSON. Add another header ‘Authorization’ and pass ‘Bearer’ + ‘Access Token’ separated by Space as a value.

  3. Hello, do you know what happens to platform events after they expire? (i.e. after 72 hours)?
    Can we refetch them?
    Or are they lost forever?

    Reply

Leave a Comment