(Quick Reference)

20 Native WebSockets - Reference Documentation

Authors: Andrea Del Bene, Martin Grigorov, Carsten Hufe, Christian Kroemer, Daniel Bartl, Paul Borș

Version: 6.x

20 Native WebSockets

WebSockets is a technology that provides full-duplex communications channels over a single TCP connection. This means that once the browser establish a web socket connection to the server the server can push data back to the browser without the browser explicitly asking again and again whether there is something new for it.

Wicket Native WebSockets modules provide functionality to integrate with the non-standard APIs provided by different web containers (like Apache Tomcat and Jetty) and standard JSR356 implementations.

Native WebSocket works only when both the browser and the web containers support WebSocket technology. There are no plans to add support to fallback to long-polling, streaming or any other technology that simulates two way communication. Use it only if you really know that you will run your application in an environment that supports WebSockets. Currently supported web containers are Jetty 7.5+ and Tomcat 7.0.27+. Supported browsers can be found at caniuse.com.

20.1 How does it work ?

Each of the modules provide a specialization of org.apache.wicket.protocol.http.WicketFilter that registers implementation specific endpoint when an HTTP request is upgraded to WebSocket one. Later Wicket uses this endpoint to write data back to the browser and read data sent by it.

WebSockets communication can be used in a Wicket page by using org.apache.wicket.protocol.ws.api.WebSocketBehavior or in a IResource by exteding org.apache.wicket.protocol.ws.api.WebSocketResource. When a client is connected it is being registered in a application scoped registry using as a key the application name, the client session id, and the id of the page or the resource name that registered it. Later when the server needs to push a message it can use this registry to filter out which clients need to receive the message.

When a message is received from the client Wicket wraps it in IWebSocketMessage and calls WebSocketBehavior#onMessage() or WebSocketResource#onMessage() where the application logic can react on it. The server can push plain text and binary data to the client, but it can also add components for re-render, prepend/append JavaScript as it can do with Ajax.

20.2 How to use

  • Classpath dependency

Depending on the web container that is used the application has to add a dependency to either:

  • for Jetty 9.0.x

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket-native-websocket-jetty9</artifactId>
  <version>...</version>
</dependency>
  • for Jetty 7.x and 8.x

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket-native-websocket-jetty</artifactId>
  <version>...</version>
</dependency>
  • for Tomcat 7.0.27+ (first, non-JSR356 implementation)

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket-native-websocket-tomcat</artifactId>
  <version>...</version>
</dependency>
  • for JSR356 complaint implementations (at the moment are supported: Tomcat 8.x, Tomcat 7.0.47+, Jetty 9.1.x and JBoss Wildfly 8.0.Final)

<dependency>
  <groupId>org.apache.wicket</groupId>
  <artifactId>wicket-native-websocket-javax</artifactId>
  <version>...</version>
</dependency>

The examples above show snippets for Maven's pom.xml but the application can use any other dependency management tool like Gradle, SBT, …
  • web.xml

In WEB-INF/web.xml replace the usage of WicketFilter with any of the following depending on the web container that is used:

For Jetty 9.0.x:

<filter-class>org.apache.wicket.protocol.ws.jetty9.Jetty9WebSocketFilter</filter-class>

For Jetty 7.5+ and 8.x:

<filter-class>org.apache.wicket.protocol.ws.jetty7.Jetty7WebSocketFilter</filter-class>

For Tomcat 7.0.27+ (old implementation):

<filter-class>org.apache.wicket.protocol.ws.tomcat7.Tomcat7WebSocketFilter</filter-class>

For JSR356 complaint web containers (at the moment: Tomcat 7.0.47+, Tomcat 8.x and Jetty 9.1.x):

<filter-class>org.apache.wicket.protocol.ws.javax.JavaxWebSocketFilter</filter-class>
  • WebSocketBehavior

org.apache.wicket.protocol.ws.api.WebSocketBehavior is similar to Wicket Ajax behaviors that you may have used. Add WebSocketBehavior to the page (or to any component in the page) that will use web socket communication:

public class MyPage extends WebPage {

public MyPage() { add(new WebSocketBehavior() { @Override protected void onMessage(WebSocketRequestHandler handler, TextMessage message) { String msg = message.getText(); // do something with msg } }); } }

Use message.getText() to read the message sent by the client and use handler.push(String) to push a text message to the connected client. Additionally you can use handler.add(Component...) to add Wicket components for re-render, handler#prependJavaScript(CharSequence) and handler#appendJavaScript(CharSequence) as you do with AjaxRequestTarget.

  • WebSocketResource

Wicket allows one thread at a time to use a page instance to simplify the usage of the pages in multithreaded enviroment. When a WebSocket message is sent to a page Wicket needs to acquire the lock to that page to be able to pass the IWebSocketMessage to the WebSocketBehavior. This may be problematic when the application needs to send many messages from the client to the server. For this reason Wicket provides WebSocketResource - an IResource implemetation that provides the same APIs as WebSocketBehavior. The benefit is that there is no need of synchronization as with the pages and the drawback is that WebSocketRequesthandler#add(Component...) method cannot be used because there is no access to the components in an IResource.

To register such WebSocket resource add such line to YourApplication#init() method:

getSharedResources().add("someName", new MyWebSocketResource());

and

page.add(new BaseWebSocketBehavior("someName"));
to any page. This will prepare the JavaScript connection for you.
  • WebSocket connection registry

To push data to one or more clients the application can use the IWebSocketConnectionRegistry to find all registered connections and send data to all/any of them:

Application application = Application.get(applicationName);
WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
IWebSocketConnectionRegistry webSocketConnectionRegistry = webSocketSettings.getConnectionRegistry();
IWebSocketConnection connection = webSocketConnectionRegistry.getConnection(application, sessionId, key);

20.3 Client-side APIs

By adding a (Base)WebSocketBehavior to your component(s) Wicket will contribute wicket-websocket-jquery.js library which provides some helper functions to write your client side code. There is a default websocket connection per Wicket Page opened for you which you can use like:
Wicket.WebSocket.send('{msg: "my message"}').

If you need more WebSocket connections then you can do:

var ws = new Wicket.WebSocket(); 
ws.send('message');

To close a connection:

Wicket.WebSocket.close()

or

ws.close()

Wicket.WebSocket is a simple wrapper around the native window.WebSocket API which is used to intercept the calls and to fire special JavaScript events (Wicket.Event PubSub). Once a page that contributes (Base)WebSocketBehavior is rendered the client may react on messages pushed by the server by subscribing to the '/websocket/message' event:

Wicket.Event.subscribe("/websocket/message", function(jqEvent, message) {
  var data = JSON.parse(message);
  processData(data); // does something with the pushed message
});

Here is a table of all events that the application can subscribe to:

Event nameArgumentsDescription
/websocket/openjqEventA WebSocket connection has been just opened
/websocket/messagejqEvent, messageA message has been received from the server
/websocket/closedjqEventA WebSocket connection has been closed
/websocket/errorjqEventAn error occurred in the communication. The connection will be closed

20.4 Testing

The module provides org.apache.wicket.protocol.ws.util.tester.WebSocketTester which gives you the possibility to emulate sending and receiving messages without the need to run in a real web container, as WicketTester does this for HTTP requests. Check WebSocketTesterBehaviorTest and WebSocketTesterResourceTest for an examples.

20.5 Differences with Wicket-Atmosphere module.

Wicket-Atmosphere experimental module provides integration with Atmosphere and let it handle the inconsistencies in WebSocket protocol support in different browsers and web containers. If either the browser or the web container do not support WebSockets then Atmosphere will downgrade (depending on the configuration) to either long-polling, streaming, server-side events, jsonp, … to simulate the long running connection.

20.6 FAQ

  1. Request and session scoped beans do not work.

The Web Socket communication is not processed by Servlet Filters and Listeners and thus the Dependency Injection libraries have no chance to export the request and session beans.