Streaming API for Community 'n' Internal, Platform Events subscription using CometD

Salesforce out of the box Streaming API lightning components like lightning-emp-api do not support Salesforce Communities (Community Experience Cloud).

CometD is a great option for these use cases, this supports Streaming API for both Internal and Community uses, lightning emp api is built based this event and message routing bus.

CometD connects to Salesforce like an external application through the Salesforce CometD endpoint.

You can refer to the below link for more information about the CometD endpoint 



Implementation of CometD on a Lightning Web Component:

  • Download CometD from https://download.cometd.org/ 
  • Not all versions are compatible with Salesforce platform, one version that worked for me is 3.1.1
  • upload cometd.js to static resource from this path 'cometd-3.1.1\cometd-javascript\common\src\main\webapp\js\cometd' in the downloaded file. 

CometD to connect to salesforce like an external application will need to authorize itself using any salesforce supported authorization.

For Community purpose CometD can connect simply with the current user session id to keep poling to the Streaming channel CometD endpoint of the Salesforce.

For Community users to be able to use a platform event they will need a read permission to the event which can be assigned through a permission set.

Advertisement


Apex Class
public without sharing class CometD_Controller {
    @AuraEnabled(cacheable=true)
        public static String getSessionId() {
        return UserInfo.getSessionId();
    }
}

Advertisement


LWC Component

cometdlwc.html - don't be surprised to see it empty :), we need nothing as such on this file
<template>
    
</template>

cometdlwc.js
import { LightningElement, track, wire, api } from 'lwc';
import { loadScript } from "lightning/platformResourceLoader";
import cometd from "@salesforce/resourceUrl/cometd";
import getSessionId from '@salesforce/apex/CometD_Controller.getSessionId';

export default class Cometdlwc extends LightningElement {

    @api channel;

    libInitialized = false;
    @track sessionId;
    @track error;

    @wire(getSessionId)
    wiredSessionId({ error, data }) {
        if (data) {
            this.sessionId = data;
            this.error = undefined;
            loadScript(this, cometd)
            .then(() => {
                this.initializecometd()
            });
        } else if (error) {
            console.log(error);
            this.error = error;
            this.sessionId = undefined;
        }
    }

    initializecometd() {
        if (this.libInitialized) {
            return;
        }
        this.libInitialized = true;
        var lwcThisContext = this;
        var cometdlib = new window.org.cometd.CometD();
        cometdlib.configure({
            url: window.location.protocol + '//' + window.location.hostname + '/cometd/51.0/',
            requestHeaders: { Authorization: 'OAuth ' + this.sessionId},
            appendMessageTypeToURL : false,
            logLevel: 'debug'
        });
        cometdlib.websocketEnabled = false;
        cometdlib.handshake(function(status) {
            console.log('Channel Name  ', lwcThisContext.channel);
            if (status.successful) {
                cometdlib.subscribe('/event/'+ lwcThisContext.channel, function(message){
                    const selectedEvent = new CustomEvent('message', { detail: message });
                    lwcThisContext.dispatchEvent(selectedEvent);
                });
            } else {
                console.error('Error in handshaking: ' + JSON.stringify(status));
            }
        });
    }
}


The above cometdlwc LWC component can be used in any other components using the below references

this will go in to the html file
    <c-cometdlwc channel="ChannelName__e" onmessage={messageReceived}></c-cometdlwc>

this will go in to the js file
    messageReceived(event) {
        const message = event.detail;
        console.log(message);

    }


Advertisement







Comments

Popular posts