Menu

Basic usage

Sridhar Ramachandran

Client side setup

On the client side, you need to include RMIWebSocket.js (CC-BY license) in the HTML like this:
<script src="RMIWebSocket.js"></script>

You can then create a callback object that can be invoked from the server. Here is an example from Samples/src/main/webapp/index.jsp:

callback = { 
  updateF: function(str) { fref.value = str; unsetErr(); },
  updateC: function(str) { cref.value = str; unsetErr(); },
  setErrF: function(str) { fref.style.background = "#FF6600"; },
  setErrC: function(str) { cref.style.background = "#FF6600"; },
  onsocketerror: function(str) { alert("Failed to connect or lost web socket"); },
  onrmierror: function(str) { alert("RMI error: " + str); }
};

The methods onsocketerror and onrmierror are optional methods that can be used to handle exceptions during communication. The other methods, viz. updateF, updateC, setErrF and setErrC, can be invoked from the server once the websocket is established.

The URI for the websocket endpoint is of the form 'ws://server:port/path?get-params. More information is available at http://en.wikipedia.org/wiki/WebSocket. In the above example, the URI is computed with simple string operations on the client's HTTP URL.

// Construct the WebSocket URI
httpUri = location.href;
wsUri = "ws://" + httpUri.substring(httpUri.indexOf("://") + 3, 
                                    httpUri.lastIndexOf("/")) + "/TempConversion";

Once the URI and callback object are available, the RMIWebSocket object can be created as follows:

rws = new RMIWebSocket(wsUri, callback);

This object supports call with one or more arguments where the first argument refers to a server-side method and the following arguments are parameters to that method. In the above example, the HTML page includes Javascript functions to invoke two method (onTempChangeC and onTempChangeF), as follows:

<form id="ftoc">
  <table>
    <tr><td>Farenheit <td> <input name="fval" onchange="submitf()"></input> </tr></td>
    <tr><td>Celcius <td> <input name="cval" onchange="submitc()"></input> </tr></td>
  </table>
</form>

...

function submitf() {
  rws.call('onTempChangeF', fref.value);
}

function submitc() {
  rws.call('onTempChangeC', cref.value);
}

The next section describes the server-side usage for this example.

Server side setup

On the server side, you need to include rmi-websocket-<ver>.jar (Apache 2 license) in your Jetty web application. Here is the example servlet from Samples/src/main/java/com/lambdazen/websocket/sample/:

package com.lambdazen.websocket.sample;

import javax.servlet.http.HttpServletRequest;
import com.lambdazen.websocket.AbstractRMIWebSocketServlet;
import com.lambdazen.websocket.IRMIWebSocket;
import com.lambdazen.websocket.IRMIWebSocketListener;

public class TempConversionServlet extends AbstractRMIWebSocketServlet {
public IRMIWebSocketListener createListener(IRMIWebSocket rws) {
        return new TempConversionService(rws);
    }

    public boolean checkOrigin(HttpServletRequest request, String origin) {
        // Allow all
        return true;
    }
}

AbstractRMIWebSocketServlet extends javax.servlet.http.HttpServlet and implements a websocket endpoint using Jetty's WebSocket Factory. The implementation is similar to the example from Websocket Example: Server, Client and LoadTest. The createListener method is invoked when a browser connects to the servlet's URI using web sockets.

In the above example, TempConversionService is the server-side equivalent of the callback object in the client-side. The handle to IRMIWebSocket is useful to call methods on the browser.

public class TempConversionService implements IRMIWebSocketListener {
    IRMIWebSocket rws;
    ...

    public TempConversionService(IRMIWebSocket rws) {
        this.rws = rws;
        ...
    }

This class implements IRMIWebSocketListener which provides three methods for cleanup and error handling:

    public void onClose() { ... }
    public void onDeserializationError(Exception e, String msg) { ... }
    public void onError(RMIWebSocketException e) { ... }

The method onClose() is called when the websocket is closed from the client. The other two methods are invoked when there are errors in deserialization or communication (resp).

The other public methods implemented by the TempConversionService can be invoked by the rws.call(...) statements in the client. The onTempChangeF and onTempChangeC methods are implemented as follows:

    public void onTempChangeF(String val) {
        onTempChange(true, val);
    }

    public void onTempChangeC(String val) {
        onTempChange(false, val);
    }

    private void onTempChange(boolean isFarenheit, String val) {
        try {
            double temp;
            try {
                temp = Double.valueOf(val);
            } catch (NumberFormatException e) {
                // Mark field as erroneous
                rws.call(isFarenheit ? "setErrF" : "setErrC");
                return;
            }

            double otherTemp = isFarenheit ? (temp - 32) * 5 / 9 : temp * 9/5 + 32;

            rws.call(isFarenheit ? "updateC" : "updateF", formatter.format(otherTemp));
        } catch (RMIWebSocketException e) {
            // Some error reporting
            System.err.println("RMIWebSocket call error");
            e.printStackTrace();
        }
    }

You can see that the calls to the onTempChangeF/C automatically invoke the various methods in the Javascript callback object using rws.call invocations.

Summary

In summary, you can use RMIWebSocket to invoke methods from a browser to a Jetty Web Server or vice-versa, by following these steps:
1. Write a service class by implementing IRMIWebSocketListener with additional public methods that you want to expose to the client (Javascript running on a browser)
2. Write and configure a servlet by extending AbstractRMIWebSocketServlet. The createListener method in this class must return the service class.
3. Use the IRMIWebSocket implementation passed in createListener to invoke calls on the client side.
4. Include RMIWebSocket.js in the HTML pages returned to the client.
5. Create a Javascript object for callbacks from the server to the browser.
6. Instantiate a Javascript RMIWebSocket object using the websocket URI corresponding to the servlet and a callback object.
7. Use the above object to make calls to the server.


Related

Wiki: Home

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.