[[spel]]
= Spring Expression Language (SpEL)

You can configure many Spring Integration components by using expressions written in the https://docs.spring.io/spring-framework/reference/core/expressions.html[Spring Expression Language].

In most cases, the `#root` object is the `Message`, which has two properties (`headers` and `payload`) that allow such expressions as `payload`, `payload.thing`, `headers['my.header']`, and so on.

In some cases, additional variables are provided.
For example, `<int-http:inbound-gateway/>` provides `#requestParams` (parameters from the HTTP request) and `#pathVariables` (values from path placeholders in the URI).

For all SpEL expressions, a `BeanResolver` is available to enable references to any bean in the application context (for example, `@myBean.foo(payload)`).
In addition, two `PropertyAccessors` are available.
A `MapAccessor` enables accessing values in a `Map` by using a key and a `ReflectivePropertyAccessor`, which allows access to fields and JavaBean compliant properties (by using getters and setters).
This is how you can access the `Message` headers and payload properties.

[[spel-customization]]
== SpEL Evaluation Context Customization

Starting with Spring Integration 3.0, you can add additional `PropertyAccessor` instances to the SpEL evaluation contexts used by the framework.
The framework provides the (read-only) `JsonPropertyAccessor`, which you can use to access fields from a `JsonNode` or JSON in a `String`.
You can also create your own `PropertyAccessor` if you have specific needs.

In addition, you can add custom functions.
Custom functions are `static` methods declared on a class.
Functions and property accessors are available in any SpEL expression used throughout the framework.

The following configuration shows how to directly configure the `IntegrationEvaluationContextFactoryBean` with custom property accessors and functions:

[source,xml]
----
<bean id="integrationEvaluationContext"
			class="org.springframework.integration.config.IntegrationEvaluationContextFactoryBean">
	<property name="propertyAccessors">
		<util:map>
			<entry key="things">
				<bean class="things.MyCustomPropertyAccessor"/>
			</entry>
		</util:map>
	</property>
	<property name="functions">
		<map>
			<entry key="barcalc" value="#{T(things.MyFunctions).getMethod('calc', T(things.MyThing))}"/>
		</map>
	</property>
</bean>
----

For convenience, Spring Integration provides namespace support for both property accessors and functions, as described in the following sections.
The framework automatically configures the factory bean on your behalf.

This factory bean definition overrides the default `integrationEvaluationContext` bean definition.
It adds the custom accessor and one custom function to the list (which also includes the standard accessors xref:spel.adoc[mentioned earlier]).

Note that custom functions are static methods.
In the preceding example, the custom function is a static method called `calc` on a class called `MyFunctions` and takes a single parameter of type `MyThing`.

Suppose you have a `Message` with a payload that has a type of `MyThing`.
Further, suppose that you need to perform some action to create an object called `MyObject` from `MyThing` and then invoke a custom function called `calc` on that object.

The standard property accessors do not know how to get a `MyObject` from a `MyThing`, so you could write and configure a custom property accessor to do so.
As a result, your final expression might be `"#barcalc(payload.myObject)"`.

The factory bean has another property (`typeLocator`), which lets you customize the `TypeLocator` used during SpEL evaluation.
You might need to do so running in some environments that use a non-standard `ClassLoader`.
In the following example, SpEL expressions always use the bean factory's class loader:

[source,xml]
----
<bean id="integrationEvaluationContext"
		class="org.springframework.integration.config.IntegrationEvaluationContextFactoryBean">
	<property name="typeLocator">
		<bean class="org.springframework.expression.spel.support.StandardTypeLocator">
			<constructor-arg value="#{beanFactory.beanClassLoader}"/>
		</bean>
	</property>
</bean>
----

[[spel-functions]]
== SpEL Functions

Spring Integration provides namespace support to let you create SpEL custom functions.
You can specify `<spel-function/>` components to provide https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/functions.html[custom SpEL functions] to the `EvaluationContext` used throughout the framework.
Instead of configuring the factory bean shown earlier, you can add one or more of these components, and the framework automatically adds them to the default `integrationEvaluationContext` factory bean.

For example, suppose you have a useful static method to evaluate XPath.
The following example shows how you can create a custom function to use that method:

[source,xml]
----
<int:spel-function id="xpath"
	class="com.something.test.XPathUtils" method="evaluate(java.lang.String, java.lang.Object)"/>

<int:transformer input-channel="in" output-channel="out"
		 expression="#xpath('//things/@mythings', payload)" />
----

Given the preceding example:

* The default `IntegrationEvaluationContextFactoryBean` bean with an ID of `integrationEvaluationContext` is registered with the application context.

* The `<spel-function/>` is parsed and added to the `functions` `Map` of `integrationEvaluationContext` as a map entry with its `id` as the key and the static `Method` as the value.

* The `integrationEvaluationContext` factory bean creates a new `StandardEvaluationContext` instance, and it is configured with the default `PropertyAccessor` instances, a `BeanResolver`, and the custom functions.

* That `EvaluationContext` instance is injected into the `ExpressionEvaluatingTransformer` bean.

To provide a SpEL Function by using Java configuration, you can declare a `SpelFunctionFactoryBean` bean for each function.
The following example shows how to create a custom function:

[source,java]
----
@Bean
public SpelFunctionFactoryBean xpath() {
    return new SpelFunctionFactoryBean(XPathUtils.class, "evaluate");
}
----

NOTE: SpEL functions declared in a parent context are also made available in any child contexts.
Each context has its own instance of the `integrationEvaluationContext` factory bean, because each needs a different `BeanResolver`, but the function declarations are inherited and can be overridden by declaring a SpEL function with the same name.

[[built-in-spel-functions]]
=== Built-in SpEL Functions

Spring Integration provides the folloiwng  standard functions, which are registered with the application context automatically on start up:

* `#jsonPath`: Evaluates a 'jsonPath' on a specified object.
This function invokes `JsonPathUtils.evaluate(...)`, which delegates to the https://github.com/json-path/JsonPath[Jayway JsonPath library].
The following listing shows some usage examples:
+
[source,xml]
----
<transformer expression="#jsonPath(payload, '$.store.book[0].author')"/>

<filter expression="#jsonPath(payload,'$..book[2].isbn') matches '\d-\d{3}-\d{5}-\d'"/>

<splitter expression="#jsonPath(payload, '$.store.book')"/>

<router expression="#jsonPath(payload, headers.jsonPath)">
	<mapping channel="output1" value="reference"/>
	<mapping channel="output2" value="fiction"/>
</router>
----
+
`#jsonPath` also supports a third (optional) parameter: an array of https://github.com/json-path/JsonPath#filter-predicates[`com.jayway.jsonpath.Filter`], which can be provided by a reference to a bean or bean method (for example).
+
NOTE: Using this function requires the Jayway JsonPath library (`json-path.jar`) to be on the classpath.
Otherwise, the `#jsonPath` SpEL function is not registered.
+
For more information regarding JSON see 'JSON Transformers' in xref:transformer.adoc[Transformer].

* `#xpath`: To evaluate an xpath on some provided object.
For more information regarding XML and XPath, see xref:xml.adoc[XML Support - Dealing with XML Payloads].

[[spel-property-accessors]]
== Property Accessors

Spring Integration provides namespace support to let you create SpEL custom https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/expression/PropertyAccessor.html[`PropertyAccessor`] implementations.
You can use the `<spel-property-accessors/>` component to provide a list of custom `PropertyAccessor` instances to the `EvaluationContext` used throughout the framework.
Instead of configuring the factory bean shown earlier, you can add one or more of these components, and the framework automatically adds the accessors to the default `integrationEvaluationContext` factory bean.
The following example shows how to do so:

[source,xml]
----
<int:spel-property-accessors>
	<bean id="jsonPA" class="org.springframework.integration.json.JsonPropertyAccessor"/>
	<ref bean="fooPropertyAccessor"/>
</int:spel-property-accessors>
----

In the preceding example, two custom `PropertyAccessor` instances are injected into the `EvaluationContext` (in the order in which they are declared).

To provide `PropertyAccessor` instances by using Java Configuration, you should declare a `SpelPropertyAccessorRegistrar` bean with a name of `spelPropertyAccessorRegistrar` (dictated by the `IntegrationContextUtils.SPEL_PROPERTY_ACCESSOR_REGISTRAR_BEAN_NAME` constant).
The following example shows how to configure two custom `PropertyAccessor` instances with Java:

[source,java]
----
@Bean
public SpelPropertyAccessorRegistrar spelPropertyAccessorRegistrar() {
    return new SpelPropertyAccessorRegistrar(new JsonPropertyAccessor())
                    .add(fooPropertyAccessor());
}
----

[NOTE]
====
Custom `PropertyAccessor` instances declared in a parent context are also made available in any child contexts.
They are placed at the end of result list (but before the default `org.springframework.context.expression.MapAccessor` and `o.s.expression.spel.support.ReflectivePropertyAccessor`).
If you declare a `PropertyAccessor` with the same bean ID in a child context, it overrides the parent accessor.
Beans declared within a `<spel-property-accessors/>` must have an 'id' attribute.
The final order of usage is as follows:

* The accessors in the current context, in the order in which they are declared
* Any accessors from parent contexts, in order
* The `MapAccessor`
* The `ReflectivePropertyAccessor`
====
