Spring Integration入站网关在队列为空时触发事件 [英] Spring integration inbound-gateway Fire an event when queue is empty
问题描述
我是新手,但是我会尽量保持警惕。
I'm a newbie around but I'll try to be consice.
{INPUT QUEUE}->[INBOUND-GATEWAY-1]-->[ROUTER]----------->(ACTIVATOR)<---------------
\ /
\-->{HOLD QUEUE}--->[INBOUND-GATEWAY-2]--^
我在这种情况下,我必须像前一种情况一样动态地改变流中的路由条件。来自队列的消息将发送到激活器进行处理,或者将另一个队列保留。在特定时间,我必须关闭INBOUND-GATEWAY-1,以便没有新消息进入流程,然后打开INBOUND-GATEWAY-2,以处理来自HOLD QUEUE的所有消息。一旦所有来自HOLD QUEUE的消息都被消耗掉,两个网关都必须像以前一样关闭/打开。这里的事情是我怎么知道什么时候HOLD QUEUE为空,所以我可以触发启动网关1的方法?
I'm having an scenario in which I have to dynamically change routing conditions in a flow like the former. Messages comming from a queue are sent to an activator to be processed, or another queue to be put on hold. At certain time, I have to close INBOUND-GATEWAY-1 so no new messages come into the flow, and open INBOUND-GATEWAY-2 to let all messages from HOLD QUEUE be processed. Once all messages from HOLD QUEUE were been consumed, both gateways must me closed/opened as they were before. The thing here is how could I know when HOLD QUEUE is empty so I could trigger a method in which gateway-1 could be started?
如果有人请,我将不胜感激可以帮助我。
I'd be grateful if somebody could help me.
预先感谢
推荐答案
经过一些调试和阅读,最后我找到了解决这个问题的方法。入站网关是JmsMessageDrivenEndpoint,它基于两个内部组件,即MessageListenerContainer和MessageListener。 MessageListenerContainer是负责调度MessageListener行为的负责人,因此,重写noMessageReceived和messageReceived并添加一些属性来控制所需的行为,我可以做到神奇。
After some debugging and reading, finally I came to a solution for this issue. An inbound-gateway is a JmsMessageDrivenEndpoint, based in two inner components, a MessageListenerContainer and a MessageListener. MessageListenerContainer is the one in charge at scheduling MessageListener behaviour so, overriding the noMessageReceived and messageReceived, and adding some attributes to control the desired behaviour, I could be able to do the "magic".
我的MessageListenerContainer实现就是这样。
My MessageListenerContainer implementation got like this.
public class ControlMessageListenerContainer extends DefaultMessageListenerContainer{
private JmsMessageDrivenEndpoint mainInputGateway;
private long timeOut;
private long lastTimeReceived;
public PassControlMessageListenerContainer() {
this.setAutoStartup(false);
}
@Override
public void start() throws JmsException {
/*When the container is started the lastTimeReceived is set to actial time*/
lastTimeReceived = (new Date()).getTime();
super.start();
}
@Override
protected void noMessageReceived(Object invoker, Session session) {
long actualTime = (new Date()).getTime();
if((actualTime - lastTimeReceived) >= timeOut
&& mainInputGateway != null && !mainInputGateway.isRunning()){
mainInputGateway.start();
}
super.noMessageReceived(invoker, session);
}
@Override
protected void messageReceived(Object invoker, Session session) {
/*lastTimeReceived is set again to actual time at new message arrive*/
lastTimeReceived = (new Date()).getTime();
super.messageReceived(invoker, session);
}
}
最后,spring bean配置如下所示:
And finally, the spring bean config get like this:
<bean id="listenerContainer"
class="org.merol.ControlMessageListenerContainer">
<property name="mainInputGateway" ref="mainGateway" />
<property name="destination" ref="onHoldQueue" />
<property name="timeOut" value="10000"/>
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<bean id="messageListener"
class="org.springframework.integration.jms.ChannelPublishingJmsMessageListener">
<property name="requestChannel" ref="outputChannel" />
</bean>
<bean id="inboundGateway"
class="org.springframework.integration.jms.JmsMessageDrivenEndpoint">
<constructor-arg name="listenerContainer" ref="listenerContainer" />
<constructor-arg name="listener" ref="messageListener" />
</bean>
希望这对其他人会有所帮助。
Hope this could be helpful for someone else.
感谢@Nicholas提供的线索。
Thanks to @Nicholas for the clues.
这篇关于Spring Integration入站网关在队列为空时触发事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!