Java
rule-cascade-core for the JVM. No dependencies; works on maps and lists behind whatever JSON or YAML library the service already uses.
rule-cascade-core evaluates bundles and compiles source rulesets on any JVM. It has no
dependencies: it takes documents and requests as Map<String, Object>, so it sits behind Jackson,
Gson, SnakeYAML or anything else.
Supported versions: Java 17 or later (maven.compiler.release 17). CI tests JDK 17 and 21 on
Linux and JDK 21 on Windows and macOS, and builds the Spring Boot example. No maximum is declared.
Install from the repository
Install the artefact into your local Maven repository, then depend on it:
git clone https://github.com/YarlisAISolutions/rule-cascade.git
mvn -f rule-cascade/packages/java/pom.xml install<dependency>
<groupId>io.github.yarlisaisolutions</groupId>
<artifactId>rule-cascade-core</artifactId>
<version>1.0.0-alpha.2</version>
</dependency>In CI, run the same mvn install step before your build, or publish the jar to your own artefact
repository. The package is io.github.yarlisaisolutions.rulecascade.
Load
Once, at start-up. A load error must stop the application.
// From a bundle compiled in CI: no YAML, no load-time checks repeated.
@SuppressWarnings("unchecked")
Map<String, Object> parsed = (Map<String, Object>) Json.parse(text);
RuleSet rules = RuleSet.fromBundle(parsed);
// Or compile source documents: document and registry are parsed YAML or JSON as maps.
RuleSet rules = RuleSet.load(document, registry, schemaLoader);registry maps ruleset ids to documents so extends can be resolved. schemaLoader returns the
document behind an entity's $ref; with null, PATH_UNKNOWN and SCHEMA_REF_UNRESOLVED are not
checked.
Custom operators are attached with withOperators, and the start-up check compares them with what
the manifest needs:
Map<String, CustomOperator> operators = Map.of(
"x-starts-with-zero", args -> args.get(0) instanceof String s && s.startsWith("0"));
RuleSet rules = RuleSet.load(document, registry, schemaLoader).withOperators(operators);
List<String> missing = new ArrayList<>(rules.requiredOperators(Channel.SERVER));
missing.removeAll(operators.keySet());
if (!missing.isEmpty()) {
throw new IllegalStateException("custom operators not registered: " + missing);
}Evaluate
EvaluationResult result = rules.evaluate(
EvaluationRequest.builder("Transfer", "create")
.data(payload) // Map<String, Object>
.actor(userId, roles) // from authentication
.resolutions(resolutionsFromRequest)
.build());
if (!result.allowed()) {
throw new RuleViolationException(result); // return result.toMap() as problem details
}
repository.save(transfer);
result.commands().forEach(outbox::publishOnce); // de-duplicate on command.idempotencyKey()rules.evaluate(request, Channel.CLIENT) evaluates the client channel. Evaluator evaluates a
manifest received from elsewhere. A ruleset that reads ctx.now needs
.ctx(Map.of("now", Instant.now().toString())) on the builder. RuleViolationException belongs to
the Spring Boot example,
not to the library.
Errors
| What | How it surfaces | What to do |
|---|---|---|
| A bundle that is not format 1.x, or has no usable manifests | LoadException from RuleSet.fromBundle with BUNDLE_UNSUPPORTED or BUNDLE_INVALID | Let it stop start-up |
| A source ruleset that fails a check | LoadException; problems() and codes() say why | Let it stop start-up; fix it in CI |
| A request of the wrong shape | IllegalArgumentException from the builder (no entity or operation, roles that are not strings, a resolution without a rule); EvaluationRequest.fromMap applies the full wire check | Answer 400 |
| A rule that cannot be evaluated, or a missing operator | No exception: a blocking RULE-EVALUATION-ERROR finding | Alert on it |
More
The full API (bundles, places and data types, numbers, the engine protocol through Main engine)
is in the package README. A complete service is the
Spring Boot example.
Source: site/content/docs/usage/java.mdx