0

I have been through the Salesforce streaming API demo, and got that working.

For anyone wanting a reminder, the page looks like this

<apex:page >
    <apex:includeScript value="{!$Resource.cometd_js}"/>
    <apex:includeScript value="{!$Resource.jquery}"/>
    <apex:includeScript value="{!$Resource.json2_js}"/>
    <apex:includeScript value="{!$Resource.jquery_cometd}"/>

    <script type="text/javascript">
        (function($){
            $(document).ready(function() {
                // Connect to the CometD endpoint
                $.cometd.init({
                    url: window.location.protocol+'//'+window.location.hostname+'/cometd/24.0/',
                    requestHeaders: { Authorization: 'OAuth {!$Api.Session_ID}'}
                });

                // Subscribe to a topic. JSON-encoded update will be returned in the callback
                $.cometd.subscribe('/topic/InvoiceStatementUpdates', function(message) {
                    $('#content').append('<p>Notification: ' +
                        'Channel: ' + JSON.stringify(message.channel) + '<br>' +
                        'Record name: ' + JSON.stringify(message.data.sobject.Name) +
                        '<br>' + 'ID: ' + JSON.stringify(message.data.sobject.Id) + 
                        '<br>' + 'Event type: ' + JSON.stringify(message.data.event.type)+
                        '<br>' + 'Created: ' + JSON.stringify(message.data.event.createdDate) + 
                        '</p>');
                });
            });
        })(jQuery)
        function disconnect() {
           $.cometd.disconnect();
        }
        window.onbeforeunload = disconnect;
    </script>
    <body>
        <div id="content">
            <h1>Streaming API Test Page</h1>
            <p>This is a demonstration page for Streaming API. Notifications from the InvoiceStatementUpdates channel will appear here...</p>
        </div>
    </body>
</apex:page>

Now I wanted to use this in Lightning components. According to a reply by Skip Sauls here, it's supposedly doable.

This is what I have in my lightning app

<aura:application>
    <ltng:require styles=""
        scripts="/resource/cometd_js,/resource/jquery,/resource/json2_js,/resource/jquery_cometd"
        afterScriptsLoaded="{!c.setupJs}" 
    />

    <div aura:id="content">
        list:
    </div>
</aura:application>

And this is the associated controller:

({
    myAction: function(component, event, helper) {
    },

    setupJs: function() {
        // Connect to the CometD endpoint
        $.cometd.init({
            url: window.location.protocol+'//'+window.location.hostname+'/cometd/24.0/',
            requestHeaders: { Authorization: 'OAuth {!$Api.Session_ID}'}
        });

        // Subscribe to a topic. JSON-encoded update will be returned in the callback
        $.cometd.subscribe('/topic/InvoiceStatementUpdates', function(message) {
            $('.content').append('<p>Notification: ' +
                'Channel: ' + JSON.stringify(message.channel) + '<br>' +
                'Record name: ' + JSON.stringify(message.data.sobject.Name) +
                '<br>' + 'ID: ' + JSON.stringify(message.data.sobject.Id) + 
                '<br>' + 'Event type: ' + JSON.stringify(message.data.event.type)+
                '<br>' + 'Created: ' + JSON.stringify(message.data.event.createdDate) + 
                '</p>');
        });
    }
})

And lastly, this is the error I am receiving in the Chrome console log when the page loads:

POST https://smlt-dev-ed.lightning.force.com/cometd/24.0/ 401 (Unauthorized)

Now, I know that the cometd/24.0 endpoint in my VF page was preceded by a different base URL. My question is whether the Lightning supports using the streaming API, and if so, what changes do I make to my component to get it to work?

smatharu
  • 53
  • 6
  • I tried hard-coding this, to use the URL that my VF page was using. The error was expected, but here it is anyway: Refused to connect to 'https://smlt-dev-ed.my.salesforce.com/cometd/24.0/' because it violates the following Content Security Policy directive: "connect-src 'self'". Not sure where to go from here :( – smatharu Dec 03 '15 at 12:01
  • I want to warn you that this code has several cross site scripting vulnerabilities. You will need to html encode the data if you use jquery append, and this will require using another library. Alternately, build up your dom with setAttribute. – Robert Sussland Dec 03 '15 at 17:30
  • Yep I thought as much that Robert, thanks. The reason for that is that I've just copied the salesforce boilerplate code so I can get it working. I'll happily make it more secure once I know that functionally, the Streaming API can actually be used in lightning components :( – smatharu Dec 04 '15 at 09:27
  • Yes. Unfortunately the Salesforce sample code in the Ajax Toolkit (as well as other workbooks) have XSS, CRUD/FLS, and sharing vulnerabilities in their sample code. There is ongoing work to review the code and update it in the workbooks, but for the moment, please consult the secure coding guidelines: https://developer.salesforce.com/page/Secure_Coding_Guideline for the most up to date security information, rather than the workbooks. The coding guideline XSS section explicitly talks about the Ajax Toolkit. – Robert Sussland Dec 07 '15 at 01:12
  • Cheers Rob, will do. In the meantime, can anyone verify Skip Sauls' statement about being able to use PushTopics in Lightning Components? If I can'r find an answer soon, I'll have to go back to Visualforce, which would be sad, as I'm trying to show our dev teams that they need to start branching out from the (relative) safety of Visualforce – smatharu Dec 07 '15 at 17:20
  • 1
    This article may be relevant to your interests: http://blog.enree.co/2016/03/salesforce-streaming-api-on-demand.html – Mike Tetlow Apr 04 '16 at 13:36
  • Thanks Mike. This is the approach I ended up choosing when I couldn't find an answer on here.

    I was trying to avoid it, but the only way I managed to get the session ID was to return it from an Apex controller. Based on some posts by @DougChasman I got the impression that we would soon be prevented form doing that, but I guess it works for now.

    Apologies for not coming back to this thread with my workaround when I did it. Marking Mike's answer as the correct one until Salesforce provide a lightning way to get the session ID.

    – smatharu Apr 06 '16 at 07:55

1 Answers1

0

As per @mike-tetlow 's answer and link, there isn't currently a lightning way to get the session ID, so we have to resort to fetching it via an Apex controller.

smatharu
  • 53
  • 6