17. Message Publishing

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.

17.1 Message Publishing Configuration

Spring Integration provides two approaches - XML and Annotation.

17.1.1 Annotation-based approach via @Publisher annotation

Annotation bassed approach allows you to annotate any method with @Publisher annotation and provide configuration attributes which will dictate the structure of a Message. Invocation of such method will be proxied through PublisherAnnotationAdvisor which will construct a Message and send it to a channel.

Internally PublisherAnnotationAdvisor uses Spring 3.0 Expression Language support giving you the flexibility and control over the structure of a Message it will build.

PublisherAnnotationAdvisor defines and binds the following variables:

  • #return - will bind to a return value allowing you to reference it or its attributes (e.g., #return.foo where 'foo' is an attribute of the object bound to #return)

  • #exception - will bind to an exception if one is thrown.

  • #[parameName] - will be dynamically constructed pointing to the method parameter names (e.g., #fname as in the above method)

@Publisher(value="#return", channel="testChannel", headers="bar='123',fname=#fname")
public String setName(String fname, String lname){
	return fname + " " + lname;
}

In the above example the Message will be constructed and its structure will be as follows:

  • Message payload - will be of type String and contain the value returned by the method.

  • Message headers will be 'bar' with value of "123" and 'fname' with value of 'fname' parameter of the method.

As with any other annotation you will need to register PublisherAnnotationBeanPostProcessor

<bean class="org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor"/>

17.1.2 XML-based approach via <publisher> element

XML-based approach allows you to configure Message Publishing via AOP-based configuration and simple namespace-based configuration of MessagePublishingInterceptor. 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.

To configure Message Publishing via XML all you need is the following two things:

  • Provide configuration for MessagePublishingInterceptor via <publisher> XML element

  • Provide AOP configuration to apply MessagePublishingInterceptor

<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>
	

As you can see <publisher> uses the same variables as PublisherAnnotationAdvisor to utilize the power of Spring 3.0 Expression Langage.

In the above example the execution of echo method of a testBean will rander the Message with the following structure:

  • Message payload - will be of type String and value of "Echoing: [value]" where value is the value returned by an executed method.

  • Message headers will be 'foo' with value of "bar".

  • Message will be sent to echoChannel.

In the second method mapping the execution of any method that begins with echoDef of testBean will result in the Message with the following structure.

  • Message payload - will be the value returned by an executed method.

  • Since channel attriute is not provided, the Message will be sent to the defaultChannel defined by the publisher.

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.

For a simple maping rules you can rely on publisher defaults. For example:

<publisher id="anotherInterceptor"/>
	

This will map the return value of every method that matches the pointcut expression to a payload and will be sent to a default-channel. If the defaultChannelis not specified (as above) the messages will be sent to nullChannel