Platform Events in Salesforce:
Platform events simplify the process of communicating changes and responding to events. It is based on
Event-Driven Architecture which enable apps to communicate inside and outside of Salesforce. The
paradigm of event-based communication revolves around a publisher-subscriber model β a sender
broadcasts a message that one or more receivers capture. Events get sent whether or not receivers are
listening, and receivers donβt acknowledge it when they receive an event.
Components of Event Driven Systems:
- Events – A change in state that is meaningful in a business process .
- Event message – A message that contains data about the event.
- Event producer – The publisher of an event message over a channel.
- Event channel – Event consumers subscribe to the channel to receive messages. Also referred to as event bus in Salesforce.
- Event consumer – Event consumer is who subscribes the channel to receive messages from the channel.
Specifications:
- Platform event is appended with__e suffix for API name of the event
- We cannot query Platform events through SOQL or SOSL
- We cannot use Platform in reports, list views, and search. Platform events donβt have an associated tab
- Published platform events canβt be rolled back.
- All platform event fields are read-only by default
- Only after inserting Triggers Are Supported
- We can access platform events both through API and declaratively
- We can control platform events through Profiles and permissions
- Platform events can also be published using declarative tools like Process Builders
- Platform events can also be subscribed using Apex, or declarative tools
Publishing and Subscribing Platform events:
Define platform event similar to custom object, go to setup β> Quick find β> Platform events β> create
new platform events
Publish Platform events:
Publishing by Apex triggers:
In this, we have taken a scenario of publishing the event when the Account is created or updated with the
Custom field βIsEmployee__cβ. The value of that field is stored in the Employee platform event.
AccountTrigger:
trigger AccountTrigger on Account (before insert, before update) {
if (Trigger.isInsert || Trigger.isUpdate) {
AccountTriggerHandler.accountchanges(Trigger.new, Trigger.oldMap);
}
}
AccountTriggerHandler:
public class AccountTriggerHandler {
public static void accountchanges(List < Account > newAccounts, Map < Id, Account > oldMap) {
List < Employee__e > empList = new List < Employee__e > ();
for (Account acc: newAccounts) {
Account oldAccount = oldMap.containsKey(acc.Id) ? oldMap.get(acc.Id) : null;
System.debug('oldAccount -- ' + oldAccount);
if ((oldAccount == null && acc.IsEmployee__c) || (oldAccount != null &&
oldAccount.IsEmployee__c != acc.IsEmployee__c)) {
System.debug('Account -- ' + acc);
Employee__e emp = new Employee__e();
emp.IsEmployee__c = acc.IsEmployee__c;
empList.add(emp);
}
}
System.debug('empList -- ' + empList);
if (!empList.isEmpty()) {
publishEvent(empList);
}
}
public static void publishEvent(List < Employee__e > empList) {
// Call method to publish events
List < Database.SaveResult > results = EventBus.publish(empList);
System.debug('empList -- ' + empList);
// Inspect publishing result for each event
for (Database.SaveResult sr: results) {
if (sr.isSuccess()) {
System.debug('Successfully published event.');
} else {
for (Database.Error err: sr.getErrors()) {
System.debug('Error returned: ' +
err.getStatusCode() +
' - ' +
err.getMessage());
}
}
}
}
}
Thereby, we are publishing the event by trigger and subscribing to it using Lightning Web Components
and receiving the response in the component
Subscribing Platform events:
Subscribe by Lightning Components:
1. Lightning Web Components : Use the empApi methods in your Lightning Web Component,
import the methods from the lightning/empApi module as follows
import { subscribe, unsubscribe, onError, setDebugFlag, isEmpEnabled }
from 'lightning/empApi';
publishEvents.js
import {
LightningElement,
api
} from 'lwc';
import {
subscribe,
unsubscribe,
onError,
setDebugFlag,
isEmpEnabled
}
from 'lightning/empApi';
export default class PublishEvents extends LightningElement {
@api channelName = '/event/Employee__e';
subscription = {};
isOpen;
connectedCallback() {
this.handleSubscribe();
this.registerErrorListener();
}
handleSubscribe() {
const thisReference = this;
const messageCallback = function (response) {
console.log('New message received 1: ', JSON.stringify(response));
let payload = response.data.payload;
if (payload) {
console.log('payload: ', JSON.stringify(payload));
console.log('payload IsEmployee__c: ', JSON.stringify(payload.IsEmployee__c));
if (payload.IsEmployee__c == true) {
this.isOpen = true;
} else {
this.isOpen = false;
console.log('IsEmployee__c: ',
JSON.stringify(payload.IsEmployee__c));
}
};
subscribe(this.channelName, -1, messageCallback).then(response => {
// Response contains the subscription information on subscribe call
console.log('Subscription request sent to: ', JSON.stringify(response.channel));
});
}
registerErrorListener() {
// Invoke onError empApi method
onError(error => {
console.log('Received error from server: ', JSON.stringify(error));
// Error contains the server-side error
});
}
}
publishEvents.html
<template>
<lightning-card>
<template if:true={isOpen}>
<p><b>Account is marked as employee
</b></p>
</template>
<template if:false={isOpen}>
<p><b>Account is unmarked as employee
</b></p>
</template>
</lightning-card>
</template>
Here the component is placed on the Account detail record page, when the IsEmployee checkbox field is
set to true, it displays βAccount is marked as employeeβ and when it is set to false, it displays βAccount is
unmarked as employeeβ.
And here, we will be subscribing to the event in the βconnected callbackβ while loading the component
and we will get the response as mentioned below.