Montag, 9. Dezember 2013

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.

1 Kommentar :

  1. Good to read about WebSocket in connection with Oracle.

    Regarding push from Oracle to browser clients, you might be interested in taking a look at a different architectural approach:

    It's an open source project which provides a routing component which enables push directly from the database to Web apps, using WebSocket for the front-end connection. The push logic is in PL/SQL, and there's only routing logic in the middle layer.

    (Full disclosure: I work for Tavendo, the company which created