151 lines
7.6 KiB
XML
151 lines
7.6 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
<chapter id="message-publishing">
|
|
<title>Message Publishing</title>
|
|
<para>
|
|
Message Publishing feature will allow you to send a message as a result of method invocation. For example; Imagine you
|
|
have a component and every time the state of this components changes you would like to get notified. The easiest
|
|
way to send notification would be to send a message to a dedicated channel, but how would you connect the method invocation that
|
|
changes the state of the object to a message sending process and what should be the structure of the
|
|
message? Message Publishing feature will allow you to do just that.
|
|
</para>
|
|
<section id="message-publishing-config">
|
|
<title>Message Publishing Configuration</title>
|
|
<para>
|
|
Spring Integration provides two approaches - XML and Annotation.
|
|
</para>
|
|
<section id="publisher-annotation">
|
|
<title>Annotation-based approach via @Publisher annotation</title>
|
|
<para>
|
|
Annotation bassed approach allows you to annotate any method with <interfacename>@Publisher</interfacename> annotation and
|
|
provide configuration attributes which will dictate the structure of a <emphasis>Message</emphasis>. Invocation of such
|
|
method will be proxied through <classname>PublisherAnnotationAdvisor</classname> which will
|
|
construct a <emphasis>Message</emphasis> and send it to a <emphasis>channel</emphasis>.
|
|
</para>
|
|
<para>
|
|
Internally <classname>PublisherAnnotationAdvisor</classname> uses Spring 3.0 Expression Language support giving you
|
|
the flexibility and control over the structure of a <emphasis>Message</emphasis> it will build.
|
|
</para>
|
|
<para>
|
|
<classname>PublisherAnnotationAdvisor</classname> defines and binds the following variables:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><emphasis>#return</emphasis> - will bind to a return value allowing you to reference it or its
|
|
attributes (e.g., <emphasis>#return.foo</emphasis> where 'foo' is an attribute of the object bound to
|
|
<emphasis>#return</emphasis>)</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>#exception</emphasis> - will bind to an exception if one is thrown.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para><emphasis>#[parameName]</emphasis> - will be dynamically constructed pointing to the method parameter
|
|
names (e.g., <emphasis>#fname</emphasis> as in the above method)</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
<programlisting language="java">@Publisher(value="#return", channel="testChannel", headers="bar='123',fname=#fname")
|
|
public String setName(String fname, String lname){
|
|
return fname + " " + lname;
|
|
}</programlisting>
|
|
</para>
|
|
<para>
|
|
In the above example the Message will be constructed and its structure will be as follows:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Message payload - will be of type String and contain the value returned by the method.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Message headers will be 'bar' with value of "123" and 'fname' with value of 'fname' parameter of the method.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
As with any other annotation you will need to register <classname>PublisherAnnotationBeanPostProcessor</classname>
|
|
<programlisting language="xml"><bean class="org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor"/></programlisting>
|
|
</para>
|
|
</section>
|
|
<section id="aop-based-interceptor">
|
|
<title>XML-based approach via <publisher> element</title>
|
|
<para>
|
|
XML-based approach allows you to configure Message Publishing via AOP-based configuration and
|
|
simple namespace-based configuration of <classname>MessagePublishingInterceptor</classname>.
|
|
It certainly has certain benefits over annotation based approach since it
|
|
allows you to use AOP pointcut expressions, thus possibly intercepting multiple methods at once or
|
|
intercepting and publishing methods to which you don't have a source code.
|
|
</para>
|
|
<para>
|
|
To configure Message Publishing via XML all you need is the following two things:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Provide configuration for <classname>MessagePublishingInterceptor</classname>
|
|
via <code><publisher></code> XML element</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Provide AOP configuration to apply <classname>MessagePublishingInterceptor</classname></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
<programlisting language="xml">
|
|
<beans:bean id="testBean" class="org.foo.bar.TestBean" />
|
|
<aop:config>
|
|
<aop:advisor advice-ref="interceptor" pointcut="bean(testBean)" />
|
|
</aop:config>
|
|
|
|
<publisher id="interceptor" default-channel="defaultChannel">
|
|
<method pattern="echo" payload="'Echoing: ' + #return" headers="foo='bar'" channel="echoChannel"/>
|
|
<method pattern="echoDef*" payload="#return"/>
|
|
<method pattern="foo*"/>
|
|
</publisher>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
As you can see <code><publisher></code> uses the same variables as
|
|
<classname>PublisherAnnotationAdvisor</classname> to utilize the power of Spring 3.0 Expression Langage.
|
|
</para>
|
|
<para>
|
|
In the above example the execution of <code>echo</code> method of a <code>testBean</code> will
|
|
rander the <emphasis>Message</emphasis> with the following structure:
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Message payload - will be of type String and value of "Echoing: [value]" where <code>value</code> is the value
|
|
returned by an executed method.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Message headers will be 'foo' with value of "bar".</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Message will be sent to <code>echoChannel</code>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
In the second method mapping the execution of any method that begins with <code>echoDef</code> of <code>testBean</code> will result in the
|
|
Message with the following structure.
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>Message payload - will be the value
|
|
returned by an executed method.</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>Since <code>channel</code> attriute is not provided, the Message will be sent to the
|
|
<code>defaultChannel</code> defined by the <emphasis>publisher</emphasis>.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
The third mapping is almost identical to the previous (with the exceptipon of method pattern),
|
|
since the return value will be mapped to the Message paylad by default if nothing else is specifued.
|
|
</para>
|
|
<para>
|
|
For a simple maping rules you can rely on <emphasis>publisher</emphasis> defaults. For example:
|
|
<programlisting language="xml">
|
|
<publisher id="anotherInterceptor"/>
|
|
</programlisting>
|
|
This will map the return value of every method that matches the pointcut expression to a payload and will be sent to a <emphasis>default-channel</emphasis>.
|
|
If the <emphasis>defaultChannel</emphasis>is not specified (as above) the messages will be sent to <emphasis>nullChannel</emphasis>
|
|
</para>
|
|
</section>
|
|
</section>
|
|
</chapter> |