Java bindings for SLIM generated via uniffi-bindgen-java.
- Native Java Interface: Idiomatic Java API with sync methods; async variants via
CompletableFutureavailable - Java 21: Built for modern Java with records and latest language features
- JNA Integration: Seamless native library loading via Java Native Access (JNA)
- Complete Examples: Server, Point-to-Point, and Group messaging examples
- slimrpc Support: Protocol Buffers RPC over SLIM - see SLIMRPC.md for details
- Task Automation: Integrated with Taskfile for easy builds and testing
- Java 21 or higher
- Maven 3.8+
- Rust toolchain (for building native library)
- uniffi-bindgen-java (auto-installed via Taskfile)
cd java
task generateThis will:
- Build the Rust bindings library
- Install uniffi-bindgen-java (if not present)
- Generate Java source files
- Copy native libraries to the correct platform directory
task buildCreates a JAR at target/slim-bindings-java-1.2.0.jar.
task installMakes the bindings available to the examples and other local projects.
# Start server
task examples:server
# Point-to-point (in separate terminals)
task examples:p2p:alice
task examples:p2p:bob
# Group messaging (in separate terminals)
task examples:group:moderator
task examples:group:client-1
task examples:group:client-2┌─────────────────────────┐
│ Java Application │
│ (Your Code) │
└───────────┬─────────────┘
│
│ Sync / CompletableFuture API
▼
┌─────────────────────────┐
│ Generated Java Classes │
│ (uniffi-bindgen-java) │
└───────────┬─────────────┘
│
│ JNA
▼
┌─────────────────────────┐
│ Native Library │
│ libslim_bindings.so │
│ (Rust + UniFFI) │
└─────────────────────────┘
java/
├── Taskfile.yaml # Build automation
├── pom.xml # Maven configuration
├── uniffi.toml # UniFFI Java bindings config
├── README.md # This file
├── generated/ # Generated code (gitignored)
│ ├── uniffi/slim_bindings/ # Java source files
│ └── native/ # Native libraries by platform (JNA format)
│ ├── darwin-x86-64/
│ ├── darwin-aarch64/
│ ├── linux-x86-64/
│ ├── linux-aarch64/
│ ├── win32-x86-64/
│ └── win32-aarch64/
└── examples/ # Java examples
├── Taskfile.yaml
├── pom.xml
└── src/main/java/io/agntcy/slim/examples/
├── common/ # Shared utilities
├── Server.java # Server example
├── PointToPoint.java # P2P messaging
└── Group.java # Group messaging
import io.agntcy.slim.bindings.*;
// Initialize with defaults
SlimBindings.initializeWithDefaults();
// Or with OpenTelemetry tracing
SlimBindings.initializeWithTracing("my-app", "localhost:4317");Service service = SlimBindings.getGlobalService();
Name appName = new Name("org", "namespace", "app");
// Create app with shared secret
App app = service.createAppWithSecret(appName, "my-secret-min-32-chars!!!!!!!!!!");// Create client config
ClientConfig config = SlimBindings.newInsecureClientConfig("http://localhost:46357");
// Connect (sync)
Long connectionId = service.connect(config);Separate from the app identity passed to createAppWithSecret and friends, the gRPC
connection to a SLIM node can carry its own credentials via ClientConfig.setAuth (and
ServerConfig.setAuth when hosting). Supported modes are Basic, StaticJwt, Jwt,
Spire, and Oidc.
OIDC, client side (client-credentials flow):
ClientConfig config = SlimBindings.newInsecureClientConfig("http://localhost:46357");
config.setAuth(new ClientAuthenticationConfig.Oidc(new OidcConfig(
"https://auth.example.com", // issuerUrl
"my-client", // clientId
"s3cr3t", // clientSecret
null, // audience
null, null, null, // refreshToken, refreshTokenFile, accessTokenFile
"openid profile", // scope
Duration.ofSeconds(30), // timeout (client-side)
null, // jwksTtl (server-side)
null, // claimCacheTtl (server-side)
null))); // policy (server-side)
Long connectionId = service.connect(config);For the refresh-token flow set refreshToken — or refreshTokenFile, which is rewritten
in place as tokens rotate — instead of clientSecret.
Server side, verifying incoming JWTs against the issuer's JWKS endpoint, optionally restricting access by claim:
ServerConfig config = SlimBindings.newInsecureServerConfig("127.0.0.1:46357");
config.setAuth(new ServerAuthenticationConfig.Oidc(new OidcConfig(
"https://auth.example.com",
null, null,
"slim", // audience - required for verification
null, null, null, null, null,
Duration.ofHours(1), // jwksTtl
Duration.ofMinutes(1), // claimCacheTtl
new OidcPolicyConfig.Cel("\"admin\" in claims.groups"))));policy accepts OidcPolicyConfig.Cel, OidcPolicyConfig.Rego (which must define
package slim.auth with default allow = false), or OidcPolicyConfig.RegoFile.
Client-only fields (scope, timeout) and server-only fields (jwksTtl,
claimCacheTtl, policy) are ignored by the other side.
From a config file — SlimBindings.newConfigFromJson accepts a full gRPC client config,
covering TLS material, backoff, and every authentication mode. The examples read the same
document from SLIM_CLIENT_CONFIG:
{
"endpoint": "http://127.0.0.1:46357",
"tls": { "insecure": true },
"auth": {
"type": "oidc",
"issuer_url": "https://auth.example.com",
"client_id": "my-client",
"client_secret": "s3cr3t",
"audience": "slim",
"policy": { "cel": "\"admin\" in claims.groups" }
}
}The schema matches data-plane/core/config/src/grpc/schema/client-config.schema.json in the
slim repo.
Name remoteName = new Name("org", "namespace", "remote");
// Create point-to-point session
SessionConfig sessionConfig = new SessionConfig(
SessionType.POINT_TO_POINT,
null, // maxRetries
null, // interval
Map.of(), // metadata
new MlsSettings(100) // mlsSettings (null to disable)
);
Session session = app.createSessionAndWait(sessionConfig, remoteName);byte[] message = "Hello, SLIM!".getBytes();
// Publish and wait
session.publishAndWait(message, null, null);Duration timeout = Duration.ofSeconds(30);
ReceivedMessage msg = session.getMessage(timeout);
System.out.println("Received: " + new String(msg.payload()));Async variants (*Async) returning CompletableFuture are available for all operations. They can be a good choice when using Virtual Threads (Java 21+), where blocking is cheap and you can use .get() or .join() without tying up OS threads.
When using the standard Java thread model (OS threads) with async methods, consider increasing the common pool parallelism:
java -Djava.util.concurrent.ForkJoinPool.common.parallelism=16 -jar myapp.jarRun task in the java/ directory to see all available tasks:
task # List all tasks
task generate # Generate Java bindings
task build # Build Java code and create JAR
task install # Install JAR to local Maven repository
task clean # Clean build artifacts and generated code
task examples:server # Run server example
task examples:p2p:alice # Run P2P receiver
task examples:p2p:bob # Run P2P sender
task examples:group:* # Run group examplesSee examples/README.md for detailed example documentation.
| Platform | Architecture | Status |
|---|---|---|
| macOS | x86_64 | ✅ Supported |
| macOS | aarch64 (M1/M2) | ✅ Supported |
| Linux | x86_64 | ✅ Supported |
| Linux | aarch64 | ✅ Supported |
| Windows | x86_64 | ✅ Supported |
Copyright AGNTCY Contributors (https://github.com/agntcy)
SPDX-License-Identifier: Apache-2.0