4

I am trying to build a Lightning component by an example from Salesforce Developers Youtube channel, here is original video: https://youtu.be/G931jWBnxHU?t=42m26s

So author encaplulated code for subscribing for Platrorm events in custom component.

Usage:

<c:Subscriber eventName="MyEvent__e" onmessage="{!c.onMessage}" />

Component:

<aura:component description="Subscriber" controller="SessionController">
    <aura:attribute name="eventName" type="String" />
    <ltng:require scripts="{!$Resource.cometd + '/cometd-javascript-master/cometd.js'}" afterScriptsLoaded="{!c.onJSLoaded}" />
    <aura:registerEvent name="onmessage" type="c:MessageEvent" />
</aura:component>

Controller:

({
    onJSLoaded: function(component, event, helper) {
        debugger;
        var action = component.get("c.getSessionId");
        action.setCallback(this, function(response) {
            var sessionId = response.getReturnValue();
            var cometd = new window.org.cometd.CometD();
            cometd.configure({
                url: window.location.protocol + '//' + window.location.hostname + '/cometd/40.0',
                requestHeaders: { Authorization: 'OAuth ' + sessionId }
            });

            cometd.handshake($A.getCallback(function(status) {
                if (status.successful) {
                    var eventName = component.get("v.eventName");
                    cometd.subscribe('/event/' + eventName, $A.getCallback(
                        function(message) {
                            console.log(message);
                            var messageEvent = component.getEvent("onmessage");
                            messageEvent.setParam("message", message);
                            messageEvent.fire();
                        }
                    ));
                }
            }));

        });
        $A.enqueueAction(action);
    }
})

When I place my component in browser, it fails at handshake method with an error

VM57302:161 Refused to connect to 'wss://kushney-dev-ed.lightning.force.com/cometd/40.0' because it violates the following Content Security Policy directive: "connect-src 'self' *.eu5.visual.force.com https://api.bluetail.salesforce.com https://preprod.bluetail.salesforce.com https://eu5.salesforce.com https://staging.bluetail.salesforce.com".

I found this article: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/security_csp_stricter.htm

I deactivated "Enable Stricter Content Security Policy for Lightning Components" critical update but that did not help.

EDIT 1

Added line cometd.websocketEnabled = false; to cometd condiguration code, now handshake is not blocked by browser, but fails with error ypeError: Cannot add property context, object is not extensible↵ at F.LongPollingTransport._self.xhrSend (/resource/1502195543000/kushney__cometd/cometd-javascript-master/cometd.js:564:25)...

  • have you tried adding the domains to the CSP trusted sites? – glls Aug 8 '17 at 13:56
  • 2
    I think you should ask a new question about the second error. It is a separate issue entirely. It's much more useful to the community to mark the answer resolved and clearly delineate issues. – Adrian Larson Aug 8 '17 at 14:30
  • and @vladdihoney, make sure you accept POZ's answer if it helped! thanks! – glls Aug 8 '17 at 16:41
  • @vladdihoney Did you ever open a question for your second problem (the TypeError that gets thrown during handshake)? Or resolve it successfully? Getting stuck with the same error when trying to do a cometD handshake. – Grekker Oct 24 '17 at 4:32
  • 2
    Figured it out. The cometd library on GitHub since version 3.1.2 added a line of code that Salesforce doesn't like, my guess is because it changes XHR and LockerService is forcing XHR to not change. Here's the offending commit: github.com/cometd/cometd/commit/… To get around this use version 3.1.1, or reverse/comment out the additions in this commit. – Grekker Oct 24 '17 at 4:58
9

The error you are reporting is related to the fact that the Salesforce Platform does not yet provide a WebSocket server for Platform Events.

While waiting for this feature, you have to add this line just after your call to cometd.configure(...) :

cometd.websocketEnabled = false;

This will switch CometD to a long polling transport.

You can check out a working example of a Lightning Component that registers to a Platform Event in the Build an Instant Notification App Trailhead project.

Cheers,

  • Thanks, this removes handshake error, but handshake is not yet successful. In console I get this: Cannot add property context, object is not extensible at F.LongPollingTransport._self.xhrSend (/resource/1502195543000/kushney__cometd/cometd-javascript-master/cometd.js:564:25)... – Vladyslav K Aug 8 '17 at 14:12
  • This could be related to a JS resource loading conflict. Before being able to receive Platform Events you need to wait for two "tasks" that are running in parallel: CometD needs to load and you need to retrieve the remote session id. You cannot predict the order in which these will be available so you need to check that in your code. Check out the code of the Trailhead project, it contains the right "lock" mechanism that ensures everything is available before connecting. – POZ Aug 8 '17 at 14:26
  • cometD initialization code is in sessionId method callback, so it is always with sessionId available, but nevermind, this is another question indeed – Vladyslav K Aug 9 '17 at 7:59
2

The Lightning Component framework uses Content Security Policy (CSP), which is a W3C standard, to control the source of content that can be loaded on a page. To use third-party APIs that make requests to an external (non-Salesforce) server, add the server as a CSP Trusted Site.

When you define a CSP Trusted Site, the site’s URL is added to the list of allowed sites for the following directives in the CSP header.

  • connect-src
  • frame-src
  • img-src
  • style-src
  • font-src
  • media-src

Create CSP Trusted Sites to Access Third-Party APIs

enter image description here

0

I was having ongoing CometD issues and just found the reason and workaround. According to sources inside Salesforce (but not documented anywhere I can find), Salesforce system push notifications use CometD and create a conflict with other implementations, killing off the conflicting processes.

Workaround: go to Settings>Apps>Mobile App>Salesforce Notifications and uncheck both boxes. This was an immediate fix for my issue. The downside is that your mobile users can't receive push notifications now.

Rumor has it that there's a major overhaul to Streaming API coming in Summer '18, which should address this issue.

  • And here we are: the new lightning:empApi component available in Winter '19 solves this problem by sharing a CometD connection between internal components and your custom components. – POZ Oct 4 '18 at 8:30
  • @POZ Yes! Excited to see this, though it doesn't support Mobile yet, so I'm waiting to convert my code. – PatMcClellan__c Oct 4 '18 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.