It’s all about Lightning right now and rightly so it’s the future; a good looking, exciting future. So what have I been doing with all of this then? I always find new technology is best learnt when you have a real use case and I have been lucky enough to have one to work on over the past few weeks. Not only that but it’s one that has lead me to have to do something that I couldn’t find documented anywhere!I’m not going to regal you with the details of the project right now – if you’re at Dreamforce though drop by the IoT zone and find, myself, Paul Battisson or Will Coleman and you should be able to see the fruits of our labour. If you’re not at DF then I’ll follow up in a couple of weeks time.

Anyway, “The Project” has required a custom user interface to be built in Salesforce and after an initial prototype in Visualforce we decided to shift across to Lightning – it’s what all the cool kids seem to be doing! One of the challenges that we had was to make the user interface play audio on demand. The playing piece is pretty easy, just use the <audio> tag it’s the “on demand” piece that proved more of a challenge.

Streaming API

In the original Visualforce prototype we made use of the Streaming API. This allowed us to create a record containing the url of the audio we wanted to play. Listening to this topic from our JavaScript on the VF page is pretty easy, and documented well, when we saw a record created we extracted the URL and updated the audio tag. Too easy.

In order to keep as much of the back end the same as possible we wanted to make us of the same mechanism in the Lightning version of the application. The only problem is that the Streaming API isn’t really supported from Lightning. Well, it’s not that it’s not supported it’s just not been documented anywhere. As one never to shirk away from a challenge I decided to get it working, whatever the cost! (The cost incidently was only a couple of hours of a Sunday afternoon, but still.) The JavaScript to change the src attribute of the audio component was going to be the easy part so I started with getting the Streaming API working.

The first step was to get all of the necessary JavaScript files loaded to support the cometd connection. All of the examples for Visualforce show that you need four files: cometd.js, jquery.js, json2.js, jquery.cometd.js adding these as resources and referencing them in via lghtn:require tags is easy. The problem I came across is the fact that as I loaded the component I kept getting sporadic errors, very occasionally though the component would load without any problems. A bit of digging and a conversation with Paul releaved what was happening – the scripts are loaded asynchronuously. This is fine when your scripts aren’t dependant on each other but here we had a clear line of dependancies. The trick to solving this is to use one require tage and provide a list of scripts. The scripts are then loaded synchronously in the order that they are listed. Problem solved.

Who Are You?

At this point we have loaded all of the JavaScript that we need to subscribe to our PushTopic, so the next obvious step is to actually listen. This however is where the second and possibly more tricky problem arises; authentication. The cometd connection back to Salesforce needs to be an authenticated one, obviously! In Visualforce the binding {!$Api.Session_ID} is used, and if this were an external application then there would be some form of OAuth going on to get a token. Given that we’re inside of Salesforce we shouldn’t need to worry about reauthentication, so no need to setup an OAuth dance. Instead we should just be able to get our session id and pass that in the Authentication header of the cometd connection.

I say “should be able to” because this is where the problem truely lies… we can’t simple bind to the $Api global variable in Lightning and get the session id. Bummer, what to do? What I did next can be described as many things… a hack, a flash of briliance, the ramblings of a mad man. I had the realisation that the session id is actually stored as a cookie on the browser – sid – and that I can read cookies from JavaScript. Therefore I could in theory read the id from the cookie and then use it in the header for the cometd connection.

Ewwww… yeah, I know it’s not pretty but it does actually work. There are a few nuances to reading cookies from JavaScript depending on browser version etc so I made use of a jQuery plugin to handle all of that for me. And this is the code I ended up with;

So What?

How fantastic! But why is this really of any interest? It helped immeasurably with this project but does it have any wider application, should you care about it? Well actually, yes, I think it does have broader appeal. Lightning is pretty cool, it looks good and it has this fantastic event driven architecture behind it allowing components to communicate with each other. But that’s all client side, what happens if there’s an event on the server side that you want your UI to react to. Sure you could build your own polling solution to look for those changes and then send out the relevant client side events. But that’s what the Streaming API does for us, so why would you ever rebuild something that already exists?! Using this code we can create ourselves a simple component that connects to the Streaming API, listens to Push Topics and then raises client side events for all our other component to react to. Taking this code and extending that isn’t a massive jump and something I’ll leave you to do yourselves – doing is the best learning remember 😉

So, whilst it’s not pretty it certainly works and is a great way to get Streaming API functionality into your Lightning components and consequently raise events on the client side for changes on the server. As for it’s robustness, well I’ll leave that one up to you – it’s clearly not going to be documented or supported by Salesforce. But it works and often that’s all that matters.