camunda / Feel Scala
Programming Languages
Projects that are alternatives of or similar to Feel Scala
FEEL Scala
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 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
Usage
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.
Install
The FEEL engine can be integrated in two different ways
- as a native Scala/Java 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.
For trying out FEEL expression quickly in development, have a look at the FEEL REPL.
As Native Scala 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()
⚠️ Enabling external functions is not recommended because external functions make it possible to call arbitrary Java methods. This poses a potential security risk. Enabling this feature can be safe if you have full control of the expressions that will be evaluated (i.e. none of them are entered by a user or generated by an external system). In all other cases this feature is considered unsafe. It is recommended to use the Function Provider SPI instead.
As Script Engine
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
FEEL REPL
The easiest way to try out your FEEL expressions in development is to use the REPL (Read-Eval-Print-Loop) of the FEEL engine. It is a simple script based on Ammonite that downloads the dependency to the FEEL engine and initialize it for you.
- Download Ammonite: http://ammonite.io/#Ammonite-REPL
- Download the script: feel-repl.sc
- Run the script:
amm --predef feel-repl.sc
Contribution
See the Contribution Guide.
The following resources can help to understand the general concepts behind the implementation:
- Build your own Programming Language with Scala
- Easy Parsing with Parser Combinators
- FastParse - Documentation of the Parser Library