I\'m in the process of developing a messaging interface for one of our applications. The application is a service which is designed to accept a \"Job\", do some processing, and
I'm as much a noob to spring-integration and spring-integration-amqp as you, I suspect, but I did get something working based in part on the one sample project.
For rabbitmq infrastructure, I have the following:
<rabbit:connection-factory id="rabbitConnectionFactory"/>
<rabbit:template id="amqpTemplate" connection-factory="rabbitConnectionFactory"/>
<rabbit:admin connection-factory="rabbitConnectionFactory"/>
<!-- some attributes seemed to be ok with queue name, others required id
-- so I used both with the same value -->
<rabbit:queue id='test.queue' name='test.queue'/>
<rabbit:direct-exchange name:"my.exchange">
<rabbit:bindings>
<rabbit:binding queue="test.queue" key="test.binding"/>
</rabbit:bindings>
</rabbit:direct-exchange>
To send a message to rabbitmq, I have the following:
<!-- This is just an interface definition, no implementation required
-- spring will generate an implementation which puts a message on the channel -->
<int:gateway id="backgroundService",
service-interface="com.company.BackgroundService"
default-request-channel="toRabbit"
<int:channel id:"toRabbit"/>
<!-- used amqpTemplate to send messages on toRabbit channel to rabbitmq -->
<int-amqp:outbound-channel-adapter channel:"toRabbit"
amqp-template="amqpTemplate"
exchange-name="my.exchange"
routing-key="test.binding"/>
And to receive messages I have the following:
<int:service-activator input-channel="fromRabbit"
ref="testService"
method="serviceMethod"/>
// from rabbitmq to local channel
<int-amqp:inbound-channel-adapter channel="fromRabbit"
queue-names="test.queue"
connection-factory="rabbitConnectionFactory"/>
<int:channel id="fromRabbit"/>
Some caveats - the documentation of amqp integration in spring-integration says it is possible to to a synchronous send and receive of a return value, but I haven't figured that out yet. When my service-activator method returned a value, it caused an exception to get thrown, putting the message back on rabbitmq (and generating an infinite loop, since it would then receive the message again and throw the exception again).
My BackgroundService interfacde looks like this:
package com.company
import org.springframework.integration.annotation.Gateway
public interface BackgroundService {
//@Gateway(requestChannel="someOtherMessageChannel")
public String sayHello(String toWho)
}
You can specify a channel on every method via the annotation if you don't wish to use the default channel configured in the spring bean.
The service attached to the service-activator looks like this:
package com.company;
class TestService {
public void serviceMethod(String param) {
log.info("serviceMethod received: " + param");
//return "hello, " + param;
}
}
When I had everything wired up locally without rabbitmq involved, the return value was correctly received by the caller. When I went to rabbitmq channels, I got the aforementioned infinite loop when an exception was thrown after returning a value. It is surely possible or else it wouldn't be possible to wire in different channels without modifying code, but I'm not sure what the trick is yet. Please respond with a solution if you figure it out. Obviously, you can put whatever routing, transforming, and filtering you like between the endpoints, as needed.
Don't be surprised if my XML excerpts above have typos in them. I had to convert back to xml from groovy DSL, so I could have made mistakes. But the intent should be clear enough.