16. Inbound Messaging Gateways

16.1 SimpleMessagingGateway

Even though the MessageChannelTemplate is fairly straightforward, it does not hide the details of messaging from your application code. To support working with plain Objects instead of messages, Spring Integration provides SimpleMessagingGateway with the following methods:

 public void send(Object object) { ... }

 public Object receive() { ... }

 public Object sendAndReceive(Object object) { ... }

 Message<?> sendAndReceiveMessage(Object object);

It enables configuration of a request and/or reply channel and delegates to instances of the InboundMessageMapper and OutboundMessageMapper strategy interfaces.

 SimpleMessagingGateway gateway = new SimpleMessagingGateway(inboundMapper, outboundMapper);
 gateway.setRequestChannel(requestChannel);
 gateway.setReplyChannel(replyChannel);
 Object result = gateway.sendAndReceive("test");

16.2 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 above. Namespace support is also provided as demonstrated by the following example.

<gateway id="fooService"
         service-interface="org.example.FooService"
         default-request-channel="requestChannel"
         default-reply-channel="replyChannel"/>

Then, the "fooService" can be injected into other beans, and the code that invokes the methods on that proxied instance of the FooService 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).

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.

 public interface Cafe {

     @Gateway(requestChannel="orders")
     void placeOrder(Order order);

 }

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:

 public interface FileWriter {

     @Gateway(requestChannel="filesOut")
     void write(byte[] content, @Header(FileHeaders.FILENAME) String filename);

 }

If you prefer XML way of configuring Gateway methods, you can provide method sub-elements to the gateway configuration (see below)

<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"/>
    	<si:method name="echoUpperCase" request-channel="inputB"/>
    	<si:method name="echoViaDefault"/>
</si:gateway>