我正在使用spring-integration和ActiveMQ来集成主服务器和几个“客户端”应用程序。
主要目标是使用嵌入式ActiveMQ代理开发小型客户端,嵌入式代理由此客户端应用程序启动 以便从同一站点上的多个第三方应用程序接收JMS消息。客户端应用程序通过JMS连接与服务器连接 主要安装ActiveMQ服务器(这已经存在)。 我需要为客户端提供离线功能,这意味着如果客户端断开连接 应将从第三个客户端收到的消息存储在同一站点上,并在服务器再次联机时发送它们。 当没有涉及事务性时,所有这些似乎都正常工作,但我对spring-integration中配置的通道的事务边界有疑问。
主要流程是:
同一网站上的第三个客户 - >我们的网站应用程序客户 - >重新格式化消息并在messageTranslator
- >上添加信息存储在remoteChannel
- >发送到主服务器
这是我的网站客户端配置:
客户端应用中的嵌入式ActiveMQ代理:
<bean id="broker1" class="org.apache.activemq.xbean.BrokerFactoryBean">
<property name="config" value="classpath:activemq/activemq.xml" />
<property name="start" value="true" />
</bean>
连接工厂; remoteConnectionFactory
是与主服务器和队列定义的连接:
<!-- Local queue definitions -->
<bean id="localConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost"/>
</bean>
</property>
<property name="sessionCacheSize" value="10"/>
</bean>
<bean id="localEventQueue" class="org.apache.activemq.command.ActiveMQQueue" >
<constructor-arg value="event.client"/>
</bean>
<!-- Remote(Server) queue definitions -->
<bean id="remoteConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://192.168.0.125:62626"/>
</bean>
</property>
<property name="sessionCacheSize" value="10"/>
</bean>
<bean id="remoteQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="remote.event"/>
</bean>
本地流程,在同一个远程站点上:
<!-- local process -->
<int:channel id="transformChannel" >
<int:queue />
</int:channel>
<int-jms:message-driven-channel-adapter
id="jmsEventsFromClient"
connection-factory="localConnectionFactory"
destination="localEventQueue"
channel="transformChannel"
concurrent-consumers="4"
auto-startup="true"/>
<!-- Transforms the message from clients to a standard messages that server knows-->
<int:service-activator input-channel="transformChannel"
ref="messageTranslator"
output-channel="remoteChannel" >
<int:poller fixed-delay="500">
</int:poller>
</int:service-activator>
<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:channel id="remoteChannel" >
<int:queue message-store="store" />
</int:channel>
<!-- local file database with HSQL store of the remotechannel -->
<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.HsqlChannelMessageStoreQueryProvider"/>
</property>
<property name="usingIdCache" value="true"/>
</bean>
发送到远程队列:
<!-- the message is send to the remote server -->
<int-jms:outbound-channel-adapter id="remoteJms"
connection-factory="remoteConnectionFactory"
destination="remoteQueue"
channel="remoteChannel"
session-transacted="true"
auto-startup="true">
<int:poller fixed-delay="500">
<int:transactional propagation="REQUIRED"
isolation="DEFAULT"
synchronization-factory="syncFactory"
transaction-manager="transactionManager"/>
</int:poller>
</int-jms:outbound-channel-adapter>
当没有配置JTA事务管理器且remoteJms
不是session-transacted
时,一切正常,即使我模拟离线情况,消息也正确地存储在store
上,当与服务器的连接再次生效(remoteJms
)时,消息将正确发送。
但是,当配置JTA事务管理器(atomikos)并且ActiveMQ主服务器关闭时,消息不会存储在store
上。我认为只要remoteJms
中的标记收到消息就会开始新的交易,但这种情况不会发生,它从jmsEventsFromClient
到jmsOut
的整个过程看起来像是一个单个事务并因remoteJms
已关闭而失败。
我想要的是有2个交易,第一个应该在eventQueue
收到消息时开始,当消息留在remoteChannel
时结束,第二个应该在邮件是从remoteChannel
获取的,并将其保留在remoteJms
上。
感谢您的意见和帮助。
编辑
仅当远程服务器关闭时才会发生这种情况,并且消息已从store
中删除,但这是我不想要的。
添加日志错误。
2015-06-29 16:39:16.859 INFO 4982 --- [ask-scheduler-4] c.atomikos.jdbc.AbstractDataSourceBean : AtomikosDataSoureBean 'dataSource': getConnection ( null )...
2015-06-29 16:39:16.859 INFO 4982 --- [ask-scheduler-4] c.atomikos.jdbc.AbstractDataSourceBean : AtomikosDataSoureBean 'dataSource': init...
2015-06-29 16:39:16.859 INFO 4982 --- [ask-scheduler-4] c.a.icatch.imp.CompositeTransactionImp : addParticipant ( XAResourceTransaction: 7472616E73616374696F6E4D616E6167657230303038303030303430:7472616E73616374696F6E4D616E616765723830 ) for transaction transactionManager0008000040
2015-06-29 16:39:16.859 INFO 4982 --- [ask-scheduler-4] c.a.datasource.xa.XAResourceTransaction : XAResource.start ( 7472616E73616374696F6E4D616E6167657230303038303030303430:7472616E73616374696F6E4D616E616765723830 , XAResource.TMNOFLAGS ) on resource dataSource represented by XAResource instance org.hsqldb.jdbc.pool.JDBCXAResource@55f823a3
2015-06-29 16:39:16.859 INFO 4982 --- [ask-scheduler-4] c.a.icatch.imp.CompositeTransactionImp : registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@c85d8b3 ) for transaction transactionManager0008000040
2015-06-29 16:39:16.859 INFO 4982 --- [ask-scheduler-4] c.atomikos.jdbc.AtomikosConnectionProxy : atomikos connection proxy for org.hsqldb.jdbc.pool.JDBCXAConnectionWrapper@731d1112: calling prepareStatement(SELECT COUNT(MESSAGE_ID) from INT_CHANNEL_MESSAGE where GROUP_KEY=? and REGION=?)...
hi message: una cadena
2015-06-29 16:39:17.820 INFO 4982 --- [ask-scheduler-9] c.atomikos.jdbc.AbstractDataSourceBean : AtomikosDataSoureBean 'dataSource': getConnection ( null )...
2015-06-29 16:39:17.820 INFO 4982 --- [ask-scheduler-9] c.atomikos.jdbc.AbstractDataSourceBean : AtomikosDataSoureBean 'dataSource': init...
2015-06-29 16:39:25.093 WARN 4982 --- [0.1:57663@61616] o.a.a.b.TransportConnection.Transport : Transport Connection to: tcp://192.168.0.125:57663 failed: java.io.EOFException
2015-06-29 16:39:27.145 WARN 4982 --- [ Atomikos:1] c.a.icatch.imp.ActiveStateHandler : Timeout/setRollbackOnly of ACTIVE coordinator !
2015-06-29 16:39:47.821 WARN 4982 --- [ask-scheduler-9] com.atomikos.jdbc.AtomikosSQLException : Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
2015-06-29 16:39:47.822 INFO 4982 --- [ask-scheduler-4] c.a.icatch.imp.CompositeTransactionImp : registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@c85d8b3 ) for transaction transactionManager0008000040
2015-06-29 16:39:47.822 INFO 4982 --- [ask-scheduler-4] c.atomikos.jdbc.AtomikosConnectionProxy : atomikos connection proxy for org.hsqldb.jdbc.pool.JDBCXAConnectionWrapper@731d1112: calling prepareStatement(SELECT COUNT(MESSAGE_ID) from INT_CHANNEL_MESSAGE where GROUP_KEY=? and REGION=?)...
2015-06-29 16:39:47.823 INFO 4982 --- [ask-scheduler-4] c.a.icatch.imp.CompositeTransactionImp : registerSynchronization ( com.atomikos.jdbc.AtomikosConnectionProxy$JdbcRequeueSynchronization@c85d8b3 ) for transaction transactionManager0008000040
2015-06-29 16:39:47.823 INFO 4982 --- [ask-scheduler-4] c.atomikos.jdbc.AtomikosConnectionProxy : atomikos connection proxy for org.hsqldb.jdbc.pool.JDBCXAConnectionWrapper@731d1112: calling prepareStatement(SELECT INT_CHANNEL_MESSAGE.MESSAGE_ID, INT_CHANNEL_MESSAGE.MESSAGE_BYTES from INT_CHANNEL_MESSAGE where INT_CHANNEL_MESSAGE.GROUP_KEY = ? and INT_CHANNEL_MESSAGE.REGION = ? order by CREATED_DATE, MESSAGE_SEQUENCE LIMIT 1)...
2015-06-29 16:39:47.823 INFO 4982 --- [ask-scheduler-4] c.atomikos.jdbc.AtomikosConnectionProxy : atomikos connection proxy for org.hsqldb.jdbc.pool.JDBCXAConnectionWrapper@731d1112: close()...
2015-06-29 16:39:47.823 INFO 4982 --- [ask-scheduler-4] c.a.datasource.xa.XAResourceTransaction : XAResource.end ( 7472616E73616374696F6E4D616E6167657230303038303030303430:7472616E73616374696F6E4D616E616765723830 , XAResource.TMSUCCESS ) on resource dataSource represented by XAResource instance org.hsqldb.jdbc.pool.JDBCXAResource@55f823a3
2015-06-29 16:39:47.823 INFO 4982 --- [ask-scheduler-4] c.a.icatch.imp.CompositeTransactionImp : commit() done (by application) of transaction transactionManager0008000040
2015-06-29 16:39:47.824 INFO 4982 --- [ask-scheduler-4] c.a.datasource.xa.XAResourceTransaction : XAResource.prepare ( 7472616E73616374696F6E4D616E6167657230303038303030303430:7472616E73616374696F6E4D616E616765723830 ) returning OK on resource dataSource represented by XAResource instance org.hsqldb.jdbc.pool.JDBCXAResource@55f823a3
2015-06-29 16:39:47.824 INFO 4982 --- [ask-scheduler-4] c.a.datasource.xa.XAResourceTransaction : XAResource.rollback ( 7472616E73616374696F6E4D616E6167657230303038303030303430:7472616E73616374696F6E4D616E616765723830 ) on resource dataSource represented by XAResource instance org.hsqldb.jdbc.pool.JDBCXAResource@55f823a3
2015-06-29 16:39:47.825 ERROR 4982 --- [ask-scheduler-4] o.s.integration.handler.LoggingHandler : org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1024)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:521)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy85.call(Unknown Source)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:298)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:292)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.transaction.RollbackException: Prepare: NO vote
at com.atomikos.icatch.jta.TransactionImp.rethrowAsJtaRollbackException(TransactionImp.java:66)
at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:206)
at com.atomikos.icatch.jta.TransactionManagerImp.commit(TransactionManagerImp.java:436)
at com.atomikos.icatch.jta.UserTransactionManager.commit(UserTransactionManager.java:177)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1021)
... 22 more
Caused by: com.atomikos.icatch.RollbackException: Prepare: NO vote
at com.atomikos.icatch.imp.ActiveStateHandler.prepare(ActiveStateHandler.java:231)
at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:681)
at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:970)
at com.atomikos.icatch.imp.CompositeTerminatorImp.commit(CompositeTerminatorImp.java:82)
at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:336)
at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:190)
... 25 more
2015-06-29 16:39:47.825 ERROR 4982 --- [ask-scheduler-9] o.s.integration.handler.LoggingHandler : org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'remoteChannel'; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.atomikos.jdbc.AtomikosSQLException: Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:292)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:239)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:95)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:248)
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:171)
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:119)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:105)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.endpoint.PollingConsumer.handleMessage(PollingConsumer.java:74)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:219)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:55)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:149)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:146)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:298)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:292)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.atomikos.jdbc.AtomikosSQLException: Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:630)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:909)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:970)
at org.springframework.integration.jdbc.store.JdbcChannelMessageStore.addMessageToGroup(JdbcChannelMessageStore.java:422)
at org.springframework.integration.store.MessageGroupQueue.doOffer(MessageGroupQueue.java:329)
at org.springframework.integration.store.MessageGroupQueue.put(MessageGroupQueue.java:274)
at org.springframework.integration.store.MessageGroupQueue.put(MessageGroupQueue.java:48)
at org.springframework.integration.channel.QueueChannel.doSend(QueueChannel.java:92)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:277)
... 28 more
Caused by: com.atomikos.jdbc.AtomikosSQLException: Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.
at com.atomikos.jdbc.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:46)
at com.atomikos.jdbc.AbstractDataSourceBean.throwAtomikosSQLException(AbstractDataSourceBean.java:90)
at com.atomikos.jdbc.AbstractDataSourceBean.throwAtomikosSQLException(AbstractDataSourceBean.java:85)
at com.atomikos.jdbc.AbstractDataSourceBean.getConnection(AbstractDataSourceBean.java:347)
at com.atomikos.jdbc.AbstractDataSourceBean.getConnection(AbstractDataSourceBean.java:394)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
... 37 more
答案 0 :(得分:0)
我想我已经明白了 - 尝试在从商店支持的receive-timeout="0"
拉出的轮询器上设置QueueChannel
。