Skip to main content
Install the ZEN Engine and evaluate your first decision in Java.

Installation

The Java bindings require JDK 22 or newer. They use the FFM (Foreign Function & Memory) API to call the native Rust engine. On JDK 24+, add --enable-native-access=ALL-UNNAMED to your JVM options to silence native-access warnings. On versions 2.0.1 and earlier, the bundled native library must be provided manually: extract it from the jar for your platform and pass -Duniffi.component.zen_uniffi.libraryOverride=/absolute/path/to/library; newer versions extract it automatically.

Basic usage

Loader

The ZenEngine constructor takes a ZenLoader that resolves decisions by key. ZenLoader is a sealed interface with four variants: Callback for loading from any storage backend, and the configurations Static, Filesystem, and Zip, which pre-load and pre-compile all decisions when you create the engine.

Loader configurations

Prefer a configuration when your decisions are known up front. The engine compiles them once, so evaluations skip loading and parsing entirely.

Callback loader

Use ZenLoader.Callback to load decisions from any storage backend. The callback returns CompletableFuture<JsonBuffer>; complete it with null when the decision does not exist. Use ConcurrentHashMap to cache decisions for optimal performance.

AWS S3

Azure Blob Storage

Google Cloud Storage

Async evaluation

Evaluation returns CompletableFuture for non-blocking execution:

Batch evaluation

Use evaluateBatch to evaluate many contexts in a single call. Each request pairs a decision key with a context, and each result reports its own success or error:

Error handling

Tracing

Enable tracing to inspect decision execution:

Expression utilities

Evaluate ZEN expressions outside of a decision context:

Runtime requirements

The Java bindings use the FFM (Foreign Function & Memory) API from java.lang.foreign for interoperability with the native Rust engine. FFM requires JDK 22 or newer.

Best practices

Use try-with-resources. ZenEngine implements AutoCloseable to release native resources.
Initialize the engine once. Create a single ZenEngine instance at application startup and reuse it for all evaluations. Implement a loader for dynamic decisions. The loader pattern centralizes decision loading logic and enables caching with ConcurrentHashMap. Use CompletableFuture composition. Chain async operations or use allOf for parallel evaluation of multiple decisions.