Montag, 9. Dezember 2013

Rapid Response UI with WebSockets Example

In my earlier post Rapid Response UI with WebSockets, I described a way to make your UI respond very quickly to events created by the server. Last friday I showed an example to the german ADF community. This example can be downloaded here

It is a very simple messaging application. Very straight forward without any validations or clever process handling. But you can easily send messages. When you start the application you can name yourself and receive messages from there on.
To run the example you need a table called messages. There is a Scripts folder with a create script for this table.

Have fun.

Message when connected to the WebSocket Endpoint

WebSocket message sent by the server and get request send by the client upon message receive from the server. See the badge turned from 0 to 1.

Rapid Response UI with WebSockets

If you take a close look at rich internet applications, there is no real server sided event producing. The server is always only responding to requests. This is natural since it is a problem of the HTTP protocol everything depends on. If it looks like you receive a server side message just in time, it is only because you send a request earlier in the background. This requests are causing a lot of network traffic. Since most of the time it is like a client asks "is there something new on your side" and the server only response with something like "no, ask me later again". This mechanism is called polling and is way off age. The smart new solution is called WebSockets. It's part of the HTML5 standard and specially designed to allow a bidirectional communication between server and client in a web environment.

WebSocket communication is initiated with a HTTP Request. If the server is able to communicate with the WebSocket protocol the connection gets upgraded. Now the connection does not close after every request and the server is able to send messages to the client.

Right now there is no native WebSocket support within any ADF components. But I am sure there is new stuff up ahead. I expect at least the active data sync service to be upgraded to support WebSocket connections. Right now it relies on polling and streaming.

What if I have the need to refresh the clients UI by a server event? Can I make use of this cool new WebSocket protocol, to make my ADF UI respond very quickly? Yes you can. And it is far more easy than I expected. Let's try something with a JavaScript WebSocket connection and a simply bean.

Before you start you need a Weblogic 12c or a Glasfish 4 as application server because those support the new protocol. On Glasfish you have to turn it on. On Weblogic 12c you can just start.

This is what we are going to build. A ADF Application that informs it's page about something new. Without any polling or something like that.

When you created your ADF WebApplication you need to add the Weblogic 12c API library to the ViewController project.

The next thing we create is the websocket endpoint connection. We only need a small Java class for our purpose. There we add an annotation @WebSocket and define a path for our connections.

This class does nothing very special. Most interesting is the static queue which contains all the websocket connections. This can later be used by our bean to send messages to one or all the connected clients.
The next thing we should do, is connecting to our new created WebSocket endpoint. Since we don't have any smooth af:websocketconnection component, we need to do this stuff by ourselves. Create a JavaScript file and add it to an ADF page with the af:resource component directly under the af:document tag. For Example:

<af:resource type="javascript" source="/resources/js/wsClient.js"></af:resource>

Within this JavaScript file, create method to connect to our new WebSocket endpoint. 

The shown method will show us a alert window on a successful connection. So, when we start our page now, we should get a nice alert window. You have to be careful that the defined wsUri variable matches the context root you defined for your ADF Webapplication. The added "/ws" comes from the path we created by our annotation in the endpoint class.
Next we should initiate a server side message to our client. Therefore we create a bean that sends a message to all our connected clients. And to call this method as ADF ActionEvent we also need a method that has a ActionEvent parameter.

Now we are able to connect to as client with JavaScript to our WebSocket endpoint and to send a message from within out application to all connected clients. So now we are close to the final. All we need now, is to refresh our UI on this server side event. If you search for solutions to run some Java from JavaScript in an ADF Application, you get really fast to the need of the af:serverlistener component. This can run a defined Java method from JavaScript. If you define it like this

<af:serverListener type="CallJava" method="#{sender.refresh}"/>

You need a bean called sender with a refresh method. Within JavaScript you call this serverlistener like this. 

The use of this component is already well documented so I won't go into detail with this one. Now the last thing we need, is to refresh our UI within this refresh method with a partial page rendering. Therefor we use the addPartialTarget method. 

This method executes some stuff in the bindings and adds the component that is bound to our af:serverlistener. You can also add some other components to be refreshed. 

Be careful! This is only a Proof Of Concept. Because in production this can cause your server to be very slow. Just imagine you have 1000 connected clients. In the moment you call the broadcast method, there are 1000 clients, making a request to your server in the same moment. So we created our very own DOS attack :)
If you want to use this, you have to track session information and add them to the queue so you can send a message to only one client.