Backend Development 14 min read

Applying MVEL Expression Engine for Business Indicator Calculations: Design, Performance Comparison, and Migration Strategy

This article examines the challenges of scaling store settlement calculations, evaluates several Java expression engines, selects MVEL for its performance and community support, and details the architectural redesign, database schema, caching strategy, and step‑by‑step migration process for integrating the engine into a backend system.

Zhuanzhuan Tech
Zhuanzhuan Tech
Zhuanzhuan Tech
Applying MVEL Expression Engine for Business Indicator Calculations: Design, Performance Comparison, and Migration Strategy

1 Business Situation

As the store settlement business expands, the number of aggregation metrics and the complexity of their formulas increase dramatically, leading to scattered configuration across code, Apollo, and databases, frequent updates requiring deployments, and the need to maintain multiple versions of formulas in code.

2 Research and Analysis

2.1 Why Choose an Expression Engine

Introducing an expression engine decouples calculation logic from business code, centralizes formula management, and leverages native BigDecimal support for financial‑grade precision. Dynamic execution allows real‑time formula updates without redeployment, improving agility and maintainability.

2.2 Comparison of Expression Engines

The engines evaluated were AviatorScript , MVEL , QLExpress , and OGNL .

2.2.1 Overview

AviatorScript : High‑performance, lightweight Java engine that compiles expressions to bytecode. MVEL : Dynamic/static Java‑inspired language supporting both interpreted and compiled modes. QLExpress : Alibaba’s open‑source dynamic script engine, thread‑safe and efficient. OGNL : Object‑Graph Navigation Language for accessing object properties and methods.

2.2.2 Performance Analysis

Using JMH, the test expression (cate==101&&brand==1276)?((a*18 +b*3)*x/y)-c%3+99.64 : a*18 showed that AviatorScript slightly outperformed OGNL , which outperformed MVEL , and all three were far faster than QLExpress .

2.2.3 Community Activity

GitHub statistics (Stars, Forks, Watches) indicate higher popularity for AviatorScript , MVEL , and QLExpress compared to OGNL .

2.3 Final Choice

Based on the analysis, MVEL was selected for its balanced performance, active community, and Java‑like syntax. It is widely used in projects such as Drools, Quartz Scheduler, and JBPM.

3 Business Application

3.1 Overall Design

The solution consists of three modules: Configuration Center, Formula Management Center, and Formula Execution Center. The Configuration Center stores indicator configurations, the Formula Center stores formulas, and the Execution Center computes results based on the two.

3.2 Table Structure Design

Two tables are created to store configuration data and formulas.

CREATE TABLE `business_config` (
  `id` bigint(20) NOT NULL DEFAULT '0' COMMENT 'Primary key',
  `indicator_key` varchar(255) NOT NULL DEFAULT '' COMMENT 'Indicator key',
  `attribute_key` varchar(255) NOT NULL DEFAULT '' COMMENT 'Attribute key',
  `attribute_desc` varchar(255) NOT NULL DEFAULT '' COMMENT 'Attribute description',
  `attribute_value` varchar(255) NOT NULL DEFAULT '' COMMENT 'Attribute value',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `create_by` varchar(32) NOT NULL DEFAULT '' COMMENT 'Creator',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Update time',
  `update_by` varchar(32) NOT NULL DEFAULT '' COMMENT 'Updater',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_indicator` (`indicator_key`) USING BTREE COMMENT 'Unique indicator index'
) ENGINE=InnoDB COMMENT='Business indicator configuration table';

CREATE TABLE `formula_config` (
  `id` bigint NOT NULL DEFAULT '0' COMMENT 'Primary key',
  `indicator_key` varchar(255) NOT NULL DEFAULT '' COMMENT 'Indicator key',
  `formula` varchar(500) NOT NULL DEFAULT '' COMMENT 'Formula',
  `effective_timestamp` bigint NOT NULL DEFAULT '0' COMMENT 'Effective timestamp',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `create_by` varchar(32) NOT NULL DEFAULT '' COMMENT 'Creator',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Update time',
  `update_by` varchar(32) NOT NULL DEFAULT '' COMMENT 'Updater',
  PRIMARY KEY (`id`),
  INDEX `idx_business_key`(`business_key`) USING BTREE
) ENGINE=InnoDB COMMENT='Formula table';

3.3 Main Formula Execution Flow

public BigDecimal cal(String businessKey, Map
paramMap) {
    // 1. Retrieve configuration by businessKey
    Map
configMap = qfConfigService.getConfigMapByBusinessKey(businessKey);
    // Add business document parameters
    configMap.putAll(paramMap);
    // 2. Get formula by businessKey and timestamp
    String formula = getFormula(businessKey, System.currentTimeMillis());
    // 3. Engine evaluation
    return MvelExecutor.evalExpression(formula, configMap);
}

3.4 Cache Strategy in Compile Mode

Compiled expressions are cached in Redis; when a formula changes, the cache entry is removed so the next execution recompiles the expression.

/**
  * Execute expression
  */
public BigDecimal evalExpression(String expression, Map
map) {
    Serializable cache = getCache(DesEncryptUtil.encrypt(expression));
    Object object = MVEL.executeExpression(cache, map);
    return (BigDecimal) object;
}

private Serializable getCache(String expression) {
    String cacheExpression = redisUtils.get(expression);
    if (StringUtils.isNotEmpty(cacheExpression)) {
        return JsonUtil.silentString2Object(cacheExpression, Serializable.class);
    }
    Serializable compileExpression = MVEL.compileExpression(expression);
    redisUtils.setex(expression, ONE_DAY, JsonUtil.silentObject2String(compileExpression));
    return compileExpression;
}

3.5 Business Indicator Migration

The migration is performed in five steps: code logic migration, consolidation of indicator configurations into the database, migration of formulas to MVEL expressions, data accuracy verification, and gradual rollout (gray‑scale then full deployment).

4 Summary

The use of the MVEL expression engine addresses key challenges in the settlement system by centralizing configuration, enabling instant formula updates without code releases, and reducing code complexity through versioned formula storage and timestamp‑based activation.

5 References

https://github.com/killme2008/aviatorscript

https://www.yuque.com/boyan-avfmj/aviatorscript/guhmrc

https://github.com/mvel/mvel

http://mvel.documentnode.com/

https://github.com/orphan-oss/ognl

https://github.com/alibaba/QLExpress

JavaCachebackend developmentperformance testingDatabase Designexpression-enginemvel
Zhuanzhuan Tech
Written by

Zhuanzhuan Tech

A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.