Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Activemq 消息驱动通道适配器在应用程序上下文启动后丢弃第一条消息,除非延迟调用send_Activemq_Spring Integration_Spring Jms - Fatal编程技术网

Activemq 消息驱动通道适配器在应用程序上下文启动后丢弃第一条消息,除非延迟调用send

Activemq 消息驱动通道适配器在应用程序上下文启动后丢弃第一条消息,除非延迟调用send,activemq,spring-integration,spring-jms,Activemq,Spring Integration,Spring Jms,我有一个针对Spring集成配置的集成测试,它使用来自JMS主题的消息和持久订阅。对于测试,我使用ActiveMQ而不是Tibco EMS。 我遇到的问题是,在测试方法开始时,我必须使用睡眠调用延迟向端点发送第一条消息。否则,消息将被丢弃。 如果我删除持久订阅和选择器的设置,那么第一条消息可以立即发送,不会有延迟。 我想摆脱不可靠的睡眠。在发送消息之前,是否有方法检查端点是否已完全设置? 下面是配置 谢谢你的帮助 <int-jms:message-driven-channel-ad

我有一个针对Spring集成配置的集成测试,它使用来自JMS主题的消息和持久订阅。对于测试,我使用ActiveMQ而不是Tibco EMS。 我遇到的问题是,在测试方法开始时,我必须使用睡眠调用延迟向端点发送第一条消息。否则,消息将被丢弃。 如果我删除持久订阅和选择器的设置,那么第一条消息可以立即发送,不会有延迟。 我想摆脱不可靠的睡眠。在发送消息之前,是否有方法检查端点是否已完全设置? 下面是配置

谢谢你的帮助

    <int-jms:message-driven-channel-adapter
        id="myConsumer" connection-factory="myCachedConnectionFactory"
        destination="myTopic" channel="myChannel" error-channel="errorChannel"
        pub-sub-domain="true" subscription-durable="true"
        durable-subscription-name="testDurable"
        selector="..."
        transaction-manager="emsTransactionManager" auto-startup="false"/>

如果您使用干净的嵌入式activemq进行测试,则在建立订阅之前,订阅的持久性是无关的。所以你别无选择,只能等到那一刻

您可以通过发送一系列启动消息来避免睡眠,并且只在收到最后一条消息时启动真正的测试

编辑

我忘了在
DefaultMessageListenerContainer
上有一个方法
isRegisteredWithDestination()

Javadocs

/**
 * Return whether at least one consumer has entered a fixed registration with the
 * target destination. This is particularly interesting for the pub-sub case where
 * it might be important to have an actual consumer registered that is guaranteed
 * not to miss any messages that are just about to be published.
 * <p>This method may be polled after a {@link #start()} call, until asynchronous
 * registration of consumers has happened which is when the method will start returning
 * {@code true} &ndash; provided that the listener container ever actually establishes
 * a fixed registration. It will then keep returning {@code true} until shutdown,
 * since the container will hold on to at least one consumer registration thereafter.
 * <p>Note that a listener container is not bound to having a fixed registration in
 * the first place. It may also keep recreating consumers for every invoker execution.
 * This particularly depends on the {@link #setCacheLevel cache level} setting:
 * only {@link #CACHE_CONSUMER} will lead to a fixed registration.
 */

您必须共享用于测试的测试用例和整个配置。您可能真的很早就发送了一条消息,并且只在发送之后执行Subscription,所以我看到auto startup=false。如果你在发送消息后将其切换为true,这可能会产生影响。我希望有一种不同于发送实际消息的方式。请参阅我答案的编辑。顺便说一句,您不应该在新答案中添加澄清,而应该编辑您的问题。我使用的条件“amqBroker.getRegionBroker().getDestinationMap().containsKey(myTopic)”似乎有效,而不是使用isRegisteredWithDestination()。amqBroker是BrokerService bean。
/**
 * Blocks until the listener container has subscribed; if the container does not support
 * this test, or the caching mode is incompatible, true is returned. Otherwise blocks
 * until timeout milliseconds have passed, or the consumer has registered.
 * @see DefaultMessageListenerContainer#isRegisteredWithDestination()
 * @param timeout Timeout in milliseconds.
 * @return True if a subscriber has connected or the container/attributes does not support
 * the test. False if a valid container does not have a registered consumer within
 * timeout milliseconds.
 */
private static boolean waitUntilRegisteredWithDestination(SubscribableJmsChannel channel, long timeout) {
    AbstractMessageListenerContainer container =
            (AbstractMessageListenerContainer) new DirectFieldAccessor(channel).getPropertyValue("container");
    if (container instanceof DefaultMessageListenerContainer) {
        DefaultMessageListenerContainer listenerContainer =
            (DefaultMessageListenerContainer) container;
        if (listenerContainer.getCacheLevel() != DefaultMessageListenerContainer.CACHE_CONSUMER) {
            return true;
        }
        while (timeout > 0) {
            if (listenerContainer.isRegisteredWithDestination()) {
                return true;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) { }
            timeout -= 100;
        }
        return false;
    }
    return true;
}