diff --git a/docs/src/reference/docbook/message-publishing.xml b/docs/src/reference/docbook/message-publishing.xml
index f599808dfc..4e5dbd59ee 100644
--- a/docs/src/reference/docbook/message-publishing.xml
+++ b/docs/src/reference/docbook/message-publishing.xml
@@ -3,7 +3,7 @@
xmlns:xlink="http://www.w3.org/1999/xlink">
Message Publishing
- The AOP Message Publishing feature allows you to construct and send a message as a by-product of method invocation. For example, imagine you
+ The AOP Message Publishing feature allows you to construct and send a message as a by-product of a method invocation. For example, imagine you
have a component and every time the state of this component changes you would like to be notified via a Message. The easiest
way to send such notifications 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 how should the notification Message be structured?
@@ -17,16 +17,21 @@
Annotation-driven approach via @Publisher annotation
- The annotation-driven approach allows you to annotate any method with the @Publisher annotation, specifying 'channel' attribute.
- The Message will be constructed from the return value of method invocation and sent to a channel specified by 'channel' attribute.
- To further manage message structure you can also use a combination of both @Payload and @Header annotations.
+ The annotation-driven approach allows you to annotate any method with the @Publisher annotation,
+ specifying a 'channel' attribute.
+ The Message will be constructed from the return value of the method invocation and sent to a channel specified by the 'channel' attribute.
+ To further manage message structure, you can also use a combination of both @Payload
+ and @Header annotations.
- Internally message publishing feature of Spring Integration uses both Spring AOP by defining PublisherAnnotationAdvisor and
- Spring 3.0 Expression Language (SpEL) support, giving you considerable flexibility and control over the structure of the Message it will build.
+ Internally this message publishing feature of Spring Integration uses both Spring AOP by defining
+ PublisherAnnotationAdvisor and
+ Spring 3.0's Expression Language (SpEL) support, giving you considerable flexibility and control over the structure of the
+ Message it will publish.
-
- PublisherAnnotationAdvisor defines and binds the following variables:
+
+
+ The PublisherAnnotationAdvisor defines and binds the following variables:
#return - will bind to a return value allowing you to reference it or its
@@ -44,7 +49,7 @@
- Let's look at couple of examples:
+ Let's look at a couple of examples:
@Publisher
@@ -59,7 +64,7 @@ public String defaultPayload(String fname, String lname) {
Message payload - will be the return type and value of the method. This is the default.
- A newly constructed message will be sent to a default publisher channel configured with annotation post processor (see the end of this section).
+ A newly constructed message will be sent to a default publisher channel configured with an annotation post processor (see the end of this section).
@@ -70,10 +75,10 @@ public String defaultPayload(String fname, @Header("last") String lname) {
}
- In this example everything is the same as above, however we are not using default publishing channel. Instead we are specifying
- the publishing channel via 'channel' attribute of @Publisher annotation.
- We are also adding @Header annotation which results in the Message header with the name 'last' and the value of 'lname' input parameter
- to be added to the newly constructed Message.
+ In this example everything is the same as above, except that we are not using a default publishing channel. Instead we are specifying
+ the publishing channel via the 'channel' attribute of the @Publisher annotation.
+ We are also adding a @Header annotation which results in the Message header named 'last' having the same value
+ as the 'lname' method parameter. That header will be added to the newly constructed Message.
@@ -84,8 +89,8 @@ public String defaultPayloadButExplicitAnnotation(String fname, @Header String l
}
- The above example is almost identical to the previous one. The only difference here is that we are using @Payload annotation
- on the method, thus explicitly specifying that the return value of the method should be used as a payload of the Message.
+ The above example is almost identical to the previous one. The only difference here is that we are using a @Payload annotation
+ on the method, thus explicitly specifying that the return value of the method should be used as the payload of the Message.
@@ -96,9 +101,11 @@ public String setName(String fname, String lname, @Header("x") int num) {
}
- Here we are expending on the previous configuration by using Spring Expression language in the @Payload annotation further instructing
- the framework on how the message should be constructed. In this particular case the message will be a concatenation of the return value of the method invocation and
- 'lname' input argument. Message header 'x' with value of 'num' input argument will be added to the newly constructed Message.
+ Here we are expanding on the previous configuration by using the Spring Expression Language in the
+ @Payload annotation to further instruct
+ the framework how the message should be constructed. In this particular case the message will be a concatenation of the return
+ value of the method invocation and the 'lname' input argument. The Message header named 'x' will have its value determined by
+ the 'num' input argument. That header will be added to the newly constructed Message.
@@ -108,29 +115,30 @@ public String argumentAsPayload(@Payload String fname, @Header String lname) {
}
- In the above example you see another usage of @Payload annotation. Here we are annotating method argument
- which will become a payload of newly constructed message.
+ In the above example you see another usage of the @Payload annotation. Here we are annotating a method argument
+ which will become the payload of the newly constructed message.
-
As with most other annotation-driven features in Spring, you will need to register a post-processor
(PublisherAnnotationBeanPostProcessor).
<bean class="org.springframework.integration.aop.PublisherAnnotationBeanPostProcessor"/>
- You can also use namespace support for added convenience:
+ You can instead use namespace support for a more concise configuration:
<si:annotation-config default-publisher-channel="defaultChannel"/>
- Similar to other Spring annotations (e.g., @Controller), @Publisher is a meta-annotation, which means you can define your own annotations
- that will be treated as @Publisher
+ Similar to other Spring annotations (@Component, @Scheduled, etc.), @Publisher can also be used as a meta-annotation.
+ That means you can define your own annotations
+ that will be treated in the same way as the @Publisher itself.
-Here we defined @Audit annotation which itself is a @Publisher. Also note that you can define channel
+Here we defined the @Audit annotation which itself is annotated with @Publisher.
+Also note that you can define a channel
attribute on the meta-annotation thus encapsulating the behavior of where messages will be sent inside of this annotation.
Now you can annotate any method:
@@ -139,10 +147,14 @@ public String test() {
return "foo";
}]]>
-In the above example every invocation of test() method will result in Message with payload which is the return value of the method
-invocation to be sent to auditChannel
+In the above example every invocation of the test() method will result in a Message with a payload created from its return value.
+Each Message will be sent to the channel named auditChannel. One of the benefits of this technique is that you can
+avoid the duplication of the same channel name across multiple annotations. You also can provide a level of indirection between your own,
+potentially domain-specific annotations and those provided by the framework.
+
-You can also annotate the class which would mean that the properties of this annotation will be applied on every public method of this class
+
+You can also annotate the class which would mean that the properties of this annotation will be applied on every public method of that class.
- XML-based approach via <publishing-interceptor> element
+ XML-based approach via the <publishing-interceptor> element
The XML-based approach allows you to configure the same AOP-based Message Publishing functionality with
simple namespace-based configuration of a MessagePublishingInterceptor.
@@ -195,7 +207,7 @@ static class BankingOperationsImpl implements BankingOperations {
]]>
- As you can see the <publishing-interceptor> configuration look rather similar to Annotation-based approach
+ As you can see the <publishing-interceptor> configuration looks rather similar to the Annotation-based approach,
and it also utilizes the power of the Spring 3.0 Expression Language.
@@ -203,11 +215,11 @@ static class BankingOperationsImpl implements BankingOperations {
render a Message with the following structure:
- The Message payload will be of type String and value of "Echoing: [value]" where value is the value
+ The Message payload will be of type String with the content "Echoing: [value]" where value is the value
returned by an executed method.
- The Message will have header with the key "foo" value "bar".
+ The Message will have a header with the name "foo" and value "bar".
The Message will be sent to echoChannel.
@@ -222,7 +234,7 @@ static class BankingOperationsImpl implements BankingOperations {
The Message payload will be the same as in the above sample
- The Message will have header with the key "foo" and value that is the result of the SpEL expression 'bar'.toUpperCase() .
+ The Message will have a header named "foo" whose value is the result of the SpEL expression 'bar'.toUpperCase() .
The Message will be sent to echoChannel.
@@ -257,23 +269,23 @@ static class BankingOperationsImpl implements BankingOperations {
One important thing to understand is that publishing occurs in the same thread as your component's execution. So by default in is synchronous.
- This means that the entire message flow would have to wait until he publisher flow completes.
- However, quite often you want the complete opposite and that is to use Message publishing feature to initiate asynchronous sub-flows.
+ This means that the entire message flow would have to wait until the publisher's flow completes.
+ However, quite often you want the complete opposite and that is to use this Message publishing feature to initiate asynchronous sub-flows.
For example, you might host a service (HTTP, WS etc.) which receives a remote request.You may want to send this request internally into a
process that might take a while. However you may also want to reply to the user right away. So, instead of sending inbound
- request for processing via the output channel (the conventional way), you can simply use ''outout-channel or $replyChannel'' header
- to send simple acknowledgment-like reply back to the caller while using Message publisher feature to initiate a complex flow.
+ requests for processing via the output channel (the conventional way), you can simply use 'output-channel' or a 'replyChannel' header
+ to send a simple acknowledgment-like reply back to the caller while using the Message publisher feature to initiate a complex flow.
EXAMPLE:
Here is the simple service that receives a complex payload, which needs to be sent further for processing, but it
- also need to reply to the caller with a simple acknowledgment.
-
- So instead of hooking up the complex flow to the output channel we use Message publishing feature instead configuring it to create a
- new Message using the input argument of the service method (above) and sending it to the 'localProcessChannel'. And to make sure this sub-flow
- is asynchronous all we need to do is make sure that we send it to any type of async channel (ExecutorChannel in this example).
+ So instead of hooking up the complex flow to the output channel we use the Message publishing feature instead. We configure it to create a
+ new Message using the input argument of the service method (above) and send that to the 'localProcessChannel'. And to make sure this sub-flow
+ is asynchronous all we need to do is send it to any type of asynchronous channel (ExecutorChannel in this example).
@@ -291,10 +303,11 @@ static class BankingOperationsImpl implements BankingOperations {
+
]]>
- Another way of handling thi type of scenario is through wire-tap
+ Another way of handling this type of scenario is with a wire-tap.
@@ -302,10 +315,11 @@ static class BankingOperationsImpl implements BankingOperations {
Producing and publishing messages based on a scheduled trigger
In the above sections we looked at the Message publishing feature of Spring Integration which constructs and publishes messages as by-products of Method invocations.
- However in that case, you are still responsible for invoking the method.
+ However in those cases, you are still responsible for invoking the method.
In Spring Integration 2.0 we've added another related useful feature: support for scheduled Message producers/publishers via the new "expression" attribute
on the 'inbound-channel-adapter' element. Scheduling could be based on several triggers, any one of which may be configured on the 'poller' sub-element.
- Currently we support cron, fixed-rate, fixed-delay as well as any custom trigger implemented by you.
+ Currently we support cron, fixed-rate, fixed-delay as well as any custom trigger implemented by you and
+ referenced by the 'trigger' attribute value.
As mentioned above, support for scheduled producers/publishers is provided via the <inbound-channel-adapter> xml element.
@@ -320,7 +334,7 @@ static class BankingOperationsImpl implements BankingOperations {
]]>
In the above example an inbound Channel Adapter will be created which will construct a Message with its payload being the result of the expression
- defined in the expression attribute. Such message will be created and sent every time after the delay specified by the fixed-delay attribute.
+ defined in the expression attribute. Such messages will be created and sent every time the delay specified by the fixed-delay attribute occurs.
cron attribute.
-
]]>
Here you can see that in a way very similar to the Message publishing feature we are enriching a newly constructed Message with
- extra Message headers which could take scalar values as well as the results of evaluating Spring expressions.
+ extra Message headers which can take scalar values or the results of evaluating Spring expressions.