A parser and interpreter for FEEL that is written in Scala (see What is FEEL?).
The FEEL engine started as a slack time project, grown to a community-driven project and is now officially maintained by Camunda 🚀
It is integrated in the following projects:
- Camunda BPM Platform as part of the DMN engine
- Zeebe as expression language
Features: ✨
- full support for unary-tests and expressions (DMN 1.2)
- including built-in functions
- extensible by own functions and custom object mappers
The documentation describes the supported FEEL expressions (e.g. data types, language constructs, builtin-functions, etc.), how to extend/customize the engine and contains some examples.
The FEEL engine can be used/integrated in two different ways
- as a native Scala application (i.e. calling the engine API)
- as a script engine (i.e. using the Java script engine API)
Add the engine as dependency to your project's pom.xml
:
<dependency>
<groupId>org.camunda.feel</groupId>
<artifactId>feel-engine</artifactId>
<version>${VERSION}</version>
</dependency>
Or, download the JAR file (feel-engine-${VERSION}-complete.jar) and copy it into your application.
Create a new instance of the class 'FeelEngine'. Use this instance to parse and evaluate a given expression or unary tests.
Using Scala:
object MyProgram {
val engine = new FeelEngine
def feel(expression: String, context: Map[String, Any]) {
val result: Either[Failure, Boolean] = engine.evalSimpleUnaryTests(expression, context)
// or
val result: Either[Failure, Any] = engine.evalExpression(expression, context)
// handle result
result
.right.map(value => println(s"result is: $value"))
.left.map(failure => println(s"failure: $failure"))
}
}
Or using Java:
public class MyProgram {
public static void main(String[] args) {
final FeelEngine engine = new FeelEngine.Builder()
.valueMapper(SpiServiceLoader.loadValueMapper())
.functionProvider(SpiServiceLoader.loadFunctionProvider())
.build();
final Map<String, Object> variables = Collections.singletonMap("x", 21);
final Either<FeelEngine.Failure, Object> result = engine.evalExpression(expression, variables);
if (result.isRight()) {
final Object value = result.right().get();
System.out.println("result is " + value);
} else {
final FeelEngine.Failure failure = result.left().get();
throw new RuntimeException(failure.message());
}
}
}
Enable FEEL External-Functions in the configuration:
new FeelEngine(configuration = Configuration(externalFunctionsEnabled = true))
// or
new FeelEngine.Builder().enableExternalFunctions(true).build()
Call the engine via Java's script engine API (JSR 223).
object MyProgram {
val scriptEngineManager = new ScriptEngineManager
def feel(script: String, context: ScriptContext) {
val scriptEngine: FeelScriptEngine = scriptEngineManager.getEngineByName("feel")
val result: Object = scriptEngine.eval(script, context)
// ...
}
}
The engine is registered under the names:
feel
http://www.omg.org/spec/FEEL/20140401
(qualified name)feel-scala
You can also evaluate unary tests instead of an expression by using one of the names:
feel-unary-tests
feel-scala-unary-tests
See the Contribution Guide.
The following resources can help to understand the general concepts behind the implementation: