デッド レター チャネルの Camel ドキュメントで説明されているとおりに、デッド レター チャネル EIP を使用しています。これが私のcamel.xmlです(ヘッダーは削除されています)
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<!-- this is the Dead Letter Channel error handler, where we send failed message to a log endpoint -->
<route errorHandlerRef="myDeadLetterErrorHandler">
<from uri="jms:q1" />
<doTry>
<validate><simple>${body[subsc]} regex '[a-z0-9]{8}' </simple> </validate>
<choice>
<when>
<simple>${body[key1]} regex '^(v1)$'</simple>
<choice>
<when>
<simple>${body[key2]} == 'v2'</simple>
<to uri="jms:getInfo" />
</when>
</choice>
</when>
<otherwise>
<to uri="jms:invalid" />
<stop />
</otherwise>
</choice>
<doCatch>
<exception>org.apache.camel.ValidationException</exception>
<to uri="jms:invalid"/>
</doCatch>
</doTry>
</route>
<route>
<from uri="jms:queue:deadlc" />
<log message="Got ${body}" loggingLevel="ERROR" logName="cool" />
</route>
</camelContext>
<!--
Lets configure some Camel endpoints
http://camel.apache.org/components.html
-->
<!-- configure the camel activemq component to use the current broker -->
<bean id="confact" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://amq-broker?create=false"/>
<property name="userName" value="${activemq.username}"/>
<property name="password" value="${activemq.password}"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" >
<property name="connectionFactory" ref="confact" />
</bean>
<bean id="pooledConnectionFactory"
class="org.apache.activemq.pool.PooledConnectionFactory"
init-method="start"
destroy-method="stop">
<property name="maxConnections" value="8" />
<property name="connectionFactory" ref="confact" />
<property name="expiryTimeout" value="-1" />
<property name="idleTimeout" value="-1" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="8"/>
</bean>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
<bean id="myDeadLetterErrorHandler" class="org.apache.camel.builder.DeadLetterChannelBuilder">
<property name="deadLetterUri" value="jms:queue:deadlc"/>
<property name="redeliveryPolicy" ref="myRedeliveryPolicyConfig"/>
</bean>
<bean id="myRedeliveryPolicyConfig" class="org.apache.camel.processor.RedeliveryPolicy">
<property name="maximumRedeliveries" value="3"/>
<property name="redeliveryDelay" value="5000"/>
</bean>
メッセージ本文に getInfo がある場合は jms:foo から jms:getInfo にルーティングし、メッセージ本文に performAction がある場合は jms.foo から jms:performAction にルーティングするというコンテンツベースのルーターを持つルートが 1 つだけあります。
jms:getInfo コンシューマーが実行されていない場合、配信は失敗し、再配信の試行は春の XML で指定されたとおりになると予想されます。しかし、何も起こらず、デッド レター キューにも何も送られません。代わりに、activemq は以下に示す例外をスローします。
なぜそれが機能しないのか説明できますか?私の理解では、コンシューマー (コンテンツベースのルーターからメッセージを受信する宛先) が実行されていない場合、acivemq はそれを配信することさえできず、すぐに例外をスローする必要があることを認識しており、その例外はキャメルのデッドレターチャネルによって処理されます。設定どおり。
私はラクダ 2.10.3 と activemq 5.8.0 を使用しています。
これらの失敗したメッセージは、activemq Web コンソールの Activemq.DLQ に表示されるため、activemq がデッド レター キューの camel xml 構成を無視して、失敗したメッセージ配信を処理していると思われます。コンシューマが実行されている場合、メッセージは camel.xml で指定されたルーティングに従って正常に配信されます。
0:58:46,317 | デバッグ | JMS メッセージの送信先: queue://getInfo とメッセージ: ActiveMQMapMessage {commandId = 0、responseRequired = false、messageId = null、originalDestination = null、originalTransactionId = null、producerId = null、destination = null、transactionId = null、expiration = 0 、タイムスタンプ = 0、到着 = 0、brokerInTime = 0、brokerOutTime = 0、correlationId = a79a0f9e-c88f-4501-a56d-2d5667aa98e0、replyTo = temp-queue://ID:myhost-57639-1382233787365-3:3:6 、persistent = false、type = null、priority = 4、groupID = null、groupSequence = 0、targetConsumerId = null、compressed = false、userID = null、content = null、marshalledProperties = null、dataStructure = null、redeliveryCounter = 0、サイズ= 0、プロパティ = {breadcrumbId=ID:myhost-57439-1382232345453-1:1:1:1:6、CamelJmsDeliveryMode=1}、readOnlyProperties = false、readOnlyBody = false、ドロップ可能 = false} ActiveMQMapMessage{ theTable = {cluster=x78} } | org.apache.camel.component.jms.JmsConfiguration | Camel (ラクダ) スレッド #2 - JmsConsumer[bar] 20:58:48,044 | デバッグ | 非アクティブなエントリ ID の削除: 8b0d77a3-afef-4612-a49f-22c1b81eb80e (20000 ミリ秒後にタイムアウト) | org.apache.camel.component.jms.reply.CorrelationTimeoutMap | Camel (キャメル) スレッド #9 - JmsReplyManagerTimeoutChecker[getInfo] 20:58:48,044 | 警告 | 相関 ID [8b0d77a3-afef-4612-a49f-22c1b81eb80e] の応答メッセージを 20000 ミリ秒待った後、タイムアウトが発生しました。ExchangeTimedOutException を (MessageId: ID: myhost-57439-1382232345453-1:1:1:1:5 on ExchangeId: ID-myhost-57640-1382233788284-0-2) に設定し、ルーティングを続行します。| | org.apache.camel.component.jms.reply.TemporaryQueueReplyManager | Camel (ラクダ) スレッド #9 - JmsReplyManagerTimeoutChecker[getInfo] 20: 58:48,045 | 警告 | JMS メッセージ リスナーの実行に失敗しました。原因: [org.apache.camel.RuntimeCamelException - org.apache.camel.ExchangeTimedOutException: OUT メッセージが受信されませんでした: 20000 ミリ秒以内に、correlationID の応答メッセージ: 8b0d77a3-afef-4612-a49f-22c1b81eb80e が受信されませんでした。Exchange[JmsMessage[JmsMessageID: ID:myhost-57439-1382232345453-1:1:1:1:5]]] | org.apache.camel.component.jms.EndpointMessageListener | Camel (camel) スレッド #4 - JmsConsumer[bar] org.apache.camel.RuntimeCamelException: org.apache.camel.ExchangeTimedOutException: OUT メッセージは受信されませんでした: 20000 ミリ秒以内に応答メッセージが返されます。 a49f-22c1b81eb80e 受信していません。Exchange[JmsMessage[JmsMessageID: ID:myhost-57439-1382232345453-1:1:1:1:5]] org.apache.camel.util.ObjectHelper. java.lang.Thread.run(Thread.java:662) の ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 原因: org.apache.camel.ExchangeTimedOutException: OUT メッセージが受信されませんでした: 20000 ミリ秒期限の返信相関 ID: 8b0d77a3-afef-4612-a49f-22c1b81eb80e のメッセージが受信されませんでした。Exchange[JmsMessage[JmsMessageID: ID:myhost-57439-1382232345453-1:1:1:1:5]] org.apache.camel.component.jms.reply.ReplyManagerSupport.processReply(ReplyManagerSupport.java:133) at org .apache.camel.component.jms.reply.TemporaryQueueReplyHandler.onTimeout(TemporaryQueueReplyHandler.java:61) org.apache.camel.component.jms.reply.CorrelationTimeoutMap.onEviction(CorrelationTimeoutMap.java:53) org.apache.camel .component.jms.reply.CorrelationTimeoutMap.onEviction(CorrelationTimeoutMap.java: