diff --git a/docs/src/reference/docbook/gateway.xml b/docs/src/reference/docbook/gateway.xml index c8e2ec0b00..a4e41e30c4 100644 --- a/docs/src/reference/docbook/gateway.xml +++ b/docs/src/reference/docbook/gateway.xml @@ -1,103 +1,136 @@
- Inbound Messaging Gateways - + Messaging Gateways + + The primary purpose of a Gateway is to hide the messaging API provided by + Spring Integration. It allows your application's business logic to be completely + unaware of the Spring Integration API and using a generic Gateway, your code + interacts instead with a simple interface, only. +
- GatewayProxyFactoryBean + Enter the GatewayProxyFactoryBean - Working with Objects instead of Messages is an improvement. However, it would be even better to have no - dependency on the Spring Integration API at all - including the gateway class. For that reason, Spring - Integration also provides a GatewayProxyFactoryBean that generates a proxy for - any interface and internally invokes the gateway methods shown below. - GatewayProxyFactoryBean that + generates a proxy for any interface and internally invokes the gateway + methods shown below. Using dependency injection you can then expose the interface + to your business methods. + + + Here is an example of an interface that can be used to interact with Spring + Integration: + + + - + void placeOrder(Order order); + +}]]> + +
+
+ Gateway XML Namespace Support + Namespace support is also provided which allows you to configure such an interface as a service as demonstrated by the following example. + ]]> - + With this configuration defined, the "cafeService" can now be injected into other beans, and the code that invokes the methods on that proxied instance of the Cafe interface has no awareness of the Spring Integration API. The general approach is similar to that of Spring Remoting (RMI, HttpInvoker, etc.). See the "Samples" Appendix for an example that uses this "gateway" element (in the Cafe demo). - - Typically you don't have to specify the default-reply-channel since a Gateway will - auto-create a temporary, anonymous reply channel where it will listen for the reply. - However, there are some cases which may prompt you to define a default-reply-channel (or reply-channel - with adapter gateways such as HTTP, JMS, etc.). - For some background, we'll quickly discuss some of the inner-workings of the Gateway. - A Gateway will create a temporary point-to-point reply channel which is anonymous and is added - to the Message Headers with the name replyChannel. - When providing an explicit default-reply-channel (reply-channel with remote adapter gateways), - you have the option to point to a publish-subscribe channel, which is so named because you can add more than one subscriber to it. - Internally Spring Integration will create a Bridge between the temporary replyChannel and the explicitly defined - default-reply-channel. + +
+
+ Setting the Default Reply Channel + + Typically you don't have to specify the default-reply-channel, + since a Gateway will auto-create a temporary, anonymous reply channel, + where it will listen for the reply. However, there are some cases which + may prompt you to define a default-reply-channel (or reply-channel + with adapter gateways such as HTTP, JMS, etc.). + + + For some background, we'll quickly discuss some of the inner-workings of the Gateway. + A Gateway will create a temporary point-to-point reply channel which is anonymous and is added + to the Message Headers with the name replyChannel. + When providing an explicit default-reply-channel (reply-channel with remote adapter gateways), + you have the option to point to a publish-subscribe channel, which is so named because you can add more than one subscriber to it. + Internally Spring Integration will create a Bridge between the temporary replyChannel and the explicitly defined + default-reply-channel. + + + So let's say you want your reply to go not only to the gateway, but also to some other consumer. In this case you + would want two things: a) a named channel you can subscribe to and b) that channel is a publish-subscribe-channel. + The default strategy used by the gateway will not satisfy those needs, because the reply channel added to the header is anonymous and + point-to-point. This means that no other subscriber can get a handle to it and even if it could, the channel + has point-to-point behavior such that only one subscriber would get the Message. So by defining a default-reply-channel + you can point to a channel of your choosing, which in this case would be a publish-subscribe-channel. + The Gateway would create a bridge from it to the temporary, anonymous reply channel that is stored in the header. + + + Another case where you might want to provide a reply channel explicitly is for monitoring or auditing via an interceptor + (e.g., wiretap). You need a named channel in order to configure a Channel Interceptor. + +
+
+ Gateway Configuration with Annotations and/or XML + + The reason that the attributes on the 'gateway' element are named 'default-request-channel' and + 'default-reply-channel' is that you may also provide per-method channel references by using the + @Gateway annotation. + - So let's say you want your reply to go not only to the gateway, but also to some other consumer. In this case you - would want two things: a) a named channel you can subscribe to and b) that channel is a publish-subscribe-channel. - The default strategy used by the gateway will not satisfy those needs, because the reply channel added to the header is anonymous and - point-to-point. This means that no other subscriber can get a handle to it and even if it could, the channel - has point-to-point behavior such that only one subscriber would get the Message. So by defining a default-reply-channel - you can point to a channel of your choosing which in this case would be a publish-subscribe-channel. - The Gateway would create a bridge from it to the temporary, anonymous reply channel that is stored in the header. - - Another case where you might want to provide a reply channel explicitly is for monitoring or auditing via an interceptor - (e.g., wiretap). You need a named channel in order to configure a Channel Interceptor. - - - - The reason that the attributes on the 'gateway' element are named 'default-request-channel' and - 'default-reply-channel' is that you may also provide per-method channel references by using the - @Gateway annotation. - You may alternatively provide such content in method sub-elements if you prefer XML configuration (see the next paragraph). + + You may alternatively provide such content in method sub-elements if you prefer XML configuration (see the next paragraph). It is also possible to pass values to be interpreted as Message headers on the Message that is created and sent to the request channel by using the @Header annotation: + - - If you prefer the XML approach of configuring Gateway methods, you can provide method sub-elements - to the gateway configuration. + If you prefer the XML approach of configuring Gateway methods, you can provide method sub-elements + to the gateway configuration. + + ]]> - + You can also provide individual headers per method invocation via XML. This could be very useful if the headers you want to set are static in nature and you don't want to embed them in the gateway's method signature via @Header annotations. For example, in the Loan Broker example we want to influence how aggregation of the Loan quotes will be done based on what type of request was initiated (single quote or all quotes). Determining the - type of the request by evaluating what gateway method was invoked, although possible would + type of the request by evaluating what gateway method was invoked, although possible, would violate the separation of concerns paradigm (the method is a java artifact),  but expressing your intention (meta information) via Message headers is natural in a Messaging architecture. + @@ -108,12 +141,63 @@ public interface Cafe { ]]> - In the above case you can clearly see how a different value will be set for the 'RESPONSE_TYPE' - header based on the gateway's method. - + In the above case you can clearly see how a different value will be set for the 'RESPONSE_TYPE' + header based on the gateway's method. + + +
+
+ Invoking No-Argument Methods + + When invoking methods on a Gateway interface that do not have any arguments, + the default behavior is to receive a Message from a + PollableChannel. + + + At times however, you may want to trigger no-argument methods so that + you can in fact interact with other components downstream that do not require + user-provided parameters, e.g. triggering no-argument SQL calls or Stored + Procedures. + + + In order to achieve send-and-receive semantics, you must provide a payload. + In order to generate a payload, method parameters on the interface are + not necessary. You can either use the @Payload annotation + or the payload-expression attribute in XML on the method + sub-element. Below please find a few examples of what the payloads could be: + + + + a literal string + #method (for the method name) + new java.util.Date() + @someBean.someMethod()'s return value + + + + Here is an example using the @Payload annotation: + + retrieveOpenOrders(); + +}]]> + + If a method has no argument and no return value, but does contain a + payload expression, it will be treated as a send-only + operation. + +
+ +
+ Error Handling + + Of course, the Gateway invocation might result in errors. - By default any error that has occurred downstream will be re-thrown as a MessagingException (RuntimeException) + By default any error that has occurred downstream will be re-thrown as a + MessagingException (RuntimeException) upon the Gateway's method invocation. However there are times when you may want to simply log the error rather than propagating it, or you may want to treat an Exception as a valid reply, by mapping it to a Message that will conform to some @@ -122,7 +206,7 @@ public interface Cafe { error-channel attribute. In the example below, you can see that a 'transformer' is used to create a reply Message from the Exception. - + ]]> - + The exceptionTransformer could be a simple POJO that knows how to create the expected error response objects. That would then be the payload that is sent back to the caller. Obviously, you could do many @@ -188,16 +272,18 @@ of this chapter. that is exactly what Spring Integration uses to support an Asynchronous Gateway. - From the XML configuration, there is nothing different and you still define Asynchronous Gateway the same way as a regular Gateway. + From the XML configuration, there is nothing different and you still define Asynchronous Gateway the same way as a regular Gateway. + ]]> + However the Gateway Interface (service-interface) is a bit different. - + public interface MathServiceGateway { Future<Integer> multiplyByTwo(int i); } - + As you can see from the example above the return type for the gateway method is a Future. When GatewayProxyFactoryBean sees that the @@ -300,7 +386,7 @@ For a more detailed example, please refer to the async-gateway * reply-timeout is unbounded for <gateway/> elements (created by the GatewayProxyFactoryBean). Inbound gateways for external integration - (ws, http, etc.) share many characteristics and attributes with these gateways. However, + (ws, http, etc.) share many characteristics and attributes with these gateways. However, for those inbound gateways, the default reply-timeout is 1000 milliseconds (1 second). If a downstream async handoff is made to another thread, you may need to increase this attribute to allow enough time for the flow to complete before the