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
main
method 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)