跪拜 Guibai
← All articles
Backend

Replace if-else Sprawl with a 100KB Java Rule Engine

By 苏三说技术 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Business-rule churn is a constant cost center. Easy Rules gives Java teams a low-ceremony way to decouple rules from application code so changes don't require recompilation or redeployment when using expression-language or YAML definitions. The trade-off is that the project is in maintenance mode, so teams betting on it accept a frozen feature set in exchange for a tiny, fast, and well-understood engine.

Summary

A single discount-calculation method can balloon past 300 lines as promotions, user tiers, and seasonal events pile on. Easy Rules, a 100KB open-source Java library from the j-easy team, moves each condition-action pair into its own class or expression string. Rules register in an ordered set, and a rules engine evaluates them against a shared Facts context, executing only those whose conditions hold.

Four definition styles cover the spectrum from hardcoded annotations to MVEL/SpEL/JEXL expressions stored in a database or YAML config. Composite rules — UnitRuleGroup, ActivationRuleGroup, and ConditionalRuleGroup — handle AND logic, exclusive-or priority selection, and conditional chaining without nested if statements. A listener API hooks into every lifecycle step for logging, metrics, or debugging.

The library entered maintenance mode in late 2020 at version 4.1.x, so it won't gain new features, but its core is stable. It suits systems with dozens to a few hundred rules; for thousands of rules or decision-table workloads, a Rete-algorithm engine like Drools fits better.

Takeaways
Easy Rules is a ~100KB Java library that models each business rule as an object with a condition method and an action method.
Rules are evaluated against a Facts key-value context; only rules whose conditions return true fire their actions.
Four definition methods are supported: POJO annotations, a fluent RuleBuilder API, MVEL/SpEL/JEXL expression strings, and YAML/JSON config files.
Expression-language and YAML/JSON rules can be stored externally and changed without recompiling the application.
DefaultRulesEngine runs rules in priority order; InferenceRulesEngine uses forward chaining, re-evaluating until no new rules trigger.
Three composite rule types combine simple rules: UnitRuleGroup (AND), ActivationRuleGroup (first-match exclusive OR), and ConditionalRuleGroup (guard-then-chain).
Engine parameters control skip-on-first-applied, skip-on-first-failed, and priority thresholds.
A RuleListener interface provides beforeEvaluate, afterEvaluate, onSuccess, and onFailure hooks.
The project has been in maintenance mode since December 2020; the latest stable release is 4.1.x.
It is not designed for thousands of rules or complex decision tables — Drools is a better fit at that scale.
Conclusions

Easy Rules occupies a deliberate middle ground: heavier than hand-rolled if-else maps stored in a database, but far lighter than a full Rete-based engine. That makes it a pragmatic stepping stone — start simple, migrate to Drools only when rule count or complexity forces the move.

The library's maintenance-mode status is a double-edged signal. It means the API is frozen and won't surprise you with breaking changes, but it also means no community-driven improvements for modern Java features like records or pattern matching will arrive.

Storing rules as MVEL or SpEL strings in a database or config file is the feature that unlocks zero-downtime rule changes, yet the article notes this still requires a custom hot-reload mechanism. Out of the box, expression-based rules still need an application restart unless you build the reload logic yourself.

Concepts & terms
Rule Engine
A software component that evaluates a set of business rules against input data (facts) and executes the corresponding actions when conditions are met, decoupling rule logic from application code.
Forward Chaining
An inference method where the engine starts with known facts, repeatedly applies rules whose conditions are satisfied, and adds new facts until no more rules can fire. Easy Rules' InferenceRulesEngine implements this.
Composite Rules
Higher-order rules that combine multiple simple rules using logical operators. Easy Rules provides UnitRuleGroup (AND), ActivationRuleGroup (first-match exclusive OR), and ConditionalRuleGroup (guard condition gates a rule chain).
MVEL / SpEL / JEXL
Expression languages that evaluate string-based logic at runtime. MVEL (MVFLEX Expression Language), SpEL (Spring Expression Language), and JEXL (Java Expression Language) let you write conditions like "user.vip == true && order.amount > 100" as plain strings, enabling external rule storage.
From the discussion
Featured comments
爬虫技术实验室

Haha, seeing this feels so familiar. When I was doing Java, I also stacked a pile of if-else — a single coupon calculation method was almost 400 lines 😂 Later I switched to Python for crawlers and price monitoring systems, and found that Python actually has a wilder way to handle rule complexity — just write a yaml config file, validate it with pydantic, then use a simple dispatch function with reflection to call it. It's not as engineered as Easy Rules, but it's enough for small to medium scale. But honestly, if I were still on the Java side back then, Easy Rules is indeed way better than pure if-else, at least you don't have to recompile and redeploy every time you add a rule.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗