Why AviatorScript Is the Lightweight JVM Rule Engine You Need

This article introduces AviatorScript, a high‑performance, lightweight JVM‑hosted scripting language for rule engines, covering its origins, key features, quick start with Maven, core syntax, control structures, custom functions, and real‑world use cases such as client version control, marketing rules, and order risk management.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Why AviatorScript Is the Lightweight JVM Rule Engine You Need

Introduction

AviatorScript is a high‑performance, lightweight script language that runs on the JVM (including Android). It originated in 2010 as a customized subset of Groovy and is lighter and faster than traditional rule engines like Drools, Jess, and JRules.

Key Features

Supports basic types such as numbers, strings, regular expressions, and booleans, and allows use of all Java operators.

Provides built‑in bigint and decimal types for arbitrary‑precision arithmetic, with operator overloading support.

Full syntax includes multi‑line data, conditional statements, loops, lexical scoping, and exception handling.

Offers a Sequence abstraction for functional‑style collection processing.

Includes a lightweight module system for organizing code.

Allows convenient Java method invocation via multiple approaches and provides a complete script API for calling scripts from Java.

Performance is exceptional: ASM mode compiles scripts directly to JVM bytecode, while an interpreter mode works on non‑standard Java platforms such as Android.

Quick Start

Add the latest Maven dependency to a Spring Boot project:

<dependency>
    <groupId>com.googlecode.aviator</groupId>
    <artifactId>aviator</artifactId>
    <version>5.3.3</version>
</dependency>

Create a script file hello.av under src/main/resources/script with the content: println("Hello, AviatorScript!"); Write a unit test to compile and execute the script:

@Test
void testHello() throws Exception {
    ClassPathResource resource = new ClassPathResource("script/hello.av");
    String scriptPath = resource.getPath();
    Expression exp = AviatorEvaluator.getInstance().compileScript(scriptPath);
    exp.execute();
}

The output is: Hello, AviatorScript! You can also compile a script defined as a string using compile() and run it directly.

AviatorScript has an IntelliJ IDEA plugin for direct compilation and execution, though it is only maintained up to IDEA 2021.

Execution Model

Running a script consists of two steps: compile and execute. The compiled Expression object can be executed with a context map that supplies variables:

String expression = "a-(b-c) > 100";
Expression compiledExp = AviatorEvaluator.compile(expression);
Map<String, Object> context = new HashMap<>();
context.put("a", 100.3);
context.put("b", 45);
context.put("c", -199.100);
Boolean result = (Boolean) compiledExp.execute(context);
System.out.println(result);

This capability enables dynamic rule evaluation by injecting parameters into the script.

Basic Syntax

Numbers

AviatorScript supports integers (mapped to Java long), floating‑point numbers ( double), and high‑precision Decimal (BigDecimal) using the M suffix.

let a = 99;
let b = 0xFF;
let c = -99;
println(a + b); // 270
println(a / b); // 0

Type conversion follows the order long → bigint → decimal → double. Explicit conversion functions long(x) and double(x) are available.

Strings

Strings are enclosed in single or double quotes. Concatenation uses the + operator, and utility functions such as string.length and string.substring reside in the string namespace.

let a = "hello world";
println(string.length(a)); // 11
println(a + ", " + "AviatorScript!"); // hello world, AviatorScript!

Booleans and Logical Operators

Boolean values are true and false. Comparison operators ( >, >=, <, <=, ==, !=) produce booleans, and logical operators can be used in conditional expressions.

println("3 > 1 is " + (3 > 1)); // true
println("3 == 1 is " + (3 == 1)); // false

Control Flow

Conditional Statements

if (true) {
    println("in if body");
} else {
    println("in else body");
}

let a = rand(1100);
if (a > 1000) {
    println("a is greater than 1000.");
} elsif (a > 100) {
    println("a is greater than 100.");
} else {
    println("a is less than 100.");
}

Loops

for i in range(0, 10) {
    println(i);
}

for i in range(0, 10, 2) {
    println(i); // prints even numbers
}

let sum = 1;
while sum < 1000 {
    sum = sum + sum;
}
println(sum);

Loop control statements continue, break, and return are supported.

Functions

Define functions with the fn keyword:

fn add(x, y) {
    return x + y;
}
three = add(1, 2);
println(three); // 3

Custom Java functions can be injected by extending AbstractFunction and registering them with an AviatorEvaluatorInstance:

public class AddFunction extends AbstractFunction {
    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        Number left = FunctionUtils.getNumberValue(arg1, env);
        Number right = FunctionUtils.getNumberValue(arg2, env);
        return new AviatorDouble(left.doubleValue() + right.doubleValue());
    }
    @Override
    public String getName() { return "add"; }
}

Real‑World Cases

Dynamic Rule Engine

Store AviatorScript scripts in a configuration center or database, allowing business rules to be changed without redeploying code.

Client Version Control

Define a custom compareVersion function in Java, register it, and use scripts to enable or disable features based on Android or iOS version.

if (device == "Android" && compareVersion(version, "1.38.1") < 0) {
    return false;
}
return true;

Marketing Activity Rules

Write discount logic in scripts so that marketing teams can modify thresholds and amounts without code changes.

if (amount >= 100) {
    return 200;
} elsif (amount >= 500) {
    return 100;
} else {
    return 0;
}

Order Risk Control

if (amount >= 1000 || rating <= 2) {
    return "High";
} elsif (amount >= 500 || rating <= 4) {
    return "Mid";
} else {
    return "Low";
}

These examples demonstrate how AviatorScript’s extensibility and lightweight nature make it suitable for rule‑driven backend services.

Conclusion

AviatorScript offers a rich yet lightweight syntax, high performance, and seamless Java integration, making it an excellent choice for building flexible rule engines and reducing development effort in backend systems.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMrule engineBackend DevelopmentScriptingAviatorScript
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

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.