Files
session-java/README.md
T
selimaj-devandclaude 97eab5f814
Gradle Build / build (pull_request) Failing after 6s
Fix lost responses and close handling; publish to Gitea as 0.2.0
- Register pending requests before sending so fast responses aren't lost
- Fail pending requests with SessionClosedException when the connection
  closes or errors, and add onClose(), isOpen() and a request overload
  with a timeout
- Serialize text sends: java.net.http.WebSocket allows only one
  outstanding send, so concurrent requests could throw
- Reassemble text messages delivered in parts before parsing
- Complete error responses with SessionErrorException carrying the payload
- Answer requests for unknown methods with an error response
- Fix SessionResult.error() producing success responses
- Fix close() using invalid close code 0; send 1000
- Publish as dev.selimaj:session-java to the Gitea package registry;
  make Jackson an api dependency and drop unused Tyrus/Jakarta deps
- Replace the empty test with 9 tests against an in-process server

Fixes #1

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-25 14:28:04 +02:00

109 lines
3.2 KiB
Markdown

<p align="center">
<img src="logo.svg" alt="Session" width="150"/>
</p>
<h1 align="center">session-java</h1>
<p align="center">A lightweight, async WebSocket protocol for Java.</p>
## Introduction
This library provides **type-safe WebSocket communication** with a request-response and notification system built on top of a flexible protocol.
It ensures compile-time guarantees for message structure, reduces runtime errors, and simplifies building Java client/server applications.
- **Dynamic Methods**: Each message includes a method enum for type safety.
- **Typed Requests & Responses**: Automatic serialization and deserialization.
- **Optional Notifications**: Send asynchronous notifications across sessions.
## Features
- Fully typed WebSocket sessions
- Type-safe request/response mechanism
- Typed notifications
- Lightweight, minimal runtime overhead
## Installation
`session-java` is published to the Gitea package registry at `git.selimaj.dev`.
```groovy
repositories {
maven { url 'https://git.selimaj.dev/api/packages/selimaj-dev/maven' }
}
dependencies {
implementation 'dev.selimaj:session-java:0.2.0'
}
```
Versions up to 0.1.6 were published through JitPack as `com.github.selimaj-dev:session-java`.
## Usage
```java
static final Method<String, String, String> DATA =
new Method<>("data", String.class, String.class, String.class);
Session session = Session.connect("ws://localhost:8080/", 10, TimeUnit.SECONDS);
// Handle requests and notifications from the server.
session.onRequest(DATA, (id, data) -> SessionResult.ok("echo: " + data));
session.onNotification(DATA, data -> System.out.println("notified: " + data));
// Find out when the connection ends, from either side.
session.onClose(() -> System.out.println("disconnected"));
// Send a request, with or without a deadline.
String reply = session.request(DATA, "Hello", Duration.ofSeconds(10)).get();
session.close();
```
### Semantics
- A request completes exceptionally with:
- `SessionErrorException` when the peer answers with an error response (`getError()` has the payload)
- `SessionClosedException` when the session closes before the response arrives
- `TimeoutException` when the timeout passes, if one was given
- `onClose` handlers run exactly once, whether the session was closed locally, by the peer, or by a network failure. A handler registered after close runs immediately.
- Sends are serialized, so the session is safe to use from multiple threads.
- A request for an unknown method is answered with an error response instead of no reply.
## Publishing
```sh
GITEA_TOKEN=<token with package:write> ./gradlew publish
```
## Protocol
Every message is a JSON text frame with a `type` tag.
#### Request
The `id` is chosen by the sender and increments per peer.
```json
{ "type": "request", "id": 1, "method": "data", "data": "Hello from client" }
```
#### Response
A response **must** carry the id of the request it answers.
```json
{ "type": "response", "id": 1, "result": "Hello from server" }
```
#### Error response
```json
{ "type": "errorresponse", "id": 1, "error": "Invalid data" }
```
#### Notification
A notification is fire-and-forget and gets no response.
```json
{ "type": "notification", "method": "data", "data": "Hello from server" }
```