SlideShare a Scribd company logo
How and why I turned my old
Java projects into a first-class
serverless component
by Mario Fusco
Red Hat – Principal Software Engineer
@mariofusco
c
Agenda
➱
Declarative vs. Imperative programming
➱
What is a rule engine and how it works
➱
A simple example
➱
From drl to Java: the executable model
Agenda
➱
Declarative vs. Imperative programming
➱
What is a rule engine and how it works
➱
A simple example
➱
From drl to Java: the executable model
➱
What is GraalVM
➱
AoT compilation
➱
Limitations
➱
Refactoring Drools to (natively) compile on GraalVM
Agenda
c
➱
Declarative vs. Imperative programming
➱
What is a rule engine and how it works
➱
A simple example
➱
From drl to Java: the executable model
➱
What is GraalVM
➱
AoT compilation
➱
Limitations
➱
Refactoring Drools to (natively) compile on GraalVM
➱
What is Quarkus
➱
Quarkus features
➱
Integrating Drools with Quarkus
➱
Writing a Quarkus extension for Drools
What a rule-based program is
➱
A rule-based program is made up of discrete rules, each of which applies to a subset of the problem
➱
It is simpler, because you can concentrate on the rules for one situation at a time
➱
It can be more flexible in the face of fragmentary or poorly conditioned inputs
➱
Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in
short, all problems without clear algorithmic solutions
What a rule-based program is
➱
A rule-based program is made up of discrete rules, each of which applies to a subset of the problem
➱
It is simpler, because you can concentrate on the rules for one situation at a time
➱
It can be more flexible in the face of fragmentary or poorly conditioned inputs
➱
Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in
short, all problems without clear algorithmic solutions
Declarative
(What to do)
Imperative
(How to do it) Vs.
public void helloMark(Person person) {
if ( person.getName().equals( “Mark” ) {
System.out.println( “Hello Mark” );
}
}
rule “Hello Mark”
when
Person( name == “Mark” )
then
System.out.println( “Hello Mark” );
end
What a rule-based program is
➱
A rule-based program is made up of discrete rules, each of which applies to a subset of the problem
➱
It is simpler, because you can concentrate on the rules for one situation at a time
➱
It can be more flexible in the face of fragmentary or poorly conditioned inputs
➱
Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in
short, all problems without clear algorithmic solutions
Declarative
(What to do)
Imperative
(How to do it) Vs.
public void helloMark(Person person) {
if ( person.getName().equals( “Mark” ) {
System.out.println( “Hello Mark” );
}
}
rule “Hello Mark”
when
Person( name == “Mark” )
then
System.out.println( “Hello Mark” );
end
A method must
be called directly
Rules can never
be called directly
What a rule-based program is
➱
A rule-based program is made up of discrete rules, each of which applies to a subset of the problem
➱
It is simpler, because you can concentrate on the rules for one situation at a time
➱
It can be more flexible in the face of fragmentary or poorly conditioned inputs
➱
Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in
short, all problems without clear algorithmic solutions
Declarative
(What to do)
Imperative
(How to do it) Vs.
public void helloMark(Person person) {
if ( person.getName().equals( “Mark” ) {
System.out.println( “Hello Mark” );
}
}
rule “Hello Mark”
when
Person( name == “Mark” )
then
System.out.println( “Hello Mark” );
end
A method must
be called directly
Specific passing
of arguments
Rules can never
be called directly
Specific instances cannot
be passed but are
automatically selected
with pattern-matching
Introducing
➱
Easier to understand → Requirements can be more naturally translated into
rules. It is more likely for a technically skilled business analyst to verify, validate
or even change a rule than a piece of Java code
➱
Improved maintainability → We don't care about how to implement a solution
only what needs to be done to solve a problem
➱
Deals with evolving complexity → It's easier to modify a rule than a Java
program and to determine the impact of this change on the rest of the application
➱
Modularity → Each rule models an isolated and small portion of your business
logic and is not part of a monolithic program
➱
Clear separation of business logic from the rest of the system → Business
and infrastructural code have very different lifecycles
➱
Complex Event Processing → Facts can be handled like timestamped events
allowing temporal reasoning on them
RULES
How a rule-based system works
➱
The Rule Base contains a computation efficient
representation of the set of the defined rules
➱
The Working Memory contains the set of facts
inserted into sessions
➱
The engine matches the fact in the working
memory against the rules set
➱
When a match is found it creates an activation
and put it into the agenda
➱
An activation is the tuple of facts matching the
conditions of a rule plus the rule itself
➱
When all activations have been created the
agenda elects through a conflict resolution
strategy the one to be executed
➱
The elected activation is passed to the execution
engine and the fired
A simple rule set
rule RaiseAlarm when
exists Fire()
then
insert( new Alarm( "house1" ) );
System.out.println( "Raise the Alarm");
end
rule CancelAlarm when
not Fire()
a : Alarm()
then
delete( a );
System.out.println( "Cancel the Alarm");
end
rule TurnSprinklerOn when
s : Sprinkler( on == false )
f : Fire( room == s.room )
then
modify( s ) { setOn( true ) }
System.out.println( "Turn on the sprinkler for room " +
f.getRoom().getName() );
end
rule TurnSprinklerOff when
s : Sprinkler( on == true )
not Fire( room == s.room )
then
modify( s ) { setOn( false ) }
System.out.println( "Turn off the sprinkler for room " +
s.getRoom().getName() );
end
rule OK when
not Alarm()
not Sprinkler( on == true )
then
System.out.println( "Everything is ok" );
end
Pattern-matching
against objects in the
Working Memory
Code executed when
a match is found
What is
used by Quarkus
➱
A polyglot VM with cross-language JIT
supporting
●
Java Bytecode and JVM languages
●
Interop with different languages
●
Dynamic languages through Truffle API
➱
Cross-language interop out of the box
●
Simple AST-based interpreter
●
JIT across language boundaries
➱
Support for native binary compilation
(SubstrateVM)
●
faster boot-up
●
lower memory footprint
AoT compilation with GraalVM
➱
Static analysis
➱
Closed world assumption
➱
Dead code elimination:
     classes, fields, methods, branches
AoT compilation with GraalVM
➱
Static analysis
➱
Closed world assumption
➱
Dead code elimination:
     classes, fields, methods, branches
🚀 Fast process start
🔬 Less memory
đŸ’Ÿ Small size on disk
GraalVM Limitations
Dynaminc Classloading
Deloying jars, wars, etc. at runtime impossible
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
return defineClass( name, bytecode, 0, bytecode.length );
}
}
GraalVM Limitations
Dynaminc Classloading
Deloying jars, wars, etc. at runtime impossible
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
return defineClass( name, bytecode, 0, bytecode.length );
}
}
GraalVM Limitations
Dynaminc Classloading
Deloying jars, wars, etc. at runtime impossible
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
return defineClass( name, bytecode, 0, bytecode.length );
}
}
JVMTI, JMX + other
native VM interfaces
No agents → No JRebel, Byteman, profilers, tracers
Miscellaneous
➱
Security Manager
➱ finalize() (depreceated anyway)
➱ InvokeDynamic and MethodHandle
GraalVM Limitations
Dynaminc Classloading
Deloying jars, wars, etc. at runtime impossible
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
return defineClass( name, bytecode, 0, bytecode.length );
}
}
JVMTI, JMX + other
native VM interfaces
No agents → No JRebel, Byteman, profilers, tracers
Miscellaneous
➱
Security Manager
➱ finalize() (depreceated anyway)
➱ InvokeDynamic and MethodHandle
GraalVM Limitations
Dynaminc Classloading
Deloying jars, wars, etc. at runtime impossible
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
return defineClass( name, bytecode, 0, bytecode.length );
}
}
JVMTI, JMX + other
native VM interfaces
No agents → No JRebel, Byteman, profilers, tracers
Miscellaneous
➱
Security Manager
➱ finalize() (depreceated anyway)
➱ InvokeDynamic and MethodHandle
Reflection
Requires registration (closed world assumption)
GraalVM Limitations
Dynaminc Classloading
Deloying jars, wars, etc. at runtime impossible
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
return defineClass( name, bytecode, 0, bytecode.length );
}
}
JVMTI, JMX + other
native VM interfaces
No agents → No JRebel, Byteman, profilers, tracers
Miscellaneous
➱
Security Manager
➱ finalize() (depreceated anyway)
➱ InvokeDynamic and MethodHandle
[
{
"name" : "org.domain.model.Person",
"allPublicConstructors" : true,
"allPublicMethods" : true
}
]
Reflection
Requires registration (closed world assumption)
-H:ReflectionConfigurationFiles=src/main/resources/reflection.json
Drools on GraalVM - Executable Model
rule "Older than Mark" when
$p1: Person( name == "Mark" )
$p2: Person( name != "Mark", age > $p1.age )
then
System.out.println( $p1.getName() +
" is older than " + $p2.getName() );
end
Variable<Person> markV = declarationOf( Person.class );
Variable<Person> olderV = declarationOf( Person.class );
Rule rule = rule( "Older than Mark" )
.build(
pattern(markV)
.expr("exprA", p -> p.getName().equals( "Mark" ),
alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ),
reactOn( "name", "age" )),
pattern(olderV)
.expr("exprB", p -> !p.getName().equals("Mark"),
alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ),
reactOn( "name" ))
.expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(),
betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ),
reactOn( "age" )),
on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() ))
)
Drools on GraalVM - Executable Model
rule "Older than Mark" when
$p1: Person( name == "Mark" )
$p2: Person( name != "Mark", age > $p1.age )
then
System.out.println( $p1.getName() +
" is older than " + $p2.getName() );
end
Variable<Person> markV = declarationOf( Person.class );
Variable<Person> olderV = declarationOf( Person.class );
Rule rule = rule( "Older than Mark" )
.build(
pattern(markV)
.expr("exprA", p -> p.getName().equals( "Mark" ),
alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ),
reactOn( "name", "age" )),
pattern(olderV)
.expr("exprB", p -> !p.getName().equals("Mark"),
alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ),
reactOn( "name" ))
.expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(),
betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ),
reactOn( "age" )),
on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() ))
)
Drools on GraalVM - Executable Model
rule "Older than Mark" when
$p1: Person( name == "Mark" )
$p2: Person( name != "Mark", age > $p1.age )
then
System.out.println( $p1.getName() +
" is older than " + $p2.getName() );
end
Variable<Person> markV = declarationOf( Person.class );
Variable<Person> olderV = declarationOf( Person.class );
Rule rule = rule( "Older than Mark" )
.build(
pattern(markV)
.expr("exprA", p -> p.getName().equals( "Mark" ),
alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ),
reactOn( "name", "age" )),
pattern(olderV)
.expr("exprB", p -> !p.getName().equals("Mark"),
alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ),
reactOn( "name" ))
.expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(),
betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ),
reactOn( "age" )),
on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() ))
)
Executable
model
Indexes and
reactivity
explicitly defined
Executable Model at a glance
➱
A pure Java DSL for Drools rules authoring
➱
A pure Java canonical representation of a rule base
➱
Automatically generated by Maven plugin or
Quarkus extension
●
Can be embedded in jar
●
Faster boot
➱
Improve Backward/Forward compatibility
➱
Allow for faster prototyping and experimentation of
new features
➱
Prerequisite to make Drools natively compilable on
GraalVM
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
throw new UnsupportedOperationException();
}
}
Drools on GraalVM – other refactors
Dynamic class definition
is no longer necessary
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
throw new UnsupportedOperationException();
}
}
Drools on GraalVM – other refactors
Dynamic class definition
is no longer necessary
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="simpleKB"
packages="org.drools.simple.project">
<ksession name="simpleKS" default="true"/>
</kbase>
</kmodule>
var m = KieServices.get().newKieModuleModel();
var kb = m.newKieBaseModel("simpleKB");
kb.setEventProcessingMode(CLOUD);
kb.addPackage("org.drools.simple.project");
var ks = kb.newKieSessionModel("simpleKS");
ks.setDefault(true);
ks.setType(STATEFUL);
ks.setClockType(ClockTypeOption.get("realtime"));
public class InternalClassLoader extends ClassLoader {
public Class<?> defineClass( String name, byte[] bytecode ) {
throw new UnsupportedOperationException();
}
}
Drools on GraalVM – other refactors
Dynamic class definition
is no longer necessary
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<kbase name="simpleKB"
packages="org.drools.simple.project">
<ksession name="simpleKS" default="true"/>
</kbase>
</kmodule>
var m = KieServices.get().newKieModuleModel();
var kb = m.newKieBaseModel("simpleKB");
kb.setEventProcessingMode(CLOUD);
kb.addPackage("org.drools.simple.project");
var ks = kb.newKieSessionModel("simpleKS");
ks.setDefault(true);
ks.setType(STATEFUL);
ks.setClockType(ClockTypeOption.get("realtime"));
org.kie.api.io.KieResources =
org.drools.core.io.impl.ResourceFactoryServiceImpl
org.kie.api.marshalling.KieMarshallers =
org.drools.core.marshalling.MarshallerProviderImpl
org.kie.api.concurrent.KieExecutors =
org.drools.core.concurrent.ExecutorProviderImpl
Map<Class<?>, Object> serviceMap = new HashMap<>();
void wireServices() {
serviceMap.put( ServiceInterface.class,
Class.forName("org.drools.ServiceImpl")
.newInstance());
// 
 more services here
}
Demo 1
Drools on GraalVM
Introducing
➱
A Framework for writing (fast and
lightweight) Java applications
Introducing
➱
A Framework for writing (fast and
lightweight) Java applications
➱
(Optionally) allowing generation
of native executable via GraalVM
*.class
QUARKUS
optimized jar
native
executable
JVM
Maven/Gradle plugin
Introducing
➱
A Framework for writing (fast and
lightweight) Java applications
➱
(Optionally) allowing generation
of native executable via GraalVM
➱
Based on existing standard
●
Servlet
●
JAX-RS
●
JPA, JDBC
●
CDI
●
Bean Validation
●
Transactions
●
Logging
●
Microprofile
*.class
QUARKUS
optimized jar
native
executable
JVM
Maven/Gradle plugin
Introducing
➱
A Framework for writing (fast and
lightweight) Java applications
➱
(Optionally) allowing generation
of native executable via GraalVM
➱
Based on existing standard
●
Servlet
●
JAX-RS
●
JPA, JDBC
●
CDI
●
Bean Validation
●
Transactions
●
Logging
●
Microprofile
➱
Out-of-the-box integration with
libraries that you already know
*.class
QUARKUS
optimized jar
native
executable
JVM
Maven/Gradle plugin
Why Quarkus
Lower
memory
usage
Faster
startup
Optimized for
short-lived
processes
Kubernetes
Native
Live
reload
Microservices
Why Quarkus
Lower
memory
usage
Faster
startup
Optimized for
short-lived
processes
Kubernetes
Native
Live
reload
Microservices
Fast, lightweight Drools = Submarine
The question of whether a
computer can think is no
more interesting than the
question of whether a
submarine can swim
- Edsger W. Dijkstra
Integrating Quarkus and Drools
Writing a Quarkus extension
public class ExecutableModelGenerator {
private static final String PRODUCER_SOURCE = "package io.quarkus.drools.runtime;n" +
"import org.drools.modelcompiler.KieRuntimeBuilder;n" +
"n" +
"@javax.inject.Singletonn" +
"public class RuntimeProducer {n" +
" public static final KieRuntimeBuilder INSTANCE = new org.drools.project.model.ProjectRuntime();n" +
"n" +
" @javax.enterprise.inject.Producesn" +
" public KieRuntimeBuilder produce() { return INSTANCE; }n" +
"}";
@BuildStep(providesCapabilities = "io.quarkus.drools") @Record(STATIC_INIT)
public void generateModel( ArchiveRootBuildItem root,
BuildProducer<GeneratedBeanBuildItem> generatedBeans, BuildProducer<GeneratedClassBuildItem> generatedClasses) {
MemoryFileSystem srcMfs = new MemoryFileSystem();
String[] sources = generateSources(root, srcMfs);
srcMfs.write(toRuntimeSource(PRODUCER_CLASSNAME), PRODUCER_SOURCE.getBytes());
sources[sources.length - 1] = toRuntimeSource(PRODUCER_CLASSNAME);
registerGeneratedClasses(generatedBeans, generatedClasses, compileSources(srcMfs, sources));
}
private void registerGeneratedClasses( BuildProducer<GeneratedBeanBuildItem> generatedBeans,
BuildProducer<GeneratedClassBuildItem> generatedClasses, MemoryFileSystem trgMfs) {
for (String fileName : trgMfs.getFileNames()) {
String className = toClassName(fileName);
if (className.equals(PRODUCER_CLASSNAME)) {
generatedBeans.produce(new GeneratedBeanBuildItem(className, trgMfs.getBytes(fileName)));
} else {
generatedClasses.produce(new GeneratedClassBuildItem(true, className, trgMfs.getBytes(fileName)));
}
}
}
}
A simple Quarkus-based
REST endopint using Drools
@Path("/candrink/{name}/{age}")
public class CanDrinkResource {
@Inject
KieRuntimeBuilder runtimeBuilder;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String canDrink( @PathParam("name") String name, @PathParam("age") int age ) {
KieSession ksession = runtimeBuilder.newKieSession("canDrinkKS");
Result result = new Result();
ksession.insert(result);
ksession.insert(new Person( name, age ));
ksession.fireAllRules();
return result.toString();
}
}
Demo 2
Drools on Quarkus
Mario Fusco
Red Hat – Principal Software Engineer
mario.fusco@gmail.com
twitter: @mariofusco
Q A
Thanks ... Questions?

More Related Content

PDF
Comparing different concurrency models on the JVM
PDF
Reactive Programming for a demanding world: building event-driven and respons...
PDF
Why we cannot ignore Functional Programming
PDF
If You Think You Can Stay Away from Functional Programming, You Are Wrong
DOC
Ad java prac sol set
DOCX
Advance Java Programs skeleton
PDF
Laziness, trampolines, monoids and other functional amenities: this is not yo...
PDF
Concurrency Concepts in Java
Comparing different concurrency models on the JVM
Reactive Programming for a demanding world: building event-driven and respons...
Why we cannot ignore Functional Programming
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Ad java prac sol set
Advance Java Programs skeleton
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Concurrency Concepts in Java

What's hot (20)

PDF
The... Wonderful? World of Lambdas
PDF
Advanced Java Practical File
PDF
Currying and Partial Function Application (PFA)
DOC
CS2309 JAVA LAB MANUAL
PDF
Java 8 Workshop
PDF
Java Lab Manual
ODP
Software Transactioneel Geheugen
PDF
Java Class Design
PDF
Parallel streams in java 8
PDF
Java9 Beyond Modularity - Java 9 mĂĄs allĂĄ de la modularidad
DOCX
Parallel Programming With Dot Net
PDF
Java 8 Stream API. A different way to process collections.
PDF
DRYing to Monad in Java8
PDF
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
PDF
Creating Lazy stream in CSharp
PDF
Harnessing the Power of Java 8 Streams
PDF
Concurrency Utilities in Java 8
PPT
Functional Programming Past Present Future
PDF
Java programming lab manual
PDF
Java Concurrency Idioms
The... Wonderful? World of Lambdas
Advanced Java Practical File
Currying and Partial Function Application (PFA)
CS2309 JAVA LAB MANUAL
Java 8 Workshop
Java Lab Manual
Software Transactioneel Geheugen
Java Class Design
Parallel streams in java 8
Java9 Beyond Modularity - Java 9 mĂĄs allĂĄ de la modularidad
Parallel Programming With Dot Net
Java 8 Stream API. A different way to process collections.
DRYing to Monad in Java8
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Creating Lazy stream in CSharp
Harnessing the Power of Java 8 Streams
Concurrency Utilities in Java 8
Functional Programming Past Present Future
Java programming lab manual
Java Concurrency Idioms
Ad

Similar to How and why I turned my old Java projects into a first-class serverless component (20)

PDF
Kogito: cloud native business automation
PPT
bluespec talk
PDF
Native Java with GraalVM
PPTX
Concurrency in Eclipse: Best Practices and Gotchas
PDF
Building Hermetic Systems (without Docker)
PDF
Monitoring MySQL with DTrace/SystemTap
PPTX
Knowledge of Javascript
PPT
00_Introduction to Java.ppt
PDF
Automated scaling of microservice stacks for JavaEE applications - JEEConf 2017
PDF
JEEconf 2017
PDF
Drools Introduction
PDF
Chaos is a ladder !
PPTX
Android - Preventing common memory leaks
PDF
Nelson: Rigorous Deployment for a Functional World
PDF
Clean code & design patterns
PDF
Gradle For Beginners (Serbian Developer Conference 2013 english)
PPTX
Ch 6 randomization
PDF
Performance Test Driven Development with Oracle Coherence
PDF
Core Java Programming Language (JSE) : Chapter IV - Expressions and Flow Cont...
Kogito: cloud native business automation
bluespec talk
Native Java with GraalVM
Concurrency in Eclipse: Best Practices and Gotchas
Building Hermetic Systems (without Docker)
Monitoring MySQL with DTrace/SystemTap
Knowledge of Javascript
00_Introduction to Java.ppt
Automated scaling of microservice stacks for JavaEE applications - JEEConf 2017
JEEconf 2017
Drools Introduction
Chaos is a ladder !
Android - Preventing common memory leaks
Nelson: Rigorous Deployment for a Functional World
Clean code & design patterns
Gradle For Beginners (Serbian Developer Conference 2013 english)
Ch 6 randomization
Performance Test Driven Development with Oracle Coherence
Core Java Programming Language (JSE) : Chapter IV - Expressions and Flow Cont...
Ad

More from Mario Fusco (16)

PDF
Let's make a contract: the art of designing a Java API
PDF
OOP and FP
PDF
Lazy java
PDF
From object oriented to functional domain modeling
ODP
Drools 6 deep dive
PDF
OOP and FP - Become a Better Programmer
PDF
Monadic Java
PDF
FP in Java - Project Lambda and beyond
PPTX
Real world DSL - making technical and business people speaking the same language
PDF
Introducing Drools
PPTX
Java 7, 8 & 9 - Moving the language forward
PDF
Hammurabi
PPT
Swiss army knife Spring
PDF
No more loops with lambdaj
PPTX
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
PPTX
Scala - where objects and functions meet
Let's make a contract: the art of designing a Java API
OOP and FP
Lazy java
From object oriented to functional domain modeling
Drools 6 deep dive
OOP and FP - Become a Better Programmer
Monadic Java
FP in Java - Project Lambda and beyond
Real world DSL - making technical and business people speaking the same language
Introducing Drools
Java 7, 8 & 9 - Moving the language forward
Hammurabi
Swiss army knife Spring
No more loops with lambdaj
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Scala - where objects and functions meet

Recently uploaded (20)

PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
top salesforce developer skills in 2025.pdf
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PDF
System and Network Administraation Chapter 3
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
 
PDF
2025 Textile ERP Trends: SAP, Odoo & Oracle
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PPTX
Essential Infomation Tech presentation.pptx
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
System and Network Administration Chapter 2
PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
ai tools demonstartion for schools and inter college
PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Wondershare Filmora 15 Crack With Activation Key [2025
top salesforce developer skills in 2025.pdf
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Operating system designcfffgfgggggggvggggggggg
EN-Survey-Report-SAP-LeanIX-EA-Insights-2025.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
System and Network Administraation Chapter 3
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
 
2025 Textile ERP Trends: SAP, Odoo & Oracle
Design an Analysis of Algorithms II-SECS-1021-03
Essential Infomation Tech presentation.pptx
Adobe Illustrator 28.6 Crack My Vision of Vector Design
How to Migrate SBCGlobal Email to Yahoo Easily
System and Network Administration Chapter 2
CHAPTER 2 - PM Management and IT Context
ai tools demonstartion for schools and inter college
Softaken Excel to vCard Converter Software.pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf

How and why I turned my old Java projects into a first-class serverless component

  • 1. How and why I turned my old Java projects into a first-class serverless component by Mario Fusco Red Hat – Principal Software Engineer @mariofusco c
  • 2. Agenda ➱ Declarative vs. Imperative programming ➱ What is a rule engine and how it works ➱ A simple example ➱ From drl to Java: the executable model
  • 3. Agenda ➱ Declarative vs. Imperative programming ➱ What is a rule engine and how it works ➱ A simple example ➱ From drl to Java: the executable model ➱ What is GraalVM ➱ AoT compilation ➱ Limitations ➱ Refactoring Drools to (natively) compile on GraalVM
  • 4. Agenda c ➱ Declarative vs. Imperative programming ➱ What is a rule engine and how it works ➱ A simple example ➱ From drl to Java: the executable model ➱ What is GraalVM ➱ AoT compilation ➱ Limitations ➱ Refactoring Drools to (natively) compile on GraalVM ➱ What is Quarkus ➱ Quarkus features ➱ Integrating Drools with Quarkus ➱ Writing a Quarkus extension for Drools
  • 5. What a rule-based program is ➱ A rule-based program is made up of discrete rules, each of which applies to a subset of the problem ➱ It is simpler, because you can concentrate on the rules for one situation at a time ➱ It can be more flexible in the face of fragmentary or poorly conditioned inputs ➱ Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in short, all problems without clear algorithmic solutions
  • 6. What a rule-based program is ➱ A rule-based program is made up of discrete rules, each of which applies to a subset of the problem ➱ It is simpler, because you can concentrate on the rules for one situation at a time ➱ It can be more flexible in the face of fragmentary or poorly conditioned inputs ➱ Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in short, all problems without clear algorithmic solutions Declarative (What to do) Imperative (How to do it) Vs. public void helloMark(Person person) { if ( person.getName().equals( “Mark” ) { System.out.println( “Hello Mark” ); } } rule “Hello Mark” when Person( name == “Mark” ) then System.out.println( “Hello Mark” ); end
  • 7. What a rule-based program is ➱ A rule-based program is made up of discrete rules, each of which applies to a subset of the problem ➱ It is simpler, because you can concentrate on the rules for one situation at a time ➱ It can be more flexible in the face of fragmentary or poorly conditioned inputs ➱ Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in short, all problems without clear algorithmic solutions Declarative (What to do) Imperative (How to do it) Vs. public void helloMark(Person person) { if ( person.getName().equals( “Mark” ) { System.out.println( “Hello Mark” ); } } rule “Hello Mark” when Person( name == “Mark” ) then System.out.println( “Hello Mark” ); end A method must be called directly Rules can never be called directly
  • 8. What a rule-based program is ➱ A rule-based program is made up of discrete rules, each of which applies to a subset of the problem ➱ It is simpler, because you can concentrate on the rules for one situation at a time ➱ It can be more flexible in the face of fragmentary or poorly conditioned inputs ➱ Used for problems involving control, diagnosis, prediction, classification, pattern recognition 
 in short, all problems without clear algorithmic solutions Declarative (What to do) Imperative (How to do it) Vs. public void helloMark(Person person) { if ( person.getName().equals( “Mark” ) { System.out.println( “Hello Mark” ); } } rule “Hello Mark” when Person( name == “Mark” ) then System.out.println( “Hello Mark” ); end A method must be called directly Specific passing of arguments Rules can never be called directly Specific instances cannot be passed but are automatically selected with pattern-matching
  • 9. Introducing ➱ Easier to understand → Requirements can be more naturally translated into rules. It is more likely for a technically skilled business analyst to verify, validate or even change a rule than a piece of Java code ➱ Improved maintainability → We don't care about how to implement a solution only what needs to be done to solve a problem ➱ Deals with evolving complexity → It's easier to modify a rule than a Java program and to determine the impact of this change on the rest of the application ➱ Modularity → Each rule models an isolated and small portion of your business logic and is not part of a monolithic program ➱ Clear separation of business logic from the rest of the system → Business and infrastructural code have very different lifecycles ➱ Complex Event Processing → Facts can be handled like timestamped events allowing temporal reasoning on them RULES
  • 10. How a rule-based system works ➱ The Rule Base contains a computation efficient representation of the set of the defined rules ➱ The Working Memory contains the set of facts inserted into sessions ➱ The engine matches the fact in the working memory against the rules set ➱ When a match is found it creates an activation and put it into the agenda ➱ An activation is the tuple of facts matching the conditions of a rule plus the rule itself ➱ When all activations have been created the agenda elects through a conflict resolution strategy the one to be executed ➱ The elected activation is passed to the execution engine and the fired
  • 11. A simple rule set rule RaiseAlarm when exists Fire() then insert( new Alarm( "house1" ) ); System.out.println( "Raise the Alarm"); end rule CancelAlarm when not Fire() a : Alarm() then delete( a ); System.out.println( "Cancel the Alarm"); end rule TurnSprinklerOn when s : Sprinkler( on == false ) f : Fire( room == s.room ) then modify( s ) { setOn( true ) } System.out.println( "Turn on the sprinkler for room " + f.getRoom().getName() ); end rule TurnSprinklerOff when s : Sprinkler( on == true ) not Fire( room == s.room ) then modify( s ) { setOn( false ) } System.out.println( "Turn off the sprinkler for room " + s.getRoom().getName() ); end rule OK when not Alarm() not Sprinkler( on == true ) then System.out.println( "Everything is ok" ); end Pattern-matching against objects in the Working Memory Code executed when a match is found
  • 12. What is used by Quarkus ➱ A polyglot VM with cross-language JIT supporting ● Java Bytecode and JVM languages ● Interop with different languages ● Dynamic languages through Truffle API ➱ Cross-language interop out of the box ● Simple AST-based interpreter ● JIT across language boundaries ➱ Support for native binary compilation (SubstrateVM) ● faster boot-up ● lower memory footprint
  • 13. AoT compilation with GraalVM ➱ Static analysis ➱ Closed world assumption ➱ Dead code elimination:      classes, fields, methods, branches
  • 14. AoT compilation with GraalVM ➱ Static analysis ➱ Closed world assumption ➱ Dead code elimination:      classes, fields, methods, branches 🚀 Fast process start 🔬 Less memory đŸ’Ÿ Small size on disk
  • 15. GraalVM Limitations Dynaminc Classloading Deloying jars, wars, etc. at runtime impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } }
  • 16. GraalVM Limitations Dynaminc Classloading Deloying jars, wars, etc. at runtime impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } }
  • 17. GraalVM Limitations Dynaminc Classloading Deloying jars, wars, etc. at runtime impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Miscellaneous ➱ Security Manager ➱ finalize() (depreceated anyway) ➱ InvokeDynamic and MethodHandle
  • 18. GraalVM Limitations Dynaminc Classloading Deloying jars, wars, etc. at runtime impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Miscellaneous ➱ Security Manager ➱ finalize() (depreceated anyway) ➱ InvokeDynamic and MethodHandle
  • 19. GraalVM Limitations Dynaminc Classloading Deloying jars, wars, etc. at runtime impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Miscellaneous ➱ Security Manager ➱ finalize() (depreceated anyway) ➱ InvokeDynamic and MethodHandle Reflection Requires registration (closed world assumption)
  • 20. GraalVM Limitations Dynaminc Classloading Deloying jars, wars, etc. at runtime impossible public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { return defineClass( name, bytecode, 0, bytecode.length ); } } JVMTI, JMX + other native VM interfaces No agents → No JRebel, Byteman, profilers, tracers Miscellaneous ➱ Security Manager ➱ finalize() (depreceated anyway) ➱ InvokeDynamic and MethodHandle [ { "name" : "org.domain.model.Person", "allPublicConstructors" : true, "allPublicMethods" : true } ] Reflection Requires registration (closed world assumption) -H:ReflectionConfigurationFiles=src/main/resources/reflection.json
  • 21. Drools on GraalVM - Executable Model rule "Older than Mark" when $p1: Person( name == "Mark" ) $p2: Person( name != "Mark", age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end Variable<Person> markV = declarationOf( Person.class ); Variable<Person> olderV = declarationOf( Person.class ); Rule rule = rule( "Older than Mark" ) .build( pattern(markV) .expr("exprA", p -> p.getName().equals( "Mark" ), alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name", "age" )), pattern(olderV) .expr("exprB", p -> !p.getName().equals("Mark"), alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name" )) .expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(), betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ), reactOn( "age" )), on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() )) )
  • 22. Drools on GraalVM - Executable Model rule "Older than Mark" when $p1: Person( name == "Mark" ) $p2: Person( name != "Mark", age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end Variable<Person> markV = declarationOf( Person.class ); Variable<Person> olderV = declarationOf( Person.class ); Rule rule = rule( "Older than Mark" ) .build( pattern(markV) .expr("exprA", p -> p.getName().equals( "Mark" ), alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name", "age" )), pattern(olderV) .expr("exprB", p -> !p.getName().equals("Mark"), alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name" )) .expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(), betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ), reactOn( "age" )), on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() )) )
  • 23. Drools on GraalVM - Executable Model rule "Older than Mark" when $p1: Person( name == "Mark" ) $p2: Person( name != "Mark", age > $p1.age ) then System.out.println( $p1.getName() + " is older than " + $p2.getName() ); end Variable<Person> markV = declarationOf( Person.class ); Variable<Person> olderV = declarationOf( Person.class ); Rule rule = rule( "Older than Mark" ) .build( pattern(markV) .expr("exprA", p -> p.getName().equals( "Mark" ), alphaIndexedBy( String.class, ConstraintType.EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name", "age" )), pattern(olderV) .expr("exprB", p -> !p.getName().equals("Mark"), alphaIndexedBy( String.class, ConstraintType.NOT_EQUAL, 1, p -> p.getName(), "Mark" ), reactOn( "name" )) .expr("exprC", markV, (p1, p2) -> p1.getAge() > p2.getAge(), betaIndexedBy( int.class, ConstraintType.GREATER_THAN, 0, p -> p.getAge(), p -> p.getAge() ), reactOn( "age" )), on(olderV, markV).execute((p1, p2) -> System.out.println( p1.getName() + " is older than " + p2.getName() )) ) Executable model Indexes and reactivity explicitly defined
  • 24. Executable Model at a glance ➱ A pure Java DSL for Drools rules authoring ➱ A pure Java canonical representation of a rule base ➱ Automatically generated by Maven plugin or Quarkus extension ● Can be embedded in jar ● Faster boot ➱ Improve Backward/Forward compatibility ➱ Allow for faster prototyping and experimentation of new features ➱ Prerequisite to make Drools natively compilable on GraalVM
  • 25. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { throw new UnsupportedOperationException(); } } Drools on GraalVM – other refactors Dynamic class definition is no longer necessary
  • 26. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { throw new UnsupportedOperationException(); } } Drools on GraalVM – other refactors Dynamic class definition is no longer necessary <?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="simpleKB" packages="org.drools.simple.project"> <ksession name="simpleKS" default="true"/> </kbase> </kmodule> var m = KieServices.get().newKieModuleModel(); var kb = m.newKieBaseModel("simpleKB"); kb.setEventProcessingMode(CLOUD); kb.addPackage("org.drools.simple.project"); var ks = kb.newKieSessionModel("simpleKS"); ks.setDefault(true); ks.setType(STATEFUL); ks.setClockType(ClockTypeOption.get("realtime"));
  • 27. public class InternalClassLoader extends ClassLoader { public Class<?> defineClass( String name, byte[] bytecode ) { throw new UnsupportedOperationException(); } } Drools on GraalVM – other refactors Dynamic class definition is no longer necessary <?xml version="1.0" encoding="UTF-8"?> <kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> <kbase name="simpleKB" packages="org.drools.simple.project"> <ksession name="simpleKS" default="true"/> </kbase> </kmodule> var m = KieServices.get().newKieModuleModel(); var kb = m.newKieBaseModel("simpleKB"); kb.setEventProcessingMode(CLOUD); kb.addPackage("org.drools.simple.project"); var ks = kb.newKieSessionModel("simpleKS"); ks.setDefault(true); ks.setType(STATEFUL); ks.setClockType(ClockTypeOption.get("realtime")); org.kie.api.io.KieResources = org.drools.core.io.impl.ResourceFactoryServiceImpl org.kie.api.marshalling.KieMarshallers = org.drools.core.marshalling.MarshallerProviderImpl org.kie.api.concurrent.KieExecutors = org.drools.core.concurrent.ExecutorProviderImpl Map<Class<?>, Object> serviceMap = new HashMap<>(); void wireServices() { serviceMap.put( ServiceInterface.class, Class.forName("org.drools.ServiceImpl") .newInstance()); // 
 more services here }
  • 28. Demo 1 Drools on GraalVM
  • 29. Introducing ➱ A Framework for writing (fast and lightweight) Java applications
  • 30. Introducing ➱ A Framework for writing (fast and lightweight) Java applications ➱ (Optionally) allowing generation of native executable via GraalVM *.class QUARKUS optimized jar native executable JVM Maven/Gradle plugin
  • 31. Introducing ➱ A Framework for writing (fast and lightweight) Java applications ➱ (Optionally) allowing generation of native executable via GraalVM ➱ Based on existing standard ● Servlet ● JAX-RS ● JPA, JDBC ● CDI ● Bean Validation ● Transactions ● Logging ● Microprofile *.class QUARKUS optimized jar native executable JVM Maven/Gradle plugin
  • 32. Introducing ➱ A Framework for writing (fast and lightweight) Java applications ➱ (Optionally) allowing generation of native executable via GraalVM ➱ Based on existing standard ● Servlet ● JAX-RS ● JPA, JDBC ● CDI ● Bean Validation ● Transactions ● Logging ● Microprofile ➱ Out-of-the-box integration with libraries that you already know *.class QUARKUS optimized jar native executable JVM Maven/Gradle plugin
  • 35. Fast, lightweight Drools = Submarine The question of whether a computer can think is no more interesting than the question of whether a submarine can swim - Edsger W. Dijkstra
  • 36. Integrating Quarkus and Drools Writing a Quarkus extension public class ExecutableModelGenerator { private static final String PRODUCER_SOURCE = "package io.quarkus.drools.runtime;n" + "import org.drools.modelcompiler.KieRuntimeBuilder;n" + "n" + "@javax.inject.Singletonn" + "public class RuntimeProducer {n" + " public static final KieRuntimeBuilder INSTANCE = new org.drools.project.model.ProjectRuntime();n" + "n" + " @javax.enterprise.inject.Producesn" + " public KieRuntimeBuilder produce() { return INSTANCE; }n" + "}"; @BuildStep(providesCapabilities = "io.quarkus.drools") @Record(STATIC_INIT) public void generateModel( ArchiveRootBuildItem root, BuildProducer<GeneratedBeanBuildItem> generatedBeans, BuildProducer<GeneratedClassBuildItem> generatedClasses) { MemoryFileSystem srcMfs = new MemoryFileSystem(); String[] sources = generateSources(root, srcMfs); srcMfs.write(toRuntimeSource(PRODUCER_CLASSNAME), PRODUCER_SOURCE.getBytes()); sources[sources.length - 1] = toRuntimeSource(PRODUCER_CLASSNAME); registerGeneratedClasses(generatedBeans, generatedClasses, compileSources(srcMfs, sources)); } private void registerGeneratedClasses( BuildProducer<GeneratedBeanBuildItem> generatedBeans, BuildProducer<GeneratedClassBuildItem> generatedClasses, MemoryFileSystem trgMfs) { for (String fileName : trgMfs.getFileNames()) { String className = toClassName(fileName); if (className.equals(PRODUCER_CLASSNAME)) { generatedBeans.produce(new GeneratedBeanBuildItem(className, trgMfs.getBytes(fileName))); } else { generatedClasses.produce(new GeneratedClassBuildItem(true, className, trgMfs.getBytes(fileName))); } } } }
  • 37. A simple Quarkus-based REST endopint using Drools @Path("/candrink/{name}/{age}") public class CanDrinkResource { @Inject KieRuntimeBuilder runtimeBuilder; @GET @Produces(MediaType.TEXT_PLAIN) public String canDrink( @PathParam("name") String name, @PathParam("age") int age ) { KieSession ksession = runtimeBuilder.newKieSession("canDrinkKS"); Result result = new Result(); ksession.insert(result); ksession.insert(new Person( name, age )); ksession.fireAllRules(); return result.toString(); } }
  • 38. Demo 2 Drools on Quarkus
  • 39. Mario Fusco Red Hat – Principal Software Engineer [email protected] twitter: @mariofusco Q A Thanks ... Questions?