Getting Started

What's New in 2.1.0

Released October 2026

New

Introspection — Rules That Describe Themselves

The headline of 2.1.0: everything a Rule, RuleSet, or RuleFlow is made of can now be read off the built object without running it — the foundation for rulii-explorer. Conditions, actions, and functions report an ExpressionInfo (script source, compiled method, or composite operator + operands), every RuleFlow command describes itself through CommandInfo, and definitions carry input parameters, context labels, result types, and error handlers.

// What is this condition made of?
ExpressionInfo expr = rule.getCondition().getExpression();
expr.kind();        // SCRIPT, COMPILED or COMPOSITE
expr.sourceText();  // the script text as written

// What does this flow do, step by step?
ruleFlow.getDefinition().getCommands()
        .forEach(cmd -> System.out.println(cmd));
Introspection & Metadata →
New

Category & Tags

Rules, RuleSets, and RuleFlows can now say where they belong and what they are about — for tools that group and filter them. Use @Category("Pricing/Discounts") and @Tags({"vip", "discount"}) on @Rule classes, or category(...) / tags(...) on the rule, validation rule, rule set, and rule flow builders. Both are purely descriptive: rulii never reads them when it runs.

Category & Tags →
Updated

Accurate Source Tracking

  • SourceDefinition.build() now records the real caller's location instead of pointing at itself
  • Builders accept an explicit source via source(SourceDefinition) — loaders can record where an artifact was declared (rulii-spring records the XML file and line)
  • New SourceDefinition.forFile(fileName, line) and forClass(type) factories
  • Class-based rules now record their rule class as the source, not the code that called the builder
Updated

GraalJS Scripting Overhaul

  • Polyglot context leak fixed — contexts are now released after each evaluation; under sustained evaluation the old behavior exhausted the heap
  • JavaScript values are detached as they cross into Java: arrays become ArrayLists, object literals become LinkedHashMaps, Dates become Instants — no more live proxies
  • Nashorn compatibility mode on by default — scripts read Java bean properties directly: ctx.person.name instead of ctx.person.getName()
  • Factory aliases: every spelling GraalJS registers (JS, JavaScript, ECMAScript, ...) now resolves to the configured factory
  • New ScriptProcessorManager.unregister(factory) lets integrations remove factories tied to their own lifecycle
Scripting Support →
Updated

Leak Fixes & API Polish

  • Definition cache leak fixed — building conditions, actions, functions, or rules from lambdas no longer grows the heap without bound
  • RuleRegistry.getNames() returns the keys every runnable can be looked up by
  • RuleSet and RuleFlow builders gain param(name, type, required, description) overloads; InputParameter gains a description
  • ValidationRuleBuilder.build() no longer drops the builder's description; ValueValidationRule.getValueName() is public

Breaking changes: RuleRegistry.getNames() is abstract — custom registries must implement it; ContainerCommand.getBody() is now public; RuleSetDefinition.getStopActionDefinition() is deprecated — use getStopConditionDefinition().

Spring

XML Provenance, Category & Tags

rulii-spring 2.1.0 adds the Spring side of introspection: every bean definition loaded from @RuleScan(xmlLocations) carries the XML file and line it was declared on, and XML-built artifacts report them as their SourceDefinition. Every artifact element takes category and tags attributes, with file-level defaults:

<r:defaults category="Pricing" tags="checkout"/>

<r:rule name="ApproveRule" category="Pricing/Approvals" tags="vip"
        given="#ctx.total >= 100" then="#ctx.approved = true"/>
XML Rule Definitions →
Spring

Bean Lifecycle Hardening

  • Closing a child context no longer shuts down the parent's rule infrastructure (Spring Cloud bootstrap, SpringApplicationBuilder.child(), @ContextHierarchy)
  • The rulii.executorService bean is now a RuleExecutorService that shuts down gracefully with the context — waits up to rulii.executor.awaitTerminationSeconds (default 10), then interrupts
  • ScriptProcessorFactory beans are unregistered from the JVM-wide ScriptProcessorManager when the context closes — closed contexts are no longer reachable from the process-wide registry
  • RuleRegistrarMetaInfo.xmlFiles() lists the XML files that were actually loaded, in load order
Auto-Configuration →