Concept: MVEL Fundamentals
Syntax
MVEL is an expression language for Java-based applications. Its syntax is similar to Java's
but it has some additions that make it more efficient at matching content.
Note:
- MVEL uses Java namespaces and classes, but can't itself declare either.
- Unlike Java, MVEL is dynamically typed, with optional typing.
- MVEL expressions can be single statements or multiline scripts. For multiline scripts, use a semicolon to separate each statement.
- MVEL operates on the principle of last value out. It supports thereturnkeyword but doesn't generally require it.
- MVEL supports operator precedence rules and uses bracketing to control execution order.
- You can enclose MVEL string literals in single or double quotation marks.
- The semicolon is a reserved character in MVEL. You can't use it in expressions. Use(char) 59instead. Example:props['string']='a;b'throws an error. This code does not:props['string']= (char) 59 props['string_new']='a'props['string']'b'
MVEL expressions can include:
- Boolean expressions
- Method invocations
- Property expressions
- Variable assignments
An example of a simple MVEL property expression:
context.errorMessage
It extracts the property
errorMessage
from the variable or context object
context
.MVEL supports all of the usual Java comparison, mathematical, and logical operators. This
table summarizes other notable MVEL operators:
Operator | Description | Example |
|---|---|---|
new
| Instantiates an object. | new String("foo")
|
with
| Performs multiple operations on a single object
instance. | with (value) { name = 'Foo', age = 50, sex = Sex.MALE }
|
assert
| Asserts that a value is true or fails with an
AssertionError. | assert foo != null
|
contains
| Determines whether the value on the left contains the value on the
right. | var contains "Foo"
|
is or instance of
| Determines whether the value on the left is a member of the class
on the right. | var instanceof String
|
strsim
| Compares strings and returns their similarity expressed as a
percentage. | "foobol" strsim "foobar"
|
soundslike
| Performs a soundex comparison between 2 strings. | "foobar" soundslike "fubar"
|
&
| Performs a Bitwise AND operation. | foo & 5
|
|
| Performs a Bitwise OR operation. | foo | 5
|
^
| Performs a Bitwise XOR operation. | foo ^ 5
|
+
| Overloaded operator for concatenating 2 strings. | "foo" + "bar"
|
#
| Concatenates 2 literals as strings. | 8 # 9
|
in
| Inspects objects inside a collection. | (foo in list)
|
=
| Assigns a value to a variable. | var = "foobar"
|
Value Testing
In Java, the operator
==
checks whether references point to the same
object. In MVEL, however, the comparison operator ==
checks whether
values are equal. The MVEL expression foo == 'bar'
is the
equivalent of Java's foo.equals("bar")
.An example of an MVEL boolean expression:
user.name == 'John Smith'
It returns
true
if the name
property of the variable or
context object user
is John Smith.MVEL employs type coercion. If you compare 2 values of different types, MVEL tries to coerce
the value on the right to the type on the left. If that isn't possible, it tries to
coerce the value on the left to the type on the right. Example:
"123" == 123;
This expression returns
true
because MVEL coerces the value on the right to a
string before it performs the comparison.Lists, Maps, and Arrays
Enclose MVEL lists in square brackets. Separate items with commas. Example:
["Paris", "London", "Berlin"]
Enclose MVEL maps in square brackets. Separate keys and values with colons. Example:
["Foo" : "Bar", "Bar" : "Foo"]
Enclose MVEL arrays in braces. Separate items with commas. Example:
{"Bill", "Bob", "Ben"}
Property Navigation
MVEL provides a single, unified syntax for accessing properties, static fields,
lists, maps, and arrays.
In Java, you might access a property from an object using this statement:
context.getException().getCause()
In MVEL you can access the same property using this expression:
context.exception.cause
Access lists and arrays in the same manner. Example:
parts[2]
You access maps in the same way as arrays but can pass any object as the index value.
Example:
props["foobar"]
If a map uses a string as a key, you can treat the map itself as a virtual object.
Example:
props.foobar
MVEL treats strings as arrays for indexing purposes.
This example returns
B
:foo = "Berlin"; foo[0];
Assignment
You can assign variables in an MVEL expression for use within the expression or for extraction
at runtime.
Because MVEL is a dynamically typed language, you don't need to specify a type when you
declare a new variable. But you can do so.
Both of these examples are valid in MVEL:
str = "Some string"; String str = "Some string";
When assigning a value to a typed variable, MVEL attempts to perform automatic type
conversion. Example:
String num = 1;
You can cast the value of a dynamically typed variable to another type. Example:
String num = 1;
Section: Typing and Coercion
MVEL uses dynamic typing, with optional static typing. Native Java objects are
statically typed. To interact with them, MVEL must sometimes perform type coercion,
which can have implications for performance.
MVEL automatically coerces type to what seems best for the current value. This means
you must be careful when working with numbers. Errors can arise in floating point
arithmetic because MVEL automatically casts away from infinite precision
java.math.BigDecimal
to java.lang.Double
and
java.lang.Long
. This can cause problems when the type of the
stored value is not what you expect. In general, you should avoid performing
noninteger arithmetic with financial values in MVEL.MVEL's type coercion means you can call Java methods without adjusting inputs. The
interpreter or compiler analyzes the types you're passing to the method and
determines what coercion is required.
In the event of an array type conflict, MVEL attempts to coerce the entire array to
the needed input type.
MVEL performs any necessary coercion on a statically typed variable, provided the
assigned value is coercible. If it isn't, an exception occurs.