Here's my entire spring context. What I'm trying to implement is a form of guaranteed message processing. This is just a proof of concept, so ignore the Foo/Bar/Baz names and such.
Flow: User requests to block another user. BlockUserRequest is created and sent to jms:queue:dynamicQueues/BlockUserQueue com.webshots.messaging.ContentEnricher simulates DB lookup of the blocked user's e-mail and other user IDs with the same e-mail enriched BlockUserRequest is sent to jms:queue:dynamicQueues/Bar (handled by com.webshots.messaging.Bar) and jms:queue:dynamicQueues/Baz (handled by com.webshots.messaging.Baz) to perform part of the functionality com.webshots.messaging.Baz always throws an Exception, just for testing message sent to jms:queue:dynamicQueues/Baz ends up in jms:queue:dynamicQueues/DLQ and com.webshots.messaging.DeadLetterPersistanceProcessor mocks saving it to a DB (and possibly sends an e-mail) In com.webshots.messaging.DeadLetterPersistanceProcessor I need to know what Exception caused the message to be routed to the DLQ and what the original destination was. Then I can create a web interface to the stored dead letters where an administrator can view/edit the message and exception contents and resend or discard. If there's a better way to implement this, please feel free to let me know. Thanks. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:camel="http://activemq.apache.org/camel/schema/spring" xmlns:broker="http://activemq.apache.org/schema/core" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd"> <context:component-scan base-package="com.webshots.messaging"/> <camel:camelContext id="camel"> <camel:package>com.webshots.messaging</camel:package> <camel:template id="camelTemplate"/> <camel:route errorHandlerRef="deadLetterErrorHandler"> <camel:from uri="jms:queue:dynamicQueues/BlockUserQueue"/> <!-- EIP Content Enricher Pattern --> <camel:bean ref="contentEnricher"/> <!-- EIP Splitter Pattern --> <camel:multicast parallelProcessing="true"> <camel:to uri="jms:queue:dynamicQueues/Bar"/> <camel:to uri="jms:queue:dynamicQueues/Baz"/> </camel:multicast> </camel:route> <camel:route errorHandlerRef="deadLetterErrorHandler"> <camel:from uri="jms:queue:dynamicQueues/Bar"/> <camel:bean ref="bar"/> </camel:route> <camel:route errorHandlerRef="deadLetterErrorHandler"> <camel:from uri="jms:queue:dynamicQueues/Baz"/> <camel:bean ref="baz"/> </camel:route> <camel:route errorHandlerRef="infiniteRetryErrorHandler"> <camel:from uri="jms:queue:dynamicQueues/DLQ"/> <camel:process ref="deadLetterPersistanceHandler"/> </camel:route> </camel:camelContext> <bean id="contentEnricher" class="com.webshots.messaging.ContentEnricher"/> <bean id="bar" class="com.webshots.messaging.Bar"/> <bean id="baz" class="com.webshots.messaging.Baz"/> <bean id="deadLetterPersistanceHandler" class="com.webshots.messaging.DeadLetterPersistanceProcessor"/> <bean id="jms" class="org.apache.camel.component.jms.JmsComponent"> <property name="connectionFactory"> <bean class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="tcp://localhost:61616"/> </bean> </property> </bean> <bean id="headerCopyProcessor" class="com.webshots.messaging.HeaderCopyProcessor"/> <bean id="deadLetterRecipientsExpression" class="org.apache.camel.model.language.ConstantExpression"> <constructor-arg value="jms:queue:dynamicQueues/DLQ"/> </bean> <bean id="deadLetterRecipientList" class="org.apache.camel.processor.RecipientList"> <constructor-arg ref="deadLetterRecipientsExpression"/> </bean> <bean id="deadLetterProcessor" class="org.apache.camel.processor.CompositeProcessor"> <constructor-arg> <list> <ref bean="headerCopyProcessor"/> <ref bean="deadLetterRecipientList"/> </list> </constructor-arg> </bean> <bean id="deadLetterFactory" class="org.apache.camel.builder.ConstantProcessorBuilder"> <constructor-arg ref="deadLetterProcessor"/> </bean> <bean id="deadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder"> <property name="redeliveryPolicy" ref="redeliveryPolicy"/> <property name="deadLetterFactory" ref="deadLetterFactory"/> </bean> <bean id="redeliveryPolicy" class="org.apache.camel.processor.RedeliveryPolicy"> <property name="delay" value="1000"/> <property name="backOffMultiplier" value="2"/> <property name="useExponentialBackOff" value="true"/> <!-- this should make it retry 1s, 2s, 4s, 8s, 16s, 32s, ~1m, ~2m, ~4m, ~9m, ~17m, ~34m, ~68m, ~137m for a total of ~4.5h --> <!--<property name="maximumRedeliveries" value="14"/>--> <property name="maximumRedeliveries" value="1"/> </bean> <bean id="infiniteRetryErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder"> <property name="redeliveryPolicy" ref="infiniteRetryPolicy"/> </bean> <!-- TODO don't retry for NPE, etc. --> <bean id="infiniteRetryPolicy" class="org.apache.camel.processor.RedeliveryPolicy"> <property name="delay" value="60000"/> <property name="maximumRedeliveries" value="-1"/> <property name="useCollisionAvoidance" value="true"/> </bean> <bean id="blockUserRequest" scope="prototype" class="com.webshots.messaging.BlockUserRequest"> <property name="destinationUri" value="jms:queue:dynamicQueues/BlockUserQueue"/> <property name="camelTemplate" ref="camelTemplate"/> </bean> </beans> Claus Ibsen-2 wrote: > > Hi > > Could you post your route, to help get a view of your problem? > > To my knowledge the Exchange that is routed to DLC is the "original" > exchange as it was before it was processed by the node in the route > graph that failed. So if this node is a JMS producer the exchange > should have the JMS headers as well? > > For example: > from(x).process(y).to("jms:zzz"); > > If the error happens in the (to jms:zzz) the Exchange that is routed > to DLQ is how the exchange looks like from the output of the > process(y) node. > > But it helps if you could show the route and pin point where the error > happens > > > > /Claus Ibsen > Apache Camel Committer > Blog: http://davsclaus.blogspot.com/ > > > > On Tue, Dec 9, 2008 at 2:07 PM, efender <[EMAIL PROTECTED]> wrote: >> >> How can I record the original destination when routing to my DLQ? >> >> I've tried a custom processor which does this: >> >> public void process(Exchange exchange) throws Exception { >> org.apache.camel.Message in = exchange.getIn(); >> org.apache.camel.Message out = in.copy(); >> out.setHeader("originalDestination", >> in.getHeader("JMSDestination")); >> exchange.setProperty("originalDestination", >> in.getHeader("JMSDestination")); >> exchange.setOut(out); >> } >> >> But neither the property nor the header is set in my bean which listens >> to >> the DLQ. Do I need to modify/subclass >> org.apache.camel.processor.DeadLetterChannel to get this behavior? >> >> Also, I'd like to save the original Exception that caused the message to >> get >> routed to the DLQ as well. I see that it is stored in >> org.apache.camel.processor.DeadLetterChannel.FAILURE_HANDLED and >> CamelCauseException, but those properties disappear by the time the >> message >> gets to the DLQ. >> >> Any recommendations on how to save this info in a best practice sort of >> way? >> >> Thanks. >> -- >> View this message in context: >> http://www.nabble.com/Saving-original-destination-when-sending-to-DLQ-tp20914367s22882p20914367.html >> Sent from the Camel - Users mailing list archive at Nabble.com. >> >> > > -- View this message in context: http://www.nabble.com/Saving-original-destination-when-sending-to-DLQ-tp20914367s22882p20915821.html Sent from the Camel - Users mailing list archive at Nabble.com.
