camel-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From efender <eric+nab...@fender.net>
Subject Re: Saving original destination when sending to DLQ
Date Tue, 09 Dec 2008 14:36:58 GMT

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 <eric+nabble@fender.net> 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.


Mime
View raw message