INT-1552 doc polishing
This commit is contained in:
@@ -21,13 +21,13 @@ public interface Cafe {
|
||||
]]></programlisting>
|
||||
|
||||
Namespace support is also
|
||||
provided which allows you to configure such interface as a service and is demonstrated by the following example.
|
||||
provided which allows you to configure such an interface as a service as demonstrated by the following example.
|
||||
<programlisting language="xml"><![CDATA[<gateway id="cafeService"
|
||||
service-interface="org.cafeteria.Cafe"
|
||||
default-request-channel="requestChannel"
|
||||
default-reply-channel="replyChannel"/>]]></programlisting>
|
||||
|
||||
Then, the "cafeService" can be injected into other beans, and the code that invokes the methods on that
|
||||
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).
|
||||
@@ -42,7 +42,7 @@ public interface Cafe {
|
||||
void placeOrder(Order order);
|
||||
|
||||
}]]></programlisting>
|
||||
... as well as <code>method</code> sub element if you prefer XML configuration (see next paragraph)
|
||||
You may alternatively provide such content in <code>method</code> sub-elements if you prefer XML configuration (see the next paragraph).
|
||||
</para>
|
||||
<para>
|
||||
It is also possible to pass values to be interpreted as Message headers on the Message
|
||||
@@ -56,8 +56,8 @@ public interface Cafe {
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you prefer XML way of configuring Gateway methods, you can provide <emphasis>method</emphasis> sub-elements
|
||||
to the gateway configuration (see below)
|
||||
If you prefer the XML approach of configuring Gateway methods, you can provide <emphasis>method</emphasis> sub-elements
|
||||
to the gateway configuration.
|
||||
<programlisting language="xml"><![CDATA[<si:gateway id="myGateway" service-interface="org.foo.bar.TestGateway"
|
||||
default-request-channel="inputC">
|
||||
<si:method name="echo" request-channel="inputA" reply-timeout="2" request-timeout="200"/>
|
||||
@@ -72,7 +72,7 @@ public interface Cafe {
|
||||
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
|
||||
violate the separation of concerns paradigm (method is a java artifact), but expressing your
|
||||
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.
|
||||
|
||||
<programlisting language="xml"><![CDATA[<int:gateway id="loanBrokerGateway"
|
||||
@@ -84,11 +84,11 @@ public interface Cafe {
|
||||
<int:header name="RESPONSE_TYPE" value="ALL"/>
|
||||
</int:method>
|
||||
</int:gateway>]]></programlisting>
|
||||
In the above case you can clearly see how a different header value will be set for the 'RESPONSE_TYPE'
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
As with anything else, Gateway invocation might result in errors.
|
||||
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)
|
||||
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
|
||||
@@ -126,21 +126,24 @@ public interface Cafe {
|
||||
</para>
|
||||
<para>
|
||||
<important>
|
||||
Exposing messaging system via POJO Gateway is obviously a great benefit, but it does come at the price so there
|
||||
are certain things you must be aware of.
|
||||
Exposing the messaging system via simple POJI Gateways obviously provides benefits, but "hiding" the reality
|
||||
of the underlying messaging system does come at a price so there are certain things you should consider.
|
||||
|
||||
We want our Java method to return as quick as possible and not hang for infinite amount of time until they can
|
||||
return (void , exception or return value). When regular methods are used as a proxies in front of the Messaging
|
||||
system we have to take into account the asynchronous nature of the Messaging Systems. This means that there might
|
||||
be a chance that a Message hat was initiated by a Gateway could be dropped by a Filter, thus never reaching a
|
||||
component that is responsible to produce a reply. Some Service Activator method might result in the Exception,
|
||||
thus resulting in no-reply (as we don't generate Null messages).So as you can see there are multiple scenarios
|
||||
where reply message might not be coming which is perfectly natural in messaging systems. However think about the
|
||||
implication on the gateway method. The Gateway's method input arguments were incorporated into a Message and
|
||||
sent downstream. The reply Message would be converted to a return value of the Gateway's method. So you can see
|
||||
how ugly it could get if you can not guarantee that for each Gateway call there will alway be a reply Message.
|
||||
Basically your Gateway method will never return and will hang infinitely.
|
||||
One of the ways of handling this situation is via AsyncGateway (explained later in this section). Another way of handling it is to explicitly set the reply-timeout attribute. This way gateway will not hang for more then the time that was specified by the reply-timeout and will return 'null'.
|
||||
We want our Java method to return as quickly as possible and not hang for an indefinite amount of time while
|
||||
the caller is waiting on it to return (void, return value, or a thrown Exception). When regular methods are
|
||||
used as a proxies in front of the Messaging system, we have to take into account the potentially asynchronous
|
||||
nature of the underlying messaging. This means that there might
|
||||
be a chance that a Message that was initiated by a Gateway could be dropped by a Filter, thus never reaching a
|
||||
component that is responsible for producing a reply. Some Service Activator method might result in an Exception,
|
||||
thus providing no reply (as we don't generate Null messages). So as you can see there are multiple scenarios
|
||||
where a reply message might not be coming. That is perfectly natural in messaging systems. However think about the
|
||||
implication on the gateway method. The Gateway's method input arguments were incorporated into a Message and
|
||||
sent downstream. The reply Message would be converted to a return value of the Gateway's method. So you might want
|
||||
to ensure that for each Gateway call there will always be a reply Message.
|
||||
Otherwise, your Gateway method might never return and will hang indefinitely.
|
||||
One of the ways of handling this situation is via an Asynchronous Gateway (explained later in this section). Another way of handling it is to explicitly set the reply-timeout attribute. That way, the gateway will not hang any longer than the time specified by the reply-timeout and will return 'null' if that timeout does elapse. Finally, you might want to consider setting downstream flags such as 'requires-reply' on
|
||||
a service-activator or 'throw-exceptions-on-rejection' on a filter. These options will be discussed in more detail in the final section
|
||||
of this chapter.
|
||||
</important>
|
||||
</para>
|
||||
</section>
|
||||
@@ -148,13 +151,13 @@ One of the ways of handling this situation is via AsyncGateway (explained later
|
||||
<title>Asynchronous Gateway</title>
|
||||
<para>
|
||||
As a pattern the Messaging Gateway is a very nice way to hide messaging-specific code while still exposing the full capabilities of the
|
||||
messaging system. And <classname>GatewayProxyFactoryBean</classname> provides a convenient way to expose a Proxy over a service-interface
|
||||
thus giving you a POJO-based access to a messaging system (based on objects in your own domain, or primitives/Strings, etc). But when a
|
||||
messaging system. As you've seen, the <classname>GatewayProxyFactoryBean</classname> provides a convenient way to expose a Proxy over a service-interface
|
||||
thus giving you POJO-based access to a messaging system (based on objects in your own domain, or primitives/Strings, etc). But when a
|
||||
gateway is exposed via simple POJO methods which return values it does imply that for each Request message (generated when the method is invoked)
|
||||
there must be a Reply message (generated when the method has returned). Since Messaging systems naturally are asynchronous you may not always be
|
||||
able to guarantee the contract where <emphasis>"for each request there will always be be a reply"</emphasis>.
|
||||
With Spring Integration 2.0 we are introducing support for an <emphasis>Asynchronous Gateway</emphasis> which is a convenient way to initiate
|
||||
flows where you may not know if a reply is expected or how long will it take for it to arrive.
|
||||
flows where you may not know if a reply is expected or how long will it take for replies to arrive.
|
||||
</para>
|
||||
<para>
|
||||
A natural way to handle these types of scenarios in Java would be relying upon <emphasis>java.util.concurrent.Future</emphasis> instances, and
|
||||
@@ -172,12 +175,12 @@ One of the ways of handling this situation is via AsyncGateway (explained later
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
As you can see from the example above the return type for the gateway method is <classname>Future</classname>. When
|
||||
As you can see from the example above the return type for the gateway method is a <classname>Future</classname>. When
|
||||
<classname>GatewayProxyFactoryBean</classname> sees that the
|
||||
return type of the gateway method is <classname>Future</classname>, it immediately switches to the async mode by utilizing
|
||||
an <classname>AsyncTaskExecutor</classname>. That is all. The call to a method always returns immediately with <classname>Future</classname>
|
||||
encapsulating the interaction with the framework.
|
||||
Now you can interact with the <classname>Future</classname> at your own pace to get the result, timeout, get the exception etc...
|
||||
return type of the gateway method is a <classname>Future</classname>, it immediately switches to the async mode by utilizing
|
||||
an <classname>AsyncTaskExecutor</classname>. That is all. The call to such a method always returns immediately with a <classname>Future</classname> instance.
|
||||
Then, you can interact with the <classname>Future</classname> at your own pace to get the result, cancel, etc. And, as with
|
||||
any other use of Future instances, calling get() may reveal a timeout, an execution exception, and so on.
|
||||
<programlisting language="java">MathServiceGateway mathService = ac.getBean("mathService", MathServiceGateway.class);
|
||||
Future<Integer> result = mathService.multiplyByTwo(number);
|
||||
// do something else here since the reply might take a moment
|
||||
@@ -187,13 +190,13 @@ For a more detailed example, please refer to the <emphasis>async-gateway</emphas
|
||||
|
||||
</section>
|
||||
<section>
|
||||
<title>Gateway behavior when no response is coming</title>
|
||||
<title>Gateway behavior when no response arrives</title>
|
||||
<para>
|
||||
As it was explained earlier, Gateway provides a convenient way of interacting with Messaging system via POJO method
|
||||
invocations, but realizing that a typical method invocation, which is generally expected to always return (even with Exception),
|
||||
might not always map one-to-one to message exchanges (e.g., reply message might not be coming which is equivalent to
|
||||
method not returning), it is important to go over several scenarios especially in the Sync Gateway case and understand
|
||||
what the default behavior of the Gateway and how to deal with these scenarios to make Sync Gateway behavior more
|
||||
As it was explained earlier, the Gateway provides a convenient way of interacting with a Messaging system via POJO method
|
||||
invocations, but realizing that a typical method invocation, which is generally expected to always return (even with an Exception),
|
||||
might not always map one-to-one to message exchanges (e.g., a reply message might not arrive - which is equivalent to a
|
||||
method not returning). It is important to go over several scenarios especially in the Sync Gateway case and understand
|
||||
the default behavior of the Gateway and how to deal with these scenarios to make the Sync Gateway behavior more
|
||||
predictable regardless of the outcome of the message flow that was initialed from such Gateway.
|
||||
</para>
|
||||
<para>
|
||||
@@ -209,16 +212,15 @@ For a more detailed example, please refer to the <emphasis>async-gateway</emphas
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Sync Gateway - single-threaded</emphasis>.
|
||||
If a component downstream is still running (e.g., infinite loop or a very slow service), then setting <emphasis>reply-timeout</emphasis>
|
||||
has no effect and Gateway method call will not return until such downstream service exits (e.g., return or exception).
|
||||
If a component downstream is still running (e.g., infinite loop or a very slow service), then setting a <emphasis>reply-timeout</emphasis>
|
||||
has no effect and the Gateway method call will not return until such downstream service exits (via return or exception).
|
||||
<emphasis>Sync Gateway - multi-threaded</emphasis>.
|
||||
If a component downstream is still running (e.g., infinite loop or a very slow service), in a multi-threaded message
|
||||
flow setting <emphasis>reply-timeout</emphasis> will have an effect by allowing gateway method invocation to
|
||||
return once the timeout has been reached, since <classname>GatewayProxyFactoryBean</classname> will simply
|
||||
poll on the reply channel waiting for a message until the timeout expires. However it could result in the 'null' return
|
||||
flow setting the <emphasis>reply-timeout</emphasis> will have an effect by allowing gateway method invocation to
|
||||
return once the timeout has been reached, since the <classname>GatewayProxyFactoryBean</classname> will simply
|
||||
poll on the reply channel waiting for a message until the timeout expires. However it could result in a 'null' return
|
||||
from the Gateway method if the timeout has been reached before the actual reply was produced. It is also important to understand that
|
||||
the reply message (if produced) will be sent to a reply channel after Gateway method invocation might have returned, so you must be aware of that
|
||||
and design your flow with this in mind.
|
||||
the reply message (if produced) will be sent to a reply channel after the Gateway method invocation might have returned, so you must be aware of that and design your flow with this in mind.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Downstream component returns 'null'</emphasis>
|
||||
@@ -226,9 +228,9 @@ For a more detailed example, please refer to the <emphasis>async-gateway</emphas
|
||||
<para>
|
||||
<emphasis>Sync Gateway - single-threaded</emphasis>.
|
||||
If a component downstream returns 'null' and no <emphasis>reply-timeout</emphasis> has been configured, the Gateway
|
||||
method call will hang indefinitely unless: a) <emphasis>reply-timeout</emphasis> has been configured or b)
|
||||
method call will hang indefinitely unless: a) a <emphasis>reply-timeout</emphasis> has been configured or b) the
|
||||
<emphasis>requires-reply</emphasis> attribute has been set on the downstream component (e.g., service-activator)
|
||||
that might return 'null'. In this case, the exception will be thrown and propagated to the Gateway.
|
||||
that might return 'null'. In this case, an Exception would be thrown and propagated to the Gateway.
|
||||
<emphasis>Sync Gateway - multi-threaded</emphasis>. Behavior is the same as above.
|
||||
</para>
|
||||
<para>
|
||||
@@ -237,7 +239,7 @@ For a more detailed example, please refer to the <emphasis>async-gateway</emphas
|
||||
<para>
|
||||
<emphasis>Sync Gateway - single-threaded</emphasis>.
|
||||
If a component downstream returns 'void' and no <emphasis>reply-timeout</emphasis> has been configured,
|
||||
the Gateway method call will hang indefinitely unless <emphasis>reply-timeout</emphasis> has been configured
|
||||
the Gateway method call will hang indefinitely unless a <emphasis>reply-timeout</emphasis> has been configured
|
||||
<emphasis>Sync Gateway - multi-threaded</emphasis> Behavior is the same as above.
|
||||
</para>
|
||||
<para>
|
||||
@@ -245,7 +247,7 @@ For a more detailed example, please refer to the <emphasis>async-gateway</emphas
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Sync Gateway - single-threaded</emphasis>.
|
||||
If a component downstream throws a Runtime Exception, such exception will be propagated via Error Message back to
|
||||
If a component downstream throws a Runtime Exception, such exception will be propagated via an Error Message back to
|
||||
the gateway and re-thrown.
|
||||
<emphasis>Sync Gateway - multi-threaded</emphasis> Behavior is the same as above.
|
||||
</para>
|
||||
@@ -253,18 +255,21 @@ For a more detailed example, please refer to the <emphasis>async-gateway</emphas
|
||||
<important>
|
||||
It is also important to understand that by default <emphasis>reply-timeout</emphasis> is unbounded which means that
|
||||
if not explicitly set there are several scenarios (described above) where your Gateway method invocation might
|
||||
hang indefinitely, so make sure you analyze your flow and if there is even a remote possibility of one of these
|
||||
scenarios to occur, set the <emphasis>reply-timeout</emphasis> attribute to a 'safe' value or better off
|
||||
set the <emphasis>requires-reply</emphasis> attribute of the downstream component to 'true' to ensure a timely response.
|
||||
hang indefinitely. So, make sure you analyze your flow and if there is even a remote possibility of one of these
|
||||
scenarios to occur, set the <emphasis>reply-timeout</emphasis> attribute to a 'safe' value or, even better,
|
||||
set the <emphasis>requires-reply</emphasis> attribute of the downstream component to 'true' to ensure a timely response
|
||||
as produced by the throwing of an Exception as soon as that downstream component does return null internally.
|
||||
But also, realize that there are some scenarios (see the very first one)
|
||||
where <emphasis>reply-timeout</emphasis> will not help which means it is also important to analyze your message
|
||||
flow and decide when to use Sync Gateway vs Async Gateway where Gateway method invocation is always guaranteed
|
||||
to return while giving you a more granular control over the results of the invocation via Java Futures.
|
||||
where <emphasis>reply-timeout</emphasis> will not help. That means it is also important to analyze your message
|
||||
flow and decide when to use a Sync Gateway vs an Async Gateway. As you've seen the latter case is simply a matter of
|
||||
defining Gateway methods that return Future instances. Then, you are guaranteed to receive that return value, and
|
||||
you will have more granular control over the results of the invocation.
|
||||
<para>
|
||||
Also, when dealing with Router you should remember that setting <emphasis>resolution-required</emphasis> attribute to 'true'
|
||||
will result in the exception thrown by the router if it can not resolve a particular channel. And when dealing with the filter
|
||||
you can also set <emphasis>throw-exception-on-rejection</emphasis> attribute. Both of these will help to ensure a timely response
|
||||
from the Gateway method invocation.
|
||||
Also, when dealing with a Router you should remember that setting the <emphasis>resolution-required</emphasis> attribute to 'true'
|
||||
will result in an Exception thrown by the router if it can not resolve a particular channel. Likewise, when dealing with a Filter,
|
||||
you can set the <emphasis>throw-exception-on-rejection</emphasis> attribute. In both of these cases, the resulting flow will
|
||||
behave like that containing a service-activator with the 'requires-reply' attribute. In other words, it will help to ensure
|
||||
a timely response from the Gateway method invocation.
|
||||
</para>
|
||||
</important>
|
||||
</para>
|
||||
|
||||
Reference in New Issue
Block a user