Wicket Native WebSockets modules provide functionality to integrate with the non-standard APIs provided by different web containers (like )
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.
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 http 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 .
- Classpath dependency
Add the following dependency to your application to get access to the wicket-native-websocket API on any JSR356 compliant application server (at the moment are supported: Tomcat 8.0+, Tomcat 7.0.47+, Jetty 9.1.0+ and JBoss Wildfly 8.0.0+):
- for Spring Boot applications also add
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- web.xml
In WEB-INF/web.xml replace the usage of WicketFilter with the following:
<filter-class>org.apache.wicket.protocol.ws.javax.JavaxWebSocketFilter</filter-class>
For application:
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()
{
@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.
getSharedResources().add("someName", new MyWebSocketResource());
and
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);
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"}').
To close the default connection:
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);
});
Here is a table of all events that the application can subscribe to:
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
- 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 bean proxies.