Master Complex Business Logic with LiteFlow: A Lightweight Java Flow Engine
This article introduces LiteFlow, a lightweight Java flow engine, demonstrating how to replace verbose if‑else logic with concise rule files, covering its main features, IDEA plugin support, rule expression syntax, integration steps, component implementation, and a complete order‑price calculation example.
LiteFlow Overview
LiteFlow is a lightweight, powerful flow‑engine framework for orchestrating complex componentized business logic in Java. It lets you define each piece of logic as a Spring component and connect them with concise rule files.
Main Features
Unified component definition using Spring annotations such as @Component.
Lightweight rule files (XML, JSON, YML) that can be learned in minutes.
Support for serial, parallel, switch, and conditional compositions.
Rules can be loaded from local files or Zookeeper.
Hot‑refresh of rules without restarting the application.
Compatible with SpringBoot, Spring, or any Java project.
IDEA Plugin
LiteFlow provides an IDEA plugin LiteFlowX offering intelligent rule‑file suggestions, syntax highlighting, navigation between components and rules, and a toolbox for quick access.
Install the plugin from the IDEA marketplace.
After installation, components and rule files display distinct icons.
When editing a rule file, defined components are suggested and navigation to the component is supported.
The toolbox can be opened from the right side for quick component and rule view.
Rule Expressions
Serial Composition
Execute components a, b, c, d in order using the THEN keyword.
<chain name="chain1">
THEN(a, b, c, d);
</chain>Parallel Composition
Execute components a, b, c concurrently with the WHEN keyword.
<chain name="chain1">
WHEN(a, b, c);
</chain>Switch Composition
Implement switch‑like logic using SWITCH to route to a specific component.
<chain name="chain1">
SWITCH(a).to(b, c, d);
</chain>Conditional (IF) Composition
Simple if logic with IF, ternary with IF(..., a, b), else with ELSE, and else‑if with ELIF.
<chain name="chain1">
IF(x, a);
</chain> <chain name="chain1">
IF(x, a, b);
</chain> <chain name="chain1">
IF(x, a).ELSE(b);
</chain> <chain name="chain1">
IF(x1, a).ELIF(x2, b).ELSE(c);
</chain>Sub‑flow
Define a sub‑flow and reference it in the main flow for clearer logic.
<chain name="subChain">
THEN(C, D);
</chain> <chain name="mainChain">
THEN(
A, B,
subChain,
E
);
</chain>Integration Example
Add the Maven dependency:
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>2.8.5</version>
</dependency>Configure rule file location in application.yml:
server:
port: 8580
liteflow:
# rule file path
rule-source: liteflow/*.el.xmlDefine components by extending NodeComponent (or NodeSwitchComponent) and implementing process() and optionally isAccess(). Example coupon deduction component:
@Component("couponCmp")
public class CouponCmp extends NodeComponent {
@Override
public void process() throws Exception {
PriceContext context = this.getContextBean(PriceContext.class);
Long couponId = context.getCouponId();
BigDecimal couponPrice = new BigDecimal(15);
BigDecimal prePrice = context.getLastestPriceStep().getCurrPrice();
BigDecimal currPrice = prePrice.subtract(couponPrice);
context.addPriceStep(new PriceStepVO(PriceTypeEnum.COUPON_DISCOUNT,
couponId.toString(), prePrice, currPrice.subtract(prePrice),
currPrice, PriceTypeEnum.COUPON_DISCOUNT.getName()));
}
@Override
public boolean isAccess() {
PriceContext context = this.getContextBean(PriceContext.class);
return context.getCouponId() != null;
}
}Define the rule files. Promotion sub‑flow:
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="promotionChain">
THEN(fullCutCmp, fullDiscountCmp, rushBuyCmp);
</chain>
</flow>Main flow linking all components:
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="mainChain">
THEN(
checkCmp, slotInitCmp, priceStepInitCmp,
promotionConvertCmp, memberDiscountCmp,
promotionChain, couponCmp,
SWITCH(postageCondCmp).to(postageCmp, overseaPostageCmp),
priceResultCmp, stepPrintCmp
);
</chain>
</flow>Add a controller to receive order data and execute the flow:
@Controller
public class PriceExampleController {
@Resource
private FlowExecutor flowExecutor;
@RequestMapping(value = "/submit", method = RequestMethod.POST)
@ResponseBody
public String submit(@Nullable @RequestBody String reqData) {
try {
PriceCalcReqVO req = JSON.parseObject(reqData, PriceCalcReqVO.class);
LiteflowResponse response = flowExecutor.execute2Resp("mainChain", req, PriceContext.class);
return response.getContextBean(PriceContext.class).getPrintLog();
} catch (Throwable t) {
t.printStackTrace();
return "error";
}
}
}Conclusion
LiteFlow is an easy‑to‑learn, lightweight flow engine that turns tangled business logic into clear, maintainable processes. Its simple rule syntax and IDE support let developers get started in minutes, making it a practical choice for complex Java backend workflows.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
