INT-1639: Add <spel-function> support

* add `<spel-function>` XSD element
* add `SpelFunctionParser`
* add `SpelFunctionRegistrar` to avoid introducing some confused 'Method'-bean
* add `SpelFunctionRegistrar` collaboration with `IntegrationEvaluationContextFactoryBean`
* some refactoring for `IntegrationEvaluationContextFactoryBean`
* polishing some failed tests after this change

JIRA: https://jira.springsource.org/browse/INT-1639

INT-1639: SpelFunctionParser use BeanClassLoader

INT-1639: Inherit 'functions' from parent AC

INT-1639: Document the <spel-function>

INT-1639: 'NoSuchBeanDefinitionException' fix

Polishing
This commit is contained in:
Artem Bilan
2013-05-27 12:49:35 +03:00
committed by Gary Russell
parent 1705a70def
commit 93f61160e2
13 changed files with 420 additions and 46 deletions

View File

@@ -30,6 +30,9 @@
properties (using getters and setters). This is how the <interfacename>Message</interfacename> headers
and payload properties are accessible.
</para>
</section>
<section id="spel-customization">
<title>SpEL Evaluation Context Customization</title>
<para>
Starting with Spring Integration 3.0, it is possible to add additional
<interfacename>PropertyAccessor</interfacename>s to the SpEL evaluation context.
@@ -58,8 +61,7 @@
</property>
<property name="functions">
<map>
<entry key="barcalc"
value="#{T(foo.MyFunctions).getMethod('calc', T(foo.MyBar))}"/>
<entry key="barcalc" value="#{T(foo.MyFunctions).getMethod('calc', T(foo.MyBar))}"/>
</map>
</property>
</bean>]]></programlisting>
@@ -85,4 +87,63 @@
<code>"#barcalc(payload.myBar)"</code>.
</para>
</section>
<section id="spel-functions">
<title>SpEL Functions</title>
<para>
Namespace support is provided for easy addition of SpEL custom functions.
You can specify <code>&lt;spel-function/&gt;</code> components to provide
<ulink url="http://static.springsource.org/spring-framework/docs/current/spring-framework-reference/html/expressions.html#expressions-ref-functions">
custom SpEL functions</ulink> to the <interfacename>EvaluationContext</interfacename> used throughout the framework.
Instead of configuring the factory bean above, simply add one or more of these components
and the framework will automatically add them to the default <emphasis>integrationEvaluationContext</emphasis>
factory bean.
</para>
<para>For example, assuming we have a useful static method to evaluate XPath:</para>
<programlisting language="xml"><![CDATA[<int:spel-function id="xpath"
class="com.foo.test.XPathUtils" method="evaluate(java.lang.String, java.lang.Object)"/>
<int:transformer input-channel="in" output-channel="out"
expression="#xpath('//foo/@bar', payload)" />
]]></programlisting>
<para>
With this sample:
<itemizedlist>
<listitem>
The default <classname>IntegrationEvaluationContextFactoryBean</classname> bean with id
<emphasis>integrationEvaluationContext</emphasis> is registered with the application
context.
</listitem>
<listitem>
The <code>&lt;spel-function/&gt;</code> is parsed and added to the <code>functions</code>
Map of <emphasis>integrationEvaluationContext</emphasis> as map entry with <code>id</code> as the key
and the static <classname>Method</classname> as the value.
</listitem>
<listitem>
The <emphasis>integrationEvaluationContext</emphasis> factory bean creates a new
<classname>StandardEvaluationContext</classname> instance,
and it is configured with the default
<interfacename>PropertyAccessor</interfacename>s, <interfacename>BeanResolver</interfacename>
and the custom function.
</listitem>
<listitem>
That <interfacename>EvaluationContext</interfacename> instance is injected into the
<classname>ExpressionEvaluatingTransformer</classname> bean.
</listitem>
</itemizedlist>
</para>
<para>
<note>
SpEL functions declared in a parent context are also made available in any child context(s). Each
context has its own instance of the <emphasis>integrationEvaluationContext</emphasis> factory bean
because each needs a different <interfacename>BeanResolver</interfacename>, but the function
declarations are inherited (and can be overridden if needed by declaring a SpEL function with
the same name. The functions themselves are processed by the framework - they do not appear
as beans in the application context.
</note>
<note>
At this time, <interfacename>PropertyAccessor</interfacename>s are not inherited and must be
declared as described above in each context.
</note>
</para>
</section>
</appendix>

View File

@@ -64,9 +64,9 @@
<title>JMX Support</title>
<para>
A new <code>&lt;int-jmx:tree-polling-channel-adapter/&gt;</code> is provided; this
adapter queries the JMX MBean tree and sends a message with a payload that is the
graph of objects that matches the query. By default the MBeans are mapped to
primitives and simple Objects like Map, List and arrays - permitting simple
adapter queries the JMX MBean tree and sends a message with a payload that is the
graph of objects that matches the query. By default the MBeans are mapped to
primitives and simple Objects like Map, List and arrays - permitting simple
transformation, for example, to JSON
<xref linkend="jmx"/>.
</para>
@@ -82,11 +82,19 @@
<section id="3.0-spel-customization">
<title>Spring Expression Language (SpEL) Configuration</title>
<para>
A new factory bean is provided to allow
A new <classname>IntegrationEvaluationContextFactoryBean</classname> is provided to allow
configuration of custom <interfacename>PropertyAccessor</interfacename>s and functions for
use in SpEL expressions throughout the framework. For more information see <xref linkend="spel" />.
</para>
</section>
<section id="3.0-spel-functions">
<title>SpEL Functions Support</title>
<para>
To customize the SpEL <interfacename>EvaluationContext</interfacename> with static
<classname>Method</classname> functions the new <code>&lt;spel-function/&gt;</code>
component is introduced. For more information see <xref linkend="spel-functions" />.
</para>
</section>
</section>
<section id="3.0-general">
@@ -303,7 +311,7 @@
<para>
All Outbound Gateways (e.g. <code>&lt;jdbc:outbound-gateway/&gt;</code> or <code>&lt;jms:outbound-gateway/&gt;</code>)
are designed for 'request-reply' scenarios. A response is expected from the external service and
will be published to the <code>reply-channel</code>, or the <code>replyChannel</code> message header.
will be published to the <code>reply-channel</code>, or the <code>replyChannel</code> message header.
However, there are some cases where the external system might not always return a
result, e.g. a <code>&lt;jdbc:outbound-gateway/&gt;</code>, when a SELECT ends with an empty <interfacename>ResultSet</interfacename>
or, say, a Web Service is One-Way. An option is therefore needed to configure whether or not a