简体   繁体   中英

Can I have multiple repliers in Apache Camel

Hi I have the following scenario: I have one client, which can ask several servers for an answer. Only one of the server can answer depending on the input. Only the servers know what they answer. I have tried using the requestReply pattern in Apache Camel, but I have a little problem.

public void configure() // server1
{
    from("activemq:topic:topicName").choice().when(header("cc").endsWith(5)).process(new Processor() {
        @Override
        public void process(Exchange _exchange) throws Exception {
            _exchange.getOut().setBody(".....................Returning.from server1......");
        }
    });
}

public void configure() //server2
{
    String replyChannel = "activemq:replyChannel";
    from("activemq:topic:topicName").choice().when(header("cc").endsWith(6)).process(new Processor() {
        @Override
        public void process(Exchange _exchange) throws Exception {
            _exchange.getOut().setBody(".....................Returning from server2.");
        }
    });
}
....
String event = "test 1";
Object result = amqProducer.getProducerTemplate().sendBodyAndHeader("activemq:topic:topicName", ExchangePattern.InOut, event,"cc" ,event.length());
System.out.println("Result "+result);    

So I'd like the above example to return "...Returning from server2.", because of the length 6. This is also the result, but Camel issues a warning "Reply received for unknown correlationID" which is due to the code of server1, which implicits also returns an answer.

Is there a more elgant way to solve this problem?

I think that you may achieve good results by using the Scatter Gather pattern.

The solution should resemble this:

from("activemq:topic:topicName")
       .multicast()
           .to("seda:server1", "seda:server2", "seda:server3");

from("seda:server1").to("my_component:server1").to("seda:aggregator");
from("seda:server2").to("my_component:server2").to("seda:aggregator");
from("seda:server3").to("my_component:server3").to("seda:aggregator");

 from("seda:aggregator")
       .aggregate(new SingleGroupExpression(), new ServerResponseAggregator())
           .completionSize(3)
           .completionTimeout(10000)
 .to("my_component:client")

What should happen with this is that you get one message from topicName which is "multicasted" to different internal SEDA queues. Upon receipt on those queues, the message is dispatched to the respective server. Having received the response from the server(s) the message is sent to another internal SEDA queue, for aggregation and further processing.

In this short example, the aggregation strategy fires up either when 3 messages are received or when the 10 second timeout is reached.

One thing that you should be aware of is that this example implies that the servers will reply to your application. If that is not the case, you can handle this by setting the timeout option specific to the component you use to communicate with the server. For instance, if you used JMS you could do this:

from("seda:server1").to("jms:queue:server1?requestTimeout=5000").to("seda:aggregator");

And then use one of the camel error handling mechanisms (DefaultErrorHandler, Exception Clause, Dead Letter Channel, etc) to handle the errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM