04 — Core
Bindings
A Binding is a named, typed variable. A Bindings container holds multiple bindings and acts as the shared workspace for rules — conditions read from it, and actions write to it.
Creating Bindings
// Create a standard bindings container
Bindings bindings = Bindings.builder().standard();
// Simple bind (type is inferred)
bindings.bind("name", "Alice");
bindings.bind("age", 30);
// Typed bind (explicit type)
bindings.bind("score", Integer.class, 95);
// Generic types using TypeReference
bindings.bind("tags", new TypeReference<List<String>>() {}, new ArrayList<>());
Lambda Shorthand
When running rules, you can pass bindings as lambdas. The parameter name becomes the binding name:
// These two are equivalent:
// Explicit
Bindings b = Bindings.builder().standard();
b.bind("name", "Alice");
b.bind("age", 30);
rule.run(b);
// Lambda shorthand
rule.run(name -> "Alice", age -> 30);
Reading Values
// Get value (returns Object)
Object val = bindings.getValue("name");
// Get the Binding object itself
Binding<String> binding = bindings.getBinding("name");
String name = binding.getValue(); // "Alice"
Updating Values
// Update via the Binding object
Binding<Integer> ageBind = bindings.getBinding("age");
ageBind.setValue(31);
// Or directly on the container — returns the previous value
Integer prev = bindings.setValue("age", 31); // prev == 30
// setValueOrBind: sets the value if the binding exists,
// otherwise creates a new binding. Returns the previous value or null.
Integer old = bindings.setValueOrBind("score", 100);
Checking Bindings
// Does a binding exist?
boolean exists = bindings.contains("name"); // true
// How many bindings?
int count = bindings.size();
// View as a Map (returns this — no copy made)
Map<String, Object> map = bindings.asMap();
Bindings as a Map
As of 1.2.0, Bindings directly implements java.util.Map<String, Object>. You can pass a Bindings instance anywhere a Map is expected — useful for scripting integration and interop with libraries that consume Map.
// Full Map contract — read operations
bindings.containsKey("name"); // true
bindings.containsValue("Alice"); // true
bindings.get("age"); // 30
bindings.keySet(); // Set of binding names
bindings.values(); // Collection of values
bindings.entrySet(); // Set of name-value entries
// Mutation via Map API uses bind/setValue semantics
bindings.put("status", "approved");
// remove() and clear() throw UnsupportedOperationException
Insertion order: DefaultScopedBindings now preserves insertion order (backed by LinkedHashSet instead of HashSet). The iteration order of bindings is predictable and matches the order they were added.
Scoped Bindings
Scoped bindings create a child scope that inherits from a parent. Changes in the child don't affect the parent:
Bindings scoped = Bindings.builder().scoped();
// Useful for isolating rule execution contexts
Duplicate names: By default, binding the same name twice will throw an exception. Each binding name must be unique within a container.