You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by DominicTulley <do...@telelogic.com> on 2008/01/23 16:24:06 UTC

TimeoutException when using ReplyTo?

I have a routebuilder set up which sets a couple of headers on a message and
then passes that message on from queue A to queue B thus:

from ("activemq.a").setHeader("myflag",myexpression).to("activemq.b")

When I send messages with no ReplyTo set, it all works just fine.  The
messages arrive in B with their flag set appropriately.
Then I realised I had forgotten to set ReplyTo, so in my sending code I
added:
- the creation of a temp queue
- setting the replyto destination to that temp queue
- the creation of a consumer on the temp queue
- the receive call to get the answer.

Now, when I send the message various things are different/broken.  After the
message has been through the "route" and arrived at queue B we have the
following:

1)  The message has acquired an expiry time which it didn't previously have
2)  The message has been flagged as persistent (but the send mode is
non-persistent)
3)  The message has acquired a correlationID

None of these have occurred when the message arrives in A (so the routing
from A to B is making these changes).

The worst of it is that after the message expiry period passes (20 seconds
it seems) I get a java.util.concurrency.TimeoutException (stack trace at the
end of this message).  After five of these, the message is returned verbatim
to the replyTo queue and consumed.
But, it gets stranger yet...  If I put our consumer on the end of queue B
(it should consume the message and send the real reply) it appears to
receive the message five times - once each time the above noted exception
occurs.

It's possible I suppose that I'm failing to close some connection/session or
commit some send/receive operation (but I'm pretty sure I've got them all
right).  The fact that this only happens when JMSReplyTo is set throws me.

Finally, I am running on a trunk build from a day or two ago and I am
deploying my routebuilder using the newly added syntax <camelcontext>
<routeBuilderRef ref="somebean" /></camelcontext>.  I am running inside a
trunk from of AMQ from a couple of days ago also and using spring 2.0.6
rather than the 2.5.1 recently added to camel.

Any suggestions on where to start with this?  

Thanks,

-Dominic

==== Stack Trace =====

ERROR DeadLetterChannel              - Failed delivery for exchangeId:
ID-ukedfinger/4815-1201101739148/0-3. On delivery attempt: 0 caught:
java.util.concurrent.TimeoutException
java.util.concurrent.TimeoutException
        at
java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:211)
        at java.util.concurrent.FutureTask.get(FutureTask.java:85)
        at
org.apache.camel.component.jms.JmsProducer.process(JmsProducer.java:99)
        at
org.apache.camel.impl.converter.AsyncProcessorTypeConverter$ProcessorToAsynProcessorBridge.process(AsyncProcessorTypeConverter.java:44)
        at
org.apache.camel.processor.SendProcessor.process(SendProcessor.java:73)
        at
org.apache.camel.processor.DeadLetterChannel.process(DeadLetterChannel.java:143)
        at
org.apache.camel.processor.DeadLetterChannel.process(DeadLetterChannel.java:87)
        at org.apache.camel.processor.Pipeline.process(Pipeline.java:101)
        at org.apache.camel.processor.Pipeline.process(Pipeline.java:85)
        at
org.apache.camel.processor.UnitOfWorkProcessor.process(UnitOfWorkProcessor.java:40)
        at
org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:44)
        at
org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:68)
        at
org.apache.camel.component.jms.EndpointMessageListener.onMessage(EndpointMessageListener.java:66)
        at
org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:510)
        at
org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:445)
        at
org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:414)
        at
org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:309)
        at
org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:254)
        at
org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:871)

        at
org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:818)
        at java.lang.Thread.run(Thread.java:595)
Evicting inactive request for correlationID: Entry for key:
ID-ukedfinger/4815-1201101739148/2-0
-- 
View this message in context: http://www.nabble.com/TimeoutException-when-using-ReplyTo--tp15043879s22882p15043879.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: TimeoutException when using ReplyTo?

Posted by DominicTulley <do...@telelogic.com>.
Hi James,

The general picture is that I have a multithreaded client sending requests
to A and I have multiple servers listening on B.
In the middle, I have a route builder which reads from A, annotates the
message with some headers and then passes them on to B.
This allows the servers in B to use message selectors to retrieve only those
messages that they can service efficiently (according to the headers we
added).
Once a server has consumed a message and computed the reply, that reply
wants to go to the queue originally named in the message replyTo when it was
sent to A (so the whole routing from A to B plus annotation is transparent
to the replyTo mechanism).

With respect to the InOut thing - we're not using camel client libraries at
either end of this.  Both the client sending to A and the servers consuming
on B are using AMQ libraries.  I presume that means the InOut pattern you
mentioned doesn't apply - or perhaps I don't understand where it lives..

I think there are probably two separate problems for me here.  One is that
the addition of the various headers causes difficulties (triggered the dead
letter handler and also introducing an expectation of a correlationID in the
reply).  We changed the server end to honour the correlationID and that part
started working, but we don't really want the message expiry stuff.  In fact
I raised another discussion on this forum a while ago to discuss how I could
do my own expiry because the dead letter stuff didn't behave properly!

The second issue we seem to have is that when the dead letter handler does
kick in it appears to break, failing to acquire a synchronisation lock
somewhere.  This concerns me mainly because it might be some of my code
that's holding the troublesome lock - I can't tell very easily.  In a way I
don't particularly mind that the handler fails, because I'm trying not to
use it anyway, but I do worry that it suggests something else is wrong.

-Dominic
-- 
View this message in context: http://www.nabble.com/TimeoutException-when-using-ReplyTo--tp15043879s22882p15044864.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: TimeoutException when using ReplyTo?

Posted by Roman Kalukiewicz <ro...@gmail.com>.
2008/1/24, Hiram Chirino <hi...@hiramchirino.com>:
> It also makes loads of sense when talking to other InOut protocols
> like http.  For example
> from("jms:queue:test").to("http://localhost/test")
>
> It will take care sending the http response to the reply to queue.

BTW If we started this thread then I would like to ask if there is any
specific reason this MEP (Message Exchange Pattern) is not exposed via
Exchange interface, and is accessible only via cast to
DefaultExchange.

My problem is that we could imagine such situation:

from("jms:A").to("jms:B").to("jms:C");

It is really not clear what was the intent of the author here. Maybe B
queue is simply monitoring queue and there should be no response,
while C should wait for response. Maybe just the opposite situation? C
is monitoring while B is InOut. Moreover the presence of JMSReplyTo
header shouldn't change the whole intended behavior (as it does now).

I believe we should support something like:

from("jms:A").setPattern(InOnly).to("jms:B").setPattern(InOut).to("jms:C");

This is general solution, but it requires us to expose a MEP through
Exchange interface.

Roman

Re: TimeoutException when using ReplyTo?

Posted by Hiram Chirino <hi...@hiramchirino.com>.
On Jan 24, 2008 8:42 AM, DominicTulley <do...@telelogic.com> wrote:
>
> Thanks for the explanation Roman, I think it makes more sense to me now.
> It sounds like camel's automatic handling of replyto becomes more useful if
> we are bridging between brokers - then the server may not be able to access

It also makes loads of sense when talking to other InOut protocols
like http.  For example
from("jms:queue:test").to("http://localhost/test")

It will take care sending the http response to the reply to queue.

> the destination set in the ReplyTo from the original sender, so the replies
> go in steps, retracing the route the original message took.
>
> On the exception front, it also sounds better.  It wasn't clear to me if the
> exception was in response to my message, my reply, or some expectation
> within the system.  It sounds like it was a system expectation which I
> wasn't honouring so that's great too since the expectation doesn't exist for
> me now :-)
>
> I'm off to find my next hurdle now!
>
> -Dominic
>
> --
> View this message in context: http://www.nabble.com/TimeoutException-when-using-ReplyTo--tp15043879s22882p15064145.html
>
> Sent from the Camel - Users mailing list archive at Nabble.com.
>
>



-- 
Regards,
Hiram

Blog: http://hiramchirino.com

Open Source SOA
http://open.iona.com

Re: TimeoutException when using ReplyTo?

Posted by DominicTulley <do...@telelogic.com>.
Thanks for the explanation Roman, I think it makes more sense to me now.
It sounds like camel's automatic handling of replyto becomes more useful if
we are bridging between brokers - then the server may not be able to access
the destination set in the ReplyTo from the original sender, so the replies
go in steps, retracing the route the original message took.

On the exception front, it also sounds better.  It wasn't clear to me if the
exception was in response to my message, my reply, or some expectation
within the system.  It sounds like it was a system expectation which I
wasn't honouring so that's great too since the expectation doesn't exist for
me now :-)

I'm off to find my next hurdle now!

-Dominic

-- 
View this message in context: http://www.nabble.com/TimeoutException-when-using-ReplyTo--tp15043879s22882p15064145.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: TimeoutException when using ReplyTo?

Posted by Roman Kalukiewicz <ro...@gmail.com>.
2008/1/24, DominicTulley <do...@telelogic.com>:
>
> I disabled the InOut thing by using:
>
> from("activemq.A?disableReplyTo=true").setHeader(...).to("activemq.B");
>
> This appears to have resolved my immediate issue (in that the messages are
> no longer expiring).
> Is this correct, or should I also put the disableReplyTo on the "to"
> portion?

It really depends on what you want to happen. Now (as far as I guess)
it goes this way (InOnly == one-way):

client setting ReplyTo -> A -> Camel -> B -> server -> ReplyTo originally set

When you disableReplyTo it means that you don't want any response to
be sent (by Camel flow) to ReplyTo originally specified at input -
this ReplyTo is anyway propagated to server and the server responds to
JMSReplyTo.

When you had JMSReplyTo at the very beginning (without disableReplyTo)
Camel wanted to respond to the message _itself_ so it was using InOut
mode. According to InOut mode, when you send to B, Camel sets
CorrelationID and JMSReplyTo so it informs the server side about the
queue and Correlation it waits for a response on.

in InOut mode it should work as:

client setting ReplyTo -> A -> Camel  (sets its own JMSReplyTo) -> B
-> server -> ReplyTo set by Camel -> Camel -> ReplyTo specified at A
-> client

So what I guess:
Camel flow was previously working in InOut, so message was sent to B
and Camel was waiting for a response on its own JMSReplyTo (associated
with the message), but the server was responding to original
JMSReplyTo set by client side. Camel had no response, so timeout was
thrown, and redelivery was triggered.

> I'd also be interested in what you make of the concurrency timeout
> exception.  I've seen various other messages that talk about this exception,
> but it's not clear to me if it's expected or if it's an indicator that some
> code isn't behaving properly.

I believe that an answer to this question is basically in the answer
for the first part ;)

Roman

Re: TimeoutException when using ReplyTo?

Posted by DominicTulley <do...@telelogic.com>.
I disabled the InOut thing by using:

from("activemq.A?disableReplyTo=true").setHeader(...).to("activemq.B");

This appears to have resolved my immediate issue (in that the messages are
no longer expiring).
Is this correct, or should I also put the disableReplyTo on the "to"
portion?

I'd also be interested in what you make of the concurrency timeout
exception.  I've seen various other messages that talk about this exception,
but it's not clear to me if it's expected or if it's an indicator that some
code isn't behaving properly.

Thanks,

-Dominic
-- 
View this message in context: http://www.nabble.com/TimeoutException-when-using-ReplyTo--tp15043879s22882p15062110.html
Sent from the Camel - Users mailing list archive at Nabble.com.


Re: TimeoutException when using ReplyTo?

Posted by James Strachan <ja...@gmail.com>.
On 23/01/2008, DominicTulley <do...@telelogic.com> wrote:
>
> I have a routebuilder set up which sets a couple of headers on a message and
> then passes that message on from queue A to queue B thus:
>
> from ("activemq.a").setHeader("myflag",myexpression).to("activemq.b")
>
> When I send messages with no ReplyTo set, it all works just fine.  The
> messages arrive in B with their flag set appropriately.
> Then I realised I had forgotten to set ReplyTo, so in my sending code I
> added:
> - the creation of a temp queue
> - setting the replyto destination to that temp queue
> - the creation of a consumer on the temp queue
> - the receive call to get the answer.

BTW you don't have to do that; if you send a message to the JMS
endpoint with InOut as the message exchange pattern
(Exchange.setPattern()) it will automatically do this for you.


> Now, when I send the message various things are different/broken.  After the
> message has been through the "route" and arrived at queue B we have the
> following:
>
> 1)  The message has acquired an expiry time which it didn't previously have
> 2)  The message has been flagged as persistent (but the send mode is
> non-persistent)
> 3)  The message has acquired a correlationID

Thats all part of us trying to implement InOut behaviour for you under
the covers. You can override this by disabling InOut mode for messages
with a ReplyTo address set if you like.

Stepping back a little - could you describe exactly what you want to
happen; you want to consume from queue A then make a request-reply on
queue B and send the reply back to A?
-- 
James
-------
http://macstrac.blogspot.com/

Open Source Integration
http://open.iona.com