Skip to content

wAsync (Java)

A fluent, lightweight WebSocket/HTTP client for the Atmosphere Framework, powered by java.net.http (JDK 21+). Zero external dependencies beyond SLF4J.

Supports WebSocket, Server-Sent Events (SSE), HTTP Streaming, Long-Polling, and gRPC transports with automatic fallback, reconnection, and a type-safe encoder/decoder pipeline.

<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-wasync</artifactId>
<version>${project.version}</version>
</dependency>

wAsync ships from the same monorepo as the rest of Atmosphere. Source lives in modules/wasync/.

import org.atmosphere.wasync.*;
import org.atmosphere.wasync.impl.AtmosphereClient;
import org.atmosphere.wasync.impl.AtmosphereRequestBuilder;
var client = AtmosphereClient.newClient();
var request = ((AtmosphereRequestBuilder) client.newRequestBuilder())
.uri("ws://localhost:8080/chat")
.transport(Request.TRANSPORT.WEBSOCKET)
.build();
var socket = client.create()
.on(Event.OPEN, o -> System.out.println("Connected!"))
.on(Event.MESSAGE, m -> System.out.println("Received: " + m))
.on(Event.CLOSE, c -> System.out.println("Disconnected"))
.on(Event.ERROR, e -> System.err.println("Error: " + e))
.open(request);
socket.fire("Hello from wAsync!");
TransportProtocolUse Case
WEBSOCKETFull-duplex WebSocketReal-time bidirectional messaging
SSEServer-Sent EventsServer push over HTTP
STREAMINGHTTP chunked streamingContinuous server push
LONG_POLLINGRepeated HTTP requestsUniversal fallback
GRPCgRPC bidirectional streamingHigh-performance binary over HTTP/2

Chain transports for automatic fallback:

var request = ((AtmosphereRequestBuilder) client.newRequestBuilder())
.uri("http://localhost:8080/chat")
.transport(Request.TRANSPORT.WEBSOCKET) // try first
.transport(Request.TRANSPORT.SSE) // fallback
.transport(Request.TRANSPORT.LONG_POLLING) // last resort
.build();

Connect to an Atmosphere gRPC server. Requires atmosphere-grpc, grpc-netty-shaded, grpc-protobuf, and grpc-stub on the classpath.

var request = ((AtmosphereRequestBuilder) client.newRequestBuilder())
.uri("grpc://localhost:9090/chat")
.transport(Request.TRANSPORT.GRPC)
.build();
var socket = client.create()
.on(Event.OPEN, o -> System.out.println("gRPC connected"))
.on(Event.MESSAGE, m -> System.out.println("Received: " + m))
.open(request);
socket.fire("Hello via gRPC!");
socket.on(Event.OPEN, o -> { /* connected */ })
.on(Event.MESSAGE, m -> { /* message received */ })
.on(Event.CLOSE, c -> { /* disconnected */ })
.on(Event.ERROR, e -> { /* error occurred */ })
.on(Event.REOPENED, r -> { /* reconnected after disconnect */ })
.on(Event.STATUS, s -> { /* HTTP status code */ })
.on(Event.HEADERS, h -> { /* response headers */ });
Encoder<ChatMessage, String> jsonEncoder = msg ->
new ObjectMapper().writeValueAsString(msg);
var request = ((AtmosphereRequestBuilder) client.newRequestBuilder())
.uri("ws://localhost:8080/chat")
.transport(Request.TRANSPORT.WEBSOCKET)
.encoder(jsonEncoder)
.build();
socket.fire(new ChatMessage("Alice", "Hello!"));
Decoder<String, ChatMessage> jsonDecoder = new Decoder<>() {
@Override
public ChatMessage decode(Event event, String data) {
if (event == Event.MESSAGE) {
return new ObjectMapper().readValue(data, ChatMessage.class);
}
return null;
}
};
var options = client.newOptionsBuilder()
.reconnect(true)
.reconnectAttempts(5)
.pauseBeforeReconnectInSeconds(3)
.waitBeforeUnlocking(2000)
.requestTimeoutInSeconds(60)
.httpClient(myHttpClient)
.build();
var socket = client.create(options)
.on(Event.OPEN, o -> System.out.println("Connected"))
.open(request);

wAsync stacks four layers on top of the JDK’s own HTTP client. Each row below is a horizontal plane in the client; a call to .fire() travels top-down through the codec and transport layers and lands on a JDK socket.

LayerSurfaceWhat it does
Your applicationSpring / Quarkus / plain JavaBusiness code that calls into the Socket API
Socket API + codec pipeline.on(...), .fire(...), .close(); Encoder / DecoderOutbound: fire(POJO) → encode → send. Inbound: receive → decode → on(MESSAGE). Type-safe, pluggable per transport.
Transport layer (auto-fallback)Request.Builder.transport(...)WEBSOCKETSSESTREAMINGLONG_POLLINGGRPC. Picks the first one the server accepts; falls back automatically on failure.
Network backendjava.net.http.HttpClient + grpc-java (optional)JDK-native HTTP/2 + WebSocket via java.net.http (JDK 21+); bidirectional streaming over HTTP/2 via grpc-java when atmosphere-grpc is on the classpath.