eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Introduction

This article provides a first hands-on overview of Evette — a new open-source Java rule engine.

Historically, Evrete has been developed as a lightweight alternative to the Drools Rule Engine. It is fully compliant with the Java Rule Engine specification and uses the classical forward-chaining RETE algorithm with several tweaks and features for processing large amounts of data.

It requires Java 8 and higher, has zero dependencies, seamlessly operates on JSON and XML objects, and allows functional interfaces as rules’ conditions and actions.

Most of its components are extensible through Service Provider Interfaces, and one of these SPI implementations turns annotated Java classes into executable rulesets. We will give it a try today as well.

2. Maven Dependencies

Before we jump to the Java code, we need to have the evrete-core Maven dependency declared in our project’s pom.xml:

<dependency>
    <groupId>org.evrete</groupId>
    <artifactId>evrete-core</artifactId>
    <version>3.0.01</version>
</dependency>

3. Use Case Scenario

To make the introduction less abstract, let’s imagine that we run a small business, today is the end of the financial year, and we want to compute total sales per customer.

Our domain data model will include two simple classes — Customer and Invoice:

public class Customer {
    private double total = 0.0;
    private final String name;

    public Customer(String name) {
        this.name = name;
    }

    public void addToTotal(double amount) {
        this.total += amount;
    }
    // getters and setters
}
public class Invoice {
    private final Customer customer;
    private final double amount;

    public Invoice(Customer customer, double amount) {
        this.customer = customer;
        this.amount = amount;
    }
    // getters and setters
}

On a side note, the engine supports Java Records out of the box and allows the developers to declare arbitrary class properties as functional interfaces.

Later in this introduction, we will be given a collection of invoices and customers, and logic suggests we need two rules to handle the data:

  • The first rule clears each customer’s total sales value
  • The second rule matches invoices and customers and updates each customer’s total.

Once again, we’ll implement these rules with fluid rule builder interfaces and as annotated Java classes. Let’s start with the Rule builder API.

4. Rule Builder API

Rule builders are central building blocks for developing domain-specific languages (DSL) for rules. Developers will use them when parsing Excel sources, plain text, or whichever other DSL format needs to be turned into rules.

In our case, though, we’re primarily interested in their ability to embed rules straight into the developer’s code.

4.1. Ruleset Declaration

With rule builders, we can declare our two rules using fluent interfaces:

KnowledgeService service = new KnowledgeService();
Knowledge knowledge = service
  .newKnowledge()
  .newRule("Clear total sales")
  .forEach("$c", Customer.class)
  .execute(ctx -> {
      Customer c = ctx.get("$c");
      c.setTotal(0.0);
  })
  .newRule("Compute totals")
  .forEach(
      "$c", Customer.class,
      "$i", Invoice.class
  )
  .where("$i.customer == $c")
  .execute(ctx -> {
      Customer c = ctx.get("$c");
      Invoice i = ctx.get("$i");
      c.addToTotal(i.getAmount());
  });

First, we created an instance of KnowledgeService, which is essentially a shared executor service. Usually, we should have one instance of KnowledgeService per application.

The resulting Knowledge instance is a pre-compiled version of our two rules. We did this for the same reasons we compile sources in general — to ensure correctness and launch the code faster.

Those familiar with the Drools rule engine will find our rule declarations semantically equivalent to the following DRL version of the same logic:

rule "Clear total sales"
  when
    $c: Customer
  then
    $c.setTotal(0.0);
end

rule "Compute totals"
  when
    $c: Customer
    $i: Invoice(customer == $c)
  then
    $c.addToTotal($i.getAmount());
end

4.2. Mocking Test Data

We will test our ruleset on three customers and 100k invoices with random amounts and randomly distributed among the customers:

List<Customer> customers = Arrays.asList(
  new Customer("Customer A"),
  new Customer("Customer B"),
  new Customer("Customer C")
);

Random random = new Random();
Collection<Object> sessionData = new LinkedList<>(customers);
for (int i = 0; i < 100_000; i++) {
    Customer randomCustomer = customers.get(random.nextInt(customers.size()));
    Invoice invoice = new Invoice(randomCustomer, 100 * random.nextDouble());
    sessionData.add(invoice);
}

Now, the sessionData variable contains a mix of Customer and Invoice instances that we will insert into a rule session.

4.3. Rule Execution

All we will need to do now is to feed all the 100,003 objects (100k invoices plus three customers) to a new session instance and call its fire() method:

knowledge
  .newStatelessSession()
  .insert(sessionData)
  .fire();

for(Customer c : customers) {
    System.out.printf("%s:\t$%,.2f%n", c.getName(), c.getTotal());
}

The last lines will print the resulting sales volumes for each customer:

Customer A:	$1,664,730.73
Customer B:	$1,666,508.11
Customer C:	$1,672,685.10

5. Annotated Java Rules

Although our previous example works as expected, it does not make the library compliant with the specification, which expects rule engines to:

  • “Promote declarative programming by externalizing business or application logic.”
  • “Include a documented file-format or tools to author rules, and rule execution sets external to the application.”

Simply put, that means that a compliant rule engine must be able to execute rules authored outside its runtime.

And Evrete’s Annotated Java Rules extension module addresses this requirement. The module is, in fact, a “showcase” DSL, which relies solely on the library’s core API.

Let’s see how it works.

5.1. Installation

Annotated Java Rules is an implementation of one of Evrete’s Service Provider Interfaces (SPI) and requires an additional evrete-dsl-java Maven dependency:

<dependency>
    <groupId>org.evrete</groupId>
    <artifactId>evrete-dsl-java</artifactId>
    <version>3.0.01</version>
</dependency>

5.2. Ruleset Declaration

Let’s create the same ruleset using annotations. We’ll choose plain Java source over classes and bundled jars:

public class SalesRuleset {

    @Rule
    public void rule1(Customer $c) {
        $c.setTotal(0.0);
    }

    @Rule
    @Where("$i.customer == $c")
    public void rule2(Customer $c, Invoice $i) {
        $c.addToTotal($i.getAmount());
    }
}

This source file can have any name and does not need to follow Java naming conventions. The engine will compile the source as-is on the fly, and we need to make sure that:

  • our source file contains all the necessary imports
  • third-party dependencies and domain classes are on the engine’s classpath

Then we tell the engine to read our ruleset definition from an external location:

KnowledgeService service = new KnowledgeService();
URL rulesetUrl = new URL("ruleset.java"); // or file.toURI().toURL(), etc
Knowledge knowledge = service.newKnowledge(
  "JAVA-SOURCE",
  rulesetUrl
);

And that’s it. Provided that the rest of our code remains intact, we’ll get the same three customers printed along with their random sales volumes.

A few notes on this particular example:

  • We’ve chosen to build rules from plain Java (the “JAVA-SOURCE” argument), thus allowing the engine to infer fact names from method arguments.
  • Had we selected .class or .jar sources, the method arguments would have required @Fact annotations.
  • The engine has automatically ordered rules by method name. If we swap the names, the reset rule will clear previously computed volumes. As a result, we will see zero sales volumes.

5.3. How It Works

Whenever a new session is created, the engine couples it with a new instance of an annotated rule class. Essentially, we can consider instances of these classes as sessions themselves.

Therefore, class variables, if defined, become accessible to rule methods.

If we defined condition methods or declared new fields as methods, those methods would also have access to class variables.

As regular Java classes, such rulesets can be extended, reused, and packed into libraries.

5.4. Additional Features

Simple examples are well-suited for introductions but leave many important topics behind. For Annotated Java Rules, those include:

  • Conditions as class methods
  • Arbitrary property declarations as class methods
  • Phase listeners, inheritance model, and access to the runtime environment
  • And, above all, use of class fields across the board — from conditions to actions and field definitions

6. Conclusion

In this article, we briefly tested a new Java rule engine. The key takeaways include:

  1. Other engines may be better at providing ready-to-use DSL solutions and rule repositories.
  2. Evrete is instead designed for developers to build arbitrary DSLs.
  3. Those used to author rules in Java might find the “Annotated Java rules” package as a better option.

It’s worth mentioning other features not covered in this article but mentioned in the library’s API:

  • Declaring arbitrary fact properties
  • Conditions as Java predicates
  • Changing rule conditions and actions on-the-fly
  • Conflict resolution techniques
  • Appending new rules to live sessions
  • Custom implementations of library’s extensibility interfaces

The official documentation is located at https://www.evrete.org/docs/.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LS – NPI (cat=Java)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)
3 Comments
Oldest
Newest
Inline Feedbacks
View all comments