Monday, March 25, 2019

drools.js: Towards a Polyglot Drools on GraalVM (with Bonus Tech-Lead Prank)

Image courtesy of Massimiliano Dessì

You can find the full source code for this blog post in the submarine-examples repository.

Different programming languages are better for different purposes. Imagine how hard would it be to query a database using an imperative language: luckily, we use SQL for that. Now, imagine how useless would a rule engine be, if defining rules were not convenient! This is the reason why Drools comes with its own custom language, the DRL. The Drools Rule Language is in a so-called domain-specific language, a special-purpose programming language specifically designed to make interaction with a rule engine easier.

In particular, a rule is made of two main parts, the condition and the consequence.

The condition is a list of logic predicates, usually pattern matches, while the consequence is written using an imperative language, usually Java.

An Abstract Rule Engine

Rules are what really make a rule engine. After all, that's what a rule engine does: processing rules. Thus, it might sound kind of logical for the engine to be a bit entangled with the language for rule definitions. Our engine is not specially tied to the DRL; but it used to.

In the last year or so, we spent a lot of time unbundling the innards of the DRL from the guts of the Drools core. The result of this effort is what we called the Canonical Model; that is, an abstract representation of the components that make up a rule engine, including rule definitions. Incidentally, this also paved the way for supporting GraalVM and the Quarkus framework; but our goal was also different. We wanted to abstract our engine from the rule language.

Internally, the DRL is now translated into the canonical representation; but, as we said previously, this canonical model is described using Java code. While this representation is not currently intended to be hand-coded, it is very possible to do so. The following is a simple rewriting of the previous DRL rule.

As you can see, although the rule definition is now embedded in a Java "host" language, it still shows the main features of a DRL definition, namely, the logic condition and the imperative consequence (introduced by the on...execute pair) In other words, this is a so-called embedded or internal domain-specific language.

A small disclaimer applies: the code above works, but our translator takes extra steps for best performance, such as introducing indexes. In fact, one of the reasons why we do not intend this API for public consumption is that, currently, a naive rewrite like this may produce inefficient rules.

A Polyglot Automation Platform

As part of our journey experimenting with our programming model, we wanted to see whether it was feasible to interact with our engine using different programming languages. DRL aside, the canonical model rule definition API is pure-Java.

But GraalVM is not only a tool to generate native binaries: in fact, this is only one of the capabilities of this terrific project. GraalVM is, first and foremost, the one VM to rule them all: that is, a polyglot runtime, with first-class support for both JVM languages and many other dynamic programming languages, with a state-of-the-art JIT compiler, that easily compares or exceeds the performance of the industry standards. For instance, there is already support for R, Ruby, JavaScript and Python; and, compared to writing a JIT compiler from scratch, the Truffle framework makes it terribly easy to write your own, and fine-tuning it to perfection.

GraalVM gave us a great occasion to show how easy could it be to make Drools polyglot, and, above all, to play an awful practical joke on our beloved, hard-working, conference-speaking, JavaScript-hating, resident Java Champion and tech lead Mario!

Enter drools.js:

And here's a picture of Mario screaming in fear at the monster we have created



Jokes aside, this experiment is a window over one of the many possible futures of our platform. The world of application development today is polyglot. We cannot ignore this, and we are trying to understand how to reach a wider audience with our technologies, be it our rule engine, or our workflow orchestration engine; in fact, we are doing the same experiments with other parts of the platform, such as jBPM.

jBPM provides its own DSL for workflow definition. Although this is, again, work in progress, it shows a lot of promise as well. Behold: jbpm.js!

Conclusion

The DRL has served its purpose for a very long time, but we are already providing different ways to interact with our powerful engine, such as DMN and PMML; but power users will always want to reach for finer tuning and write their own rules.

The canonical model API is still a work-in-progress, and, above all, an internal API that is not intended for human consumption; but, if there is enough interest, we do plan to work further to provide a more convenient embedded DSL for rule definition. Through the power of GraalVM, we will be able to realize an embedded DSL that is just as writable in Java as any other language that GraalVM supports.

And this includes JavaScript; sorry Mario!


Share/Bookmark

1 comment: