[[expressions-evaluation]]
= Evaluation

This section introduces the simple use of SpEL interfaces and its expression language.
The complete language reference can be found in
xref:core/expressions/language-ref.adoc[Language Reference].

The following code introduces the SpEL API to evaluate the literal string expression,
`Hello World`.

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	ExpressionParser parser = new SpelExpressionParser();
	Expression exp = parser.parseExpression("'Hello World'"); // <1>
	String message = (String) exp.getValue();
----
<1> The value of the message variable is `'Hello World'`.

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	val parser = SpelExpressionParser()
	val exp = parser.parseExpression("'Hello World'") // <1>
	val message = exp.value as String
----
<1> The value of the message variable is `'Hello World'`.
======


The SpEL classes and interfaces you are most likely to use are located in the
`org.springframework.expression` package and its sub-packages, such as `spel.support`.

The `ExpressionParser` interface is responsible for parsing an expression string. In
the preceding example, the expression string is a string literal denoted by the surrounding single
quotation marks. The `Expression` interface is responsible for evaluating the previously defined
expression string. Two exceptions that can be thrown, `ParseException` and
`EvaluationException`, when calling `parser.parseExpression` and `exp.getValue`,
respectively.

SpEL supports a wide range of features, such as calling methods, accessing properties,
and calling constructors.

In the following example of method invocation, we call the `concat` method on the string literal:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	ExpressionParser parser = new SpelExpressionParser();
	Expression exp = parser.parseExpression("'Hello World'.concat('!')"); // <1>
	String message = (String) exp.getValue();
----
<1> The value of `message` is now 'Hello World!'.

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	val parser = SpelExpressionParser()
	val exp = parser.parseExpression("'Hello World'.concat('!')") // <1>
	val message = exp.value as String
----
<1> The value of `message` is now 'Hello World!'.
======

The following example of calling a JavaBean property calls the `String` property `Bytes`:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	ExpressionParser parser = new SpelExpressionParser();

	// invokes 'getBytes()'
	Expression exp = parser.parseExpression("'Hello World'.bytes"); // <1>
	byte[] bytes = (byte[]) exp.getValue();
----
<1> This line converts the literal to a byte array.

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	val parser = SpelExpressionParser()

	// invokes 'getBytes()'
	val exp = parser.parseExpression("'Hello World'.bytes") // <1>
	val bytes = exp.value as ByteArray
----
<1> This line converts the literal to a byte array.
======

SpEL also supports nested properties by using the standard dot notation (such as
`prop1.prop2.prop3`) and also the corresponding setting of property values.
Public fields may also be accessed.

The following example shows how to use dot notation to get the length of a literal:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	ExpressionParser parser = new SpelExpressionParser();

	// invokes 'getBytes().length'
	Expression exp = parser.parseExpression("'Hello World'.bytes.length"); // <1>
	int length = (Integer) exp.getValue();
----
<1> `'Hello World'.bytes.length` gives the length of the literal.

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	val parser = SpelExpressionParser()

	// invokes 'getBytes().length'
	val exp = parser.parseExpression("'Hello World'.bytes.length") // <1>
	val length = exp.value as Int
----
<1> `'Hello World'.bytes.length` gives the length of the literal.
======

The String's constructor can be called instead of using a string literal, as the following
example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	ExpressionParser parser = new SpelExpressionParser();
	Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); // <1>
	String message = exp.getValue(String.class);
----
<1> Construct a new `String` from the literal and make it be upper case.

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	val parser = SpelExpressionParser()
	val exp = parser.parseExpression("new String('hello world').toUpperCase()")  // <1>
	val message = exp.getValue(String::class.java)
----
<1> Construct a new `String` from the literal and make it be upper case.
======


Note the use of the generic method: `public <T> T getValue(Class<T> desiredResultType)`.
Using this method removes the need to cast the value of the expression to the desired
result type. An `EvaluationException` is thrown if the value cannot be cast to the
type `T` or converted by using the registered type converter.

The more common usage of SpEL is to provide an expression string that is evaluated
against a specific object instance (called the root object). The following example shows
how to retrieve the `name` property from an instance of the `Inventor` class or
create a boolean condition:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	// Create and set a calendar
	GregorianCalendar c = new GregorianCalendar();
	c.set(1856, 7, 9);

	// The constructor arguments are name, birthday, and nationality.
	Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");

	ExpressionParser parser = new SpelExpressionParser();

	Expression exp = parser.parseExpression("name"); // Parse name as an expression
	String name = (String) exp.getValue(tesla);
	// name == "Nikola Tesla"

	exp = parser.parseExpression("name == 'Nikola Tesla'");
	boolean result = exp.getValue(tesla, Boolean.class);
	// result == true
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	// Create and set a calendar
	val c = GregorianCalendar()
	c.set(1856, 7, 9)

	// The constructor arguments are name, birthday, and nationality.
	val tesla = Inventor("Nikola Tesla", c.time, "Serbian")

	val parser = SpelExpressionParser()

	var exp = parser.parseExpression("name") // Parse name as an expression
	val name = exp.getValue(tesla) as String
	// name == "Nikola Tesla"

	exp = parser.parseExpression("name == 'Nikola Tesla'")
	val result = exp.getValue(tesla, Boolean::class.java)
	// result == true
----
======




[[expressions-evaluation-context]]
== Understanding `EvaluationContext`

The `EvaluationContext` interface is used when evaluating an expression to resolve
properties, methods, or fields and to help perform type conversion. Spring provides two
implementations.

* `SimpleEvaluationContext`: Exposes a subset of essential SpEL language features and
configuration options, for categories of expressions that do not require the full extent
of the SpEL language syntax and should be meaningfully restricted. Examples include but
are not limited to data binding expressions and property-based filters.

* `StandardEvaluationContext`: Exposes the full set of SpEL language features and
configuration options. You can use it to specify a default root object and to configure
every available evaluation-related strategy.

`SimpleEvaluationContext` is designed to support only a subset of the SpEL language syntax.
It excludes Java type references, constructors, and bean references. It also requires
you to explicitly choose the level of support for properties and methods in expressions.
By default, the `create()` static factory method enables only read access to properties.
You can also obtain a builder to configure the exact level of support needed, targeting
one or some combination of the following:

* Custom `PropertyAccessor` only (no reflection)
* Data binding properties for read-only access
* Data binding properties for read and write


[[expressions-type-conversion]]
=== Type Conversion

By default, SpEL uses the conversion service available in Spring core
(`org.springframework.core.convert.ConversionService`). This conversion service comes
with many built-in converters for common conversions but is also fully extensible so that
you can add custom conversions between types. Additionally, it is
generics-aware. This means that, when you work with generic types in
expressions, SpEL attempts conversions to maintain type correctness for any objects
it encounters.

What does this mean in practice? Suppose assignment, using `setValue()`, is being used
to set a `List` property. The type of the property is actually `List<Boolean>`. SpEL
recognizes that the elements of the list need to be converted to `Boolean` before
being placed in it. The following example shows how to do so:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	class Simple {
		public List<Boolean> booleanList = new ArrayList<>();
	}

	Simple simple = new Simple();
	simple.booleanList.add(true);

	EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

	// "false" is passed in here as a String. SpEL and the conversion service
	// will recognize that it needs to be a Boolean and convert it accordingly.
	parser.parseExpression("booleanList[0]").setValue(context, simple, "false");

	// b is false
	Boolean b = simple.booleanList.get(0);
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	class Simple {
		var booleanList: MutableList<Boolean> = ArrayList()
	}

	val simple = Simple()
	simple.booleanList.add(true)

	val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()

	// "false" is passed in here as a String. SpEL and the conversion service
	// will recognize that it needs to be a Boolean and convert it accordingly.
	parser.parseExpression("booleanList[0]").setValue(context, simple, "false")

	// b is false
	val b = simple.booleanList[0]
----
======


[[expressions-parser-configuration]]
== Parser Configuration

It is possible to configure the SpEL expression parser by using a parser configuration
object (`org.springframework.expression.spel.SpelParserConfiguration`). The configuration
object controls the behavior of some of the expression components. For example, if you
index into an array or collection and the element at the specified index is `null`, SpEL
can automatically create the element. This is useful when using expressions made up of a
chain of property references. If you index into an array or list and specify an index
that is beyond the end of the current size of the array or list, SpEL can automatically
grow the array or list to accommodate that index. In order to add an element at the
specified index, SpEL will try to create the element using the element type's default
constructor before setting the specified value. If the element type does not have a
default constructor, `null` will be added to the array or list. If there is no built-in
or custom converter that knows how to set the value, `null` will remain in the array or
list at the specified index. The following example demonstrates how to automatically grow
the list:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	class Demo {
		public List<String> list;
	}

	// Turn on:
	// - auto null reference initialization
	// - auto collection growing
	SpelParserConfiguration config = new SpelParserConfiguration(true, true);

	ExpressionParser parser = new SpelExpressionParser(config);

	Expression expression = parser.parseExpression("list[3]");

	Demo demo = new Demo();

	Object o = expression.getValue(demo);

	// demo.list will now be a real collection of 4 entries
	// Each entry is a new empty String
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	class Demo {
		var list: List<String>? = null
	}

	// Turn on:
	// - auto null reference initialization
	// - auto collection growing
	val config = SpelParserConfiguration(true, true)

	val parser = SpelExpressionParser(config)

	val expression = parser.parseExpression("list[3]")

	val demo = Demo()

	val o = expression.getValue(demo)

	// demo.list will now be a real collection of 4 entries
	// Each entry is a new empty String
----
======



[[expressions-spel-compilation]]
== SpEL Compilation

Spring Framework 4.1 includes a basic expression compiler. Expressions are usually
interpreted, which provides a lot of dynamic flexibility during evaluation but
does not provide optimum performance. For occasional expression usage,
this is fine, but, when used by other components such as Spring Integration,
performance can be very important, and there is no real need for the dynamism.

The SpEL compiler is intended to address this need. During evaluation, the compiler
generates a Java class that embodies the expression behavior at runtime and uses that
class to achieve much faster expression evaluation. Due to the lack of typing around
expressions, the compiler uses information gathered during the interpreted evaluations
of an expression when performing compilation. For example, it does not know the type
of a property reference purely from the expression, but during the first interpreted
evaluation, it finds out what it is. Of course, basing compilation on such derived
information can cause trouble later if the types of the various expression elements
change over time. For this reason, compilation is best suited to expressions whose
type information is not going to change on repeated evaluations.

Consider the following basic expression:

----
someArray[0].someProperty.someOtherProperty < 0.1
----

Because the preceding expression involves array access, some property de-referencing,
and numeric operations, the performance gain can be very noticeable. In an example
micro benchmark run of 50000 iterations, it took 75ms to evaluate by using the
interpreter and only 3ms using the compiled version of the expression.


[[expressions-compiler-configuration]]
=== Compiler Configuration

The compiler is not turned on by default, but you can turn it on in either of two
different ways. You can turn it on by using the parser configuration process
(xref:core/expressions/evaluation.adoc#expressions-parser-configuration[discussed earlier]) or by using a Spring property
when SpEL usage is embedded inside another component. This section discusses both of
these options.

The compiler can operate in one of three modes, which are captured in the
`org.springframework.expression.spel.SpelCompilerMode` enum. The modes are as follows:

* `OFF` (default): The compiler is switched off.
* `IMMEDIATE`: In immediate mode, the expressions are compiled as soon as possible. This
is typically after the first interpreted evaluation. If the compiled expression fails
(typically due to a type changing, as described earlier), the caller of the expression
evaluation receives an exception.
* `MIXED`: In mixed mode, the expressions silently switch between interpreted and compiled
mode over time. After some number of interpreted runs, they switch to compiled
form and, if something goes wrong with the compiled form (such as a type changing, as
described earlier), the expression automatically switches back to interpreted form
again. Sometime later, it may generate another compiled form and switch to it. Basically,
the exception that the user gets in `IMMEDIATE` mode is instead handled internally.

`IMMEDIATE` mode exists because `MIXED` mode could cause issues for expressions that
have side effects. If a compiled expression blows up after partially succeeding, it
may have already done something that has affected the state of the system. If this
has happened, the caller may not want it to silently re-run in interpreted mode,
since part of the expression may be running twice.

After selecting a mode, use the `SpelParserConfiguration` to configure the parser. The
following example shows how to do so:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
	SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
			this.getClass().getClassLoader());

	SpelExpressionParser parser = new SpelExpressionParser(config);

	Expression expr = parser.parseExpression("payload");

	MyMessage message = new MyMessage();

	Object payload = expr.getValue(message);
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
	val config = SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
			this.javaClass.classLoader)

	val parser = SpelExpressionParser(config)

	val expr = parser.parseExpression("payload")

	val message = MyMessage()

	val payload = expr.getValue(message)
----
======

When you specify the compiler mode, you can also specify a classloader (passing null is allowed).
Compiled expressions are defined in a child classloader created under any that is supplied.
It is important to ensure that, if a classloader is specified, it can see all the types involved in
the expression evaluation process. If you do not specify a classloader, a default classloader is used
(typically the context classloader for the thread that is running during expression evaluation).

The second way to configure the compiler is for use when SpEL is embedded inside some
other component and it may not be possible to configure it through a configuration
object. In these cases, it is possible to set the `spring.expression.compiler.mode`
property via a JVM system property (or via the
xref:appendix.adoc#appendix-spring-properties[`SpringProperties`] mechanism) to one of the
`SpelCompilerMode` enum values (`off`, `immediate`, or `mixed`).


[[expressions-compiler-limitations]]
=== Compiler Limitations

Since Spring Framework 4.1, the basic compilation framework is in place. However, the framework
does not yet support compiling every kind of expression. The initial focus has been on the
common expressions that are likely to be used in performance-critical contexts. The following
kinds of expression cannot be compiled at the moment:

* Expressions involving assignment
* Expressions relying on the conversion service
* Expressions using custom resolvers or accessors
* Expressions using selection or projection

More types of expressions will be compilable in the future.




