Semi-Custom Visual Rule Engine: RuleLink

Common business scenarios often involve frequent rule adjustments such as:

  • Seting maximum discounts for specific stores
  • Configuring approval thresholds for new locations
  • Creating custom contract templates
  • Adjusting holiday cost parameters

These changes traditionally require code modifications with varying frequencies (weekly to monthly), leading to scattered rule implementations across codebases and documentation. This results in:

  • High knowledge transfer costs
  • Increased maintenance cmoplexity
  • Repeated boilerplate code patterns
  • Extensive testing requirements

RuleLink Architecture

RuleLink is a visual rule management system designed to address these challenges through:

  • Centralized rule configuration
  • Dynamic rule execution
  • Reduced development overhead

The name derives from its core capability: connecting business logic through configurable rules. It leverages Aviatorscript for expression evaluation and integrates with the rule-engine-builder-ui project for UI components.

Implementation Rationale

The project originated from two key motivations:

  1. Addressing operational needs for dynamic payment account routing
  2. Rectifying limitations from previous rule menagement approaches

While modern rule engines often use Rete algorithms, RuleLink currently employs traditional pattern matching due to current rule volume constraints.

Core Components

Storage Model

  • RuleScene: Scene definitions (currently payment-focused)
  • RuleFactObj: Fact object definitions
  • RuleBase: Rule expressions with extensible execution capabilities

Date Handling Implementation


@Component
public class TimeConverter implements ApplicationContextAware {
   @Override
   public void setApplicationContext(ApplicationContext context) {
       AviatorEvaluator.addFunction(new TimeTransformer());
   }

   static class TimeTransformer extends AbstractFunction {
       @Override
       public AviatorObject call(Map<string object=""> env, AviatorObject arg1, AviatorObject arg2) {
           String timeStr = FunctionUtils.getStringValue(arg1, env);
           String pattern = FunctionUtils.getStringValue(arg2, env);
           return AviatorLong.valueOf(DateUtil.parse(timeStr, pattern).getTime() / 1000);
       }

       @Override
       public String getName() {
           return "time_transform";
       }
   }
}
 </string>

Expression Evaluation


public boolean evaluateRule(Object context, String expr) {
   Map<string object=""> variables = new HashMap<>();
   variables.put("context", context);
   
   Expression compiledExpr = AviatorEvaluator.compile(expr, true);
   Boolean result = (Boolean) compiledExpr.execute(variables);
   
   return Boolean.TRUE.equals(result);
}
 </string>

This implementation includes expression compilation caching to optimize performance for frequently executed rules.

Tags: Aviatorscript rule engine Expression Parsing Business Rules Management

Posted on Fri, 04 Sep 2026 16:38:50 +0000 by timelf123