This directory contains Java examples demonstrating the SLIM Java bindings using sync methods.
- Java 21 or higher
- Maven 3.8+
- SLIM Java bindings installed to local Maven repository
# From examples/ directory
task compile
# Or using Maven directly
mvn clean compileStarts a SLIM server that relays messages between clients.
Run:
task server
# With custom address
task server CLI_ARGS="--slim 0.0.0.0:46357"
# With OpenTelemetry tracing
task server CLI_ARGS="--enable-opentelemetry"Options:
--slim <address>: Server address (default:127.0.0.1:46357)--enable-opentelemetry: Enable OpenTelemetry tracing tolocalhost:4317
What it does:
- Initializes the SLIM service
- Starts server on specified address
- Waits for Ctrl+C to shutdown gracefully
Demonstrates direct messaging between two peers.
Run Receiver (Alice):
task p2p:aliceRun Sender (Bob) in another terminal:
task p2p:bob
# With MLS encryption
task p2p:mls:bob
# With custom iterations
task p2p:bob EXTRA_ARGS="--iterations 20"Options:
--local <id>: Local identity (org/namespace/app) - REQUIRED--remote <id>: Remote identity to send to--server <url>: Server endpoint (default:http://localhost:46357)--message <text>: Message to send (enables sender mode)--iterations <n>: Number of messages (default: 10)--shared-secret <secret>: Authentication secret--enable-mls: Enable MLS encryption
Modes:
- Receiver: Omit
--messageto listen for incoming sessions - Sender: Provide
--messageand--remoteto send messages
What it does:
- Creates app and connects to server
- Sender: Creates session, sends N messages, waits for replies
- Receiver: Listens for session, echoes messages back
Demonstrates group messaging with a moderator and participants.
Run Moderator:
task group:moderatorRun Participants in separate terminals:
task group:client-1
task group:client-2Options:
--local <id>: Local identity (org/namespace/app) - REQUIRED--remote <id>: Group channel name (moderator only)--server <url>: Server endpoint (default:http://localhost:46357)--invites <id>: Participant to invite (can be repeated, moderator only)--shared-secret <secret>: Authentication secret--enable-mls: Enable MLS encryption
Modes:
- Moderator: Provide
--remoteand--invitesto create group - Participant: Omit
--remoteto wait for invitation
Interactive Commands:
- Type a message and press Enter to send to group
invite <id>: Invite new participant (moderator only)remove <id>: Remove participant (moderator only)exitorquit: Leave the group
What it does:
- Creates app and connects to server
- Moderator: Creates group session, invites participants
- Participant: Waits for invitation, joins group
- All members can send/receive messages interactively
- Messages display actual sender (not local identity)
Key Implementation Details:
- Uses
ExecutorServicewith 2 threads for parallel receive/keyboard loops - Receive loop displays messages from context's
sourceName(fix for sender display bug) - Keyboard loop reads stdin and publishes messages
- Auto-replies to messages (unless message is itself a reply to avoid loops)
The examples use sync methods for simplicity:
// Connect to server
Long connId = service.connect(config);
// Create session
Session session = app.createSessionAndWait(sessionConfig, remoteName);
// Send message
session.publishAndWait(message.getBytes(), null, null);
// Receive message
Duration timeout = Duration.ofSeconds(30);
ReceivedMessage msg = session.getMessage(timeout);Async alternatives: *Async variants returning CompletableFuture are available. They work well with Virtual Threads (Java 21+). When using OS threads with async methods, set -Djava.util.concurrent.ForkJoinPool.common.parallelism=16.
The Group example demonstrates parallel execution using ExecutorService:
ExecutorService executor = Executors.newFixedThreadPool(2);
// Launch receive loop
Future<?> receiveTask = executor.submit(() -> receiveLoop(...));
// Launch keyboard loop
Future<?> keyboardTask = executor.submit(() -> keyboardLoop(...));
// Wait for keyboard to finish
keyboardTask.get();
// Cancel receive loop
receiveTask.cancel(true);
// Cleanup
executor.shutdownNow();