Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.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
Java Spring与JMS+的集成;ActiveMQ:重新连接后,消息仍保留在JDBC消息存储中_Java_Activemq_Spring Integration_Spring Jms - Fatal编程技术网

Java Spring与JMS+的集成;ActiveMQ:重新连接后,消息仍保留在JDBC消息存储中

Java Spring与JMS+的集成;ActiveMQ:重新连接后,消息仍保留在JDBC消息存储中,java,activemq,spring-integration,spring-jms,Java,Activemq,Spring Integration,Spring Jms,我正在尝试使用Spring集成和ActiveMQ消息代理配置JMS。我的出站通道应由JDBC消息存储支持,以防止数据丢失,例如代理或我的应用程序脱机 到目前为止,我的配置似乎工作正常,但是JDBC消息存储的行为与我预期的不同。如果我断开代理的连接,发送到出站通道的消息将按预期的方式持久化,但在重新连接之后,它们将保留在DB中,不会发送到队列。然而,我在重新连接后发送的更多消息到达队列,如果我重新启动应用程序,持久化的消息也将最终发送 应用程序上下文.xml <?xml version="1

我正在尝试使用Spring集成和ActiveMQ消息代理配置JMS。我的出站通道应由JDBC消息存储支持,以防止数据丢失,例如代理或我的应用程序脱机

到目前为止,我的配置似乎工作正常,但是JDBC消息存储的行为与我预期的不同。如果我断开代理的连接,发送到出站通道的消息将按预期的方式持久化,但在重新连接之后,它们将保留在DB中,不会发送到队列。然而,我在重新连接后发送的更多消息到达队列,如果我重新启动应用程序,持久化的消息也将最终发送

应用程序上下文.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:jms="http://www.springframework.org/schema/jms"
   xmlns:int="http://www.springframework.org/schema/integration"
   xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
   xmlns:oxm="http://www.springframework.org/schema/oxm"
   xmlns:j2ee="http://www.springframework.org/schema/jee"
   xmlns:amq="http://activemq.apache.org/schema/core"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd
   http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
   http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd
   http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
   http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
   http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">

<!-- ActiveMQ Configuration -->
<jms:annotation-driven/>
<int:annotation-config/>

<!-- Factory for ActiveMQ connections from JNDI -->
<j2ee:jndi-lookup jndi-name="java:comp/env/jms/connectionFactory"
                  id="jmsConnectionFactory"
                  expected-type="org.apache.activemq.ActiveMQConnectionFactory"
                  proxy-interface="javax.jms.ConnectionFactory"
                  lookup-on-startup="false"
                  resource-ref="true"
                  cache="true"/>


<bean id="connectionFactory" class="org.apache.activemq.jms.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
    <property name="connectionFactory" ref="jmsConnectionFactory"/>
    <property name="maxConnections" value="8"/>
    <property name="reconnectOnException" value="true"/>
</bean>


<!-- JAXB-marshaller from spring-oxm used to handle XML-payload of messages -->
<oxm:jaxb2-marshaller id="jax2bMarshaller" context-path="de.br.ecomx"/>

<!-- message-converter -->
<bean id="messageConverter" class="org.springframework.jms.support.converter.MarshallingMessageConverter">
    <property name="marshaller" ref="jax2bMarshaller"/>
    <property name="unmarshaller" ref="jax2bMarshaller"/>
</bean>

<!-- Message Store implementation -->
<!-- Persists messages temporariliy in DB to prevent data loss on server-shutdown -->
<!-- Has to be injected specifically in Queue Channels -->
<bean id="store" class="org.springframework.integration.jdbc.store.JdbcChannelMessageStore">
    <property name="dataSource" ref="dataSource"/>
    <property name="channelMessageStoreQueryProvider">
        <bean id="queryProvider" class="org.springframework.integration.jdbc.store.channel.MySqlChannelMessageStoreQueryProvider"/>
    </property>
    <property name="usingIdCache" value="true"/>
    <property name="region" value="BWH"/>
    <property name="tablePrefix" value="BWH_"/>
</bean>

<!-- default poller for (non-message-driven) channel-adapters -->
<int:poller id="defaultPoller" default="true" fixed-delay="500">
    <int:transactional propagation="REQUIRED" isolation="DEFAULT" transaction-manager="transactionManager"/>
</int:poller>

<!-- LOGGING -->
<!--<int:logging-channel-adapter id="logger" level="DEBUG" log-full-message="true"/>-->


<!-- CHANNEL DEFINITIONS -->

<!-- intermediate channel for message enrichment -->
<int:channel id="output_enricher_channel"><int:queue/></int:channel>

<!-- general output-channel - specific channel is choosed by a router -->
<int:channel id="output_router"><int:queue/></int:channel>

<!-- channel definitions connected to consumer queues -->
<int:channel id="bwh_articleMasterData_input_channel"><int:queue/></int:channel>
<int:channel id="bwh_transferOrder_input_channel"><int:queue/></int:channel>
<!-- add your channel here... -->

<!-- channel definitions connected to producer queues -->
<int:channel id="ax_transferOrderPacked_input_channel"><int:queue message-store="store"/></int:channel>
<!-- add your channel here... -->


<!-- MESSAGE HANDLING -->

<!-- Enriches the 'messageId'-property of payload with 'id'-value from header and sends them to router -->
<int:enricher input-channel="output_enricher_channel" output-channel="output_router">
    <int:property name="messageId" expression="headers.id"/>
</int:enricher>

<!-- routing of outgoing messages to their type-specific channel -->
<int:payload-type-router input-channel="output_router">
    <int:mapping type="de.br.ecomx.TransferOrdersPacked" channel="ax_transferOrderPacked_input_channel"/>
</int:payload-type-router>


<!-- ENDPOINTS -->

<!-- endpoint configurations connecting queues with channels -->
<int-jms:message-driven-channel-adapter id="articleMasterDataConsumerChannelAdapter" connection-factory="connectionFactory"
                                        destination-name="${queue.bwh.articlemasterdata.in}" channel="bwh_articleMasterData_input_channel"
                                        message-converter="messageConverter" acknowledge="client" max-concurrent-consumers="10"
                                        auto-startup="false"/>
<int-jms:message-driven-channel-adapter id="transferOrderConsumerChannelAdapter" connection-factory="connectionFactory"
                                        destination-name="${queue.bwh.transferorder.in}" channel="bwh_transferOrder_input_channel"
                                        message-converter="messageConverter" acknowledge="client" max-concurrent-consumers="5"
                                        auto-startup="false"/>
<int-jms:outbound-channel-adapter id="transferOrderPackedProducerChannelAdapter" connection-factory="connectionFactory"
                                  destination-name="${queue.ax.transferorderpacked.in}" channel="ax_transferOrderPacked_input_channel"
                                  message-converter="messageConverter" delivery-persistent="true" session-transacted="true"
                                  auto-startup="false"/>

<!-- add your endpoint here... -->
<!-- REMEMBER: If auto-startup is set to false (which is recommended for all channel adapters) -->
<!--           the channel adapter has to be registered in ecomxConsumerChannelAdapterContainer below!!! -->


<!-- gateway definitions usually injected by producer-services and used to send messages to an outbound-channel-adapter -->
<int:gateway default-request-channel="output_enricher_channel" service-interface="de.lo.bwh.jms.gateway.EcomxProducerGateway"/>

<!-- connect endpoints with services -->
<int:service-activator input-channel="bwh_articleMasterData_input_channel" ref="ecomxArticleMasterDataConsumer"/>
<int:service-activator input-channel="bwh_transferOrder_input_channel" ref="ecomxTransferOrderConsumer"/>


<!-- container for endpoints used for start / stop all registered consumers / producers at once -->
<bean id="ecomxConsumerChannelAdapterContainer" class="de.lo.bwh.jms.EcomxConsumerChannelAdapterContainer">
    <property name="endpoints">
        <list value-type="org.springframework.integration.jms.JmsMessageDrivenEndpoint">
            <ref bean="articleMasterDataConsumerChannelAdapter"/>
            <ref bean="transferOrderConsumerChannelAdapter"/>
        </list>
    </property>
</bean>

<bean id="ecomxProducerChannelAdapterContainer" class="de.lo.bwh.jms.EcomxProducerChannelAdapterContainer">
    <property name="endpoints">
        <list value-type="org.springframework.integration.endpoint.PollingConsumer">
            <ref bean="transferOrderPackedProducerChannelAdapter"/>
        </list>
    </property>
</bean>

</beans>
<Resource name="jms/connectionFactory"
        auth="Container"
        type="org.apache.activemq.ActiveMQConnectionFactory"
        description="JMS Connection Factory"
        factory="org.apache.activemq.jndi.JNDIReferenceFactory"
        brokerURL="tcp://my.url.net:61616"
        brokerName="myActiveMQBroker"/>

嗯,这不适用于回滚消息,因为
usingIdCache=“true”
。消息会返回到数据库,但它们不会被下一次
轮询拾取,因为它们的ID在内存
idCache

我们提供此建议以处理已处理或回滚的消息:

<int:transaction-synchronization-factory id="syncFactory">
    <int:after-commit expression="@store.removeFromIdCache(headers.id.toString())" />
    <int:after-rollback expression="@store.removeFromIdCache(headers.id.toString())"/>
</int:transaction-synchronization-factory>

...

<int:poller id="defaultPoller" default="true" fixed-delay="500">
    <int:transactional propagation="REQUIRED" isolation="DEFAULT" 
                       synchronization-factory="syncFactory" 
                       transaction-manager="transactionManager"/>
</int:poller>

...
独立于TX,结果消息id将从
idCache
中删除。在你的情况下,它将准备再进行一次投票

请参阅中的更多信息。而
JdbcChannelMessageStore#setUsingIdCache
上的JavaDocs也显示了同样的情况

<int:transaction-synchronization-factory id="syncFactory">
    <int:after-commit expression="@store.removeFromIdCache(headers.id.toString())" />
    <int:after-rollback expression="@store.removeFromIdCache(headers.id.toString())"/>
</int:transaction-synchronization-factory>

...

<int:poller id="defaultPoller" default="true" fixed-delay="500">
    <int:transactional propagation="REQUIRED" isolation="DEFAULT" 
                       synchronization-factory="syncFactory" 
                       transaction-manager="transactionManager"/>
</int:poller>