In this tutorial we'll create a basic client-server application with a WebSocket connection using ActiveJ framework.
You need to import the following dependencies:
<dependencies>
<dependency>
<groupId>io.activej</groupId>
<artifactId>activej-launchers-http</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
The Logback dependency is optional.
In this tutorial we'll explicitly use the following ActiveJ technologies:
- ActiveJ HTTP - high-performance asynchronous client and server implementations.
- ActiveInject - lightweight and powerful dependency injection library.
-
ActiveJ Launcher - highly generalized
mainmethod implementation for managing application lifecycle. - ActiveJ Eventloop - provides efficient management of asynchronous operations without multithreading overhead.
- ActiveJ Promise - high-performance and handy Java Future alternative.
- ActiveJ Service Graph - designed to be used in combination with ActiveInject and ActiveJ Launcher as a means to start/stop application services according to their dependency graph.
WebSocket Pong Server
Let’s create a “Pong” WebSocket server. For this purpose we need to provide a RoutingServlet and use mapWebSocket method to map a Consumer of WebSocket as a servlet on /path. Our server will simply accept messages, print them out, and stream back a “Pong” message.
public final class WebSocketPongServerExample extends HttpServerLauncher {
@Provides
AsyncServlet servlet() {
return RoutingServlet.create()
.mapWebSocket("/", webSocket -> webSocket.readMessage()
.whenResult(message -> System.out.println("Received:" + message.getText()))
.then(() -> webSocket.writeMessage(Message.text("Pong")))
.whenComplete(webSocket::close));
}
public static void main(String[] args) throws Exception {
WebSocketPongServerExample launcher = new WebSocketPongServerExample();
launcher.launch(args);
}
}
WebSocket Ping Client
Now let’s create a client that will send a “Ping” message to server via WebSocket connection.
public final class WebSocketPingClientExample extends Launcher {
@Inject
AsyncHttpClient httpClient;
@Inject
Eventloop eventloop;
@Provides
Eventloop eventloop() {
return Eventloop.create();
}
@Provides
AsyncHttpClient client(Eventloop eventloop) {
return AsyncHttpClient.create(eventloop);
}
@Override
protected Module getModule() {
return ServiceGraphModule.create();
}
@Override
protected void run() throws ExecutionException, InterruptedException {
String url = args.length != 0 ? args[0] : "ws://127.0.0.1:8080/";
System.out.println("\nWeb Socket request: " + url);
CompletableFuture<?> future = eventloop.submit(() -> {
System.out.println("Sending: Ping");
return httpClient.webSocketRequest(HttpRequest.get(url))
.then(webSocket -> webSocket.writeMessage(Message.text("Ping"))
.then(webSocket::readMessage)
.whenResult(message -> System.out.println("Received: " + message.getText()))
.whenComplete(webSocket::close));
});
future.get();
}
public static void main(String[] args) throws Exception {
WebSocketPingClientExample example = new WebSocketPingClientExample();
example.launch(args);
}
}
First, we provide the required dependencies: AsyncHttpClient and an Eventloop for it.
Next, we need to override Launcher's getModule and run methods. getModule supplies application with basic business logic module, while run represents the main Launcher method.
In run method we create a supplier and override its get method via lambda. Here we call AsyncHttpClient.webSocketRequest that sends a request and returns a Promise of a WebSocket. Then we create a Function that sends a “Ping” message and receives a response from server.
And that's it, your WebSocket application is ready to be used. First, launch the server implementation, and then client.
You can find the source code of the examples on GitHub.
Top comments (0)