Spring-JMS OutboundGateway не принимает ответ
Может быть, это глупый вопрос, и я упускаю что-то очень простое, но я действительно застрял. Я использую ActiveMQ 5.5.1 и SI 2.1.4
Мои фрагменты конфигов:
--- --- SERVER
<beans:bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<beans:property name="brokerURL" value="tcp://localhost:61616" />
</beans:bean>
<beans:bean id="listQueue" class="org.apache.activemq.command.ActiveMQQueue">
<beans:constructor-arg name="name" value="LIST_QUEUE"/>
</beans:bean>
<beans:bean id="replyListQueue" class="org.apache.activemq.command.ActiveMQQueue">
<beans:constructor-arg name="name" value="REPLY_LIST_QUEUE"/>
</beans:bean>
<channel id="replyListChannel"/>
<channel id="listIn" />
<channel id="listDriver"/>
<channel id="listStock"/>
<jms:inbound-channel-adapter id="listInJms"
connection-factory="connectionFactory"
destination="listQueue"
channel="listIn"
auto-startup="true">
<poller fixed-rate="3000"/>
</jms:inbound-channel-adapter>
<header-value-router input-channel="listIn" header-name="List"
default-output-channel="nullChannel">
<mapping value="Driver" channel="listDriver" />
<mapping value="Stock" channel="listStock" />
</header-value-router>
<jms:outbound-channel-adapter connection-factory="connectionFactory"
channel="replyListChannel"
destination="replyListQueue"
auto-startup="true">
</jms:outbound-channel-adapter>
--- --- КЛИЕНТ
<beans:bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<beans:property name="brokerURL" value="tcp://localhost:61616" />
</beans:bean>
<beans:bean id="requestListQueue" class="org.apache.activemq.command.ActiveMQQueue">
<beans:constructor-arg value="LIST_QUEUE"/>
</beans:bean>
<beans:bean id="replyListQueue" class="org.apache.activemq.command.ActiveMQQueue">
<beans:constructor-arg value="REPLY_LIST_QUEUE"/>
</beans:bean>
<channel id="requestListChannel">
<queue capacity="20"/>
</channel>
<channel id="listStockChannel">
<queue capacity="20"/>
</channel>
<channel id="listDriverChannel">
<queue capacity="20"/>
</channel>
<channel id="replyListChannel"/>
<jms:outbound-gateway id="outListGW"
connection-factory="connectionFactory"
request-destination="requestListQueue"
request-channel="requestListChannel"
reply-destination="replyListQueue"
reply-channel="replyListChannel"
reply-timeout="20000"
receive-timeout="20000">
<poller fixed-rate="5000" />
</jms:outbound-gateway>
<header-value-router input-channel="replyListChannel" header-name="List"
default-output-channel="nullChannel">
<mapping value="Driver" channel="listDriverChannel" />
<mapping value="Stock" channel="listStockChannel" />
</header-value-router>
Затем в каком-то месте кода я делаю запрос вручную и слушаю канал ответа:
public static DriverList requestDriverList() {
Message<String> ldrm = MessageBuilder.withPayload("DriverList request").
setHeader("List", "Driver").build();
try {
ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath:dmclnt/config/integ-context.xml");
MessageChannel requestListChannel =
ctx.getBean("requestListChannel", MessageChannel.class);
QueueChannel listDriverChannel =
ctx.getBean("listDriverChannel", QueueChannel.class);
logger.info("Request for DriverList is sent to channel");
Message dlm = listDriverChannel.receive(20000);
String xmlDL = (String)dlm.getPayload();
JAXBContext jaxbctx = JAXBContext.newInstance(DriverList.class);
DriverList dl = (DriverList)jaxbctx.createUnmarshaller().
unmarshal(newStringReader(xmlDL));
logger.info("DriverList objct unmarshalled: "+dl.toString());
return dl;
} catch (JAXBException e) {
logger.error("Error converting xmlDriverList to DriverList object",e);
return null;
} catch (RuntimeException e){
logger.error(e);
return null;
}
}
Но я получаю
"MessageTimeoutException: failed to receive JMS response within timeout of: 20000ms"
все время. Когда я просматриваю журнал сервера, я вижу, что ответ с правильной полезной нагрузкой был успешно отправлен с сервера на клиент, и, кроме того, ответ помещается в REPLY_LIST_QUEUE, как я вижу в консоли администратора ActiveMQ. И больше ничего не происходит! Сообщение в REPLY_LIST_QUEUE With_Correct_Payload находится в состоянии ожидания и постановки в очередь в этой очереди. Нет сообщений снятых с производства. Похоже, JmsOutboundGateway не принимает сообщения из очереди-получателя ответа, хотя задержка receive-timeout="20000ms" более чем достаточна для получения ответа. Что я делаю неправильно?
1 ответ
Это связано с тем, что исходящий шлюз имеет некоторые ожидания относительно корреляции сообщений. Я думаю, что с вашей конфигурацией шлюз ожидает, что сервер вернет идентификатор входящего сообщения в идентификаторе корреляции. Он использует селектор сообщений для получения своих ответов.
Если вы используете входящий шлюз на сервере, он будет обрабатывать корреляцию для вас.
Есть ли какая-то особая причина, по которой вы решили использовать на сервере адаптеры дискретных каналов вместо входящего шлюза?
Возможно, вы захотите перейти на 2.2.3, где были сделаны некоторые улучшения в исходящем шлюзе (но он все еще требует правильной корреляции со стороны сервера).
РЕДАКТИРОВАТЬ: за ваш комментарий ниже...
Если вы хотите использовать вместо этого пару адаптеров, в текущей конфигурации вам придется использовать <header-enricher/>
скопировать входящий заголовок jms_messageid
в jms_correlationId
,
В качестве альтернативы на стороне клиента (исходящий шлюз) установите correlation-key
приписывать JmsCorrelationId
, Это заставит шлюз заполнять этот заголовок в исходящем сообщении, и вам ничего не понадобится на стороне сервера.