簡體   English   中英

使用 spring 集成消息驅動的通道適配器配置 AtomikosConnectionFactoryBean

[英]Configuring AtomikosConnectionFactoryBean with spring integration message driven channel adapter

我正在嘗試使用 Atomikos 進行 Spring 集成項目的分布式事務管理。 如果我嘗試在消息驅動的通道適配器中使用 AtomikosConnectionFactoryBean 作為連接工廠,我會遇到問題。

我收到以下錯誤:

Caused by: com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ0018: Failed to connect to queue manager 'NYHUB6S' with connection mode 'Client' and host name 'nyhub6s.us.ml.com'.
    at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:608) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:236) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:430) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.wmq.internal.WMQXAConnection.<init>(WMQXAConnection.java:70) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.wmq.factories.WMQXAConnectionFactory.createV7ProviderConnection(WMQXAConnectionFactory.java:190) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.wmq.factories.WMQConnectionFactory.createProviderConnection(WMQConnectionFactory.java:6210) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.wmq.factories.WMQXAConnectionFactory.createProviderXAConnection(WMQXAConnectionFactory.java:102) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.jms.admin.JmsConnectionFactoryImpl.createXAConnectionInternal(JmsConnectionFactoryImpl.java:371) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.mq.jms.MQXAQueueConnectionFactory.createXAQueueConnection(MQXAQueueConnectionFactory.java:144) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.mq.jms.MQXAQueueConnectionFactory.createXAConnection(MQXAQueueConnectionFactory.java:98) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.atomikos.datasource.xa.jms.JmsTransactionalResource.refreshXAConnection(JmsTransactionalResource.java:73) ~[transactions-jta-4.0.4.jar:na]
    ... 17 common frames omitted
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2009' ('MQRC_CONNECTION_BROKEN').
    at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:223) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    ... 26 common frames omitted
Caused by: com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009;AMQ9204: Connection to host 'nyhub6s.us.ml.com(1467)' rejected. [1=com.ibm.mq.jmqi.JmqiException[CC=2;RC=2009],3=nyhub6s.us.ml.com(1467),5=RemoteRcvThread.run]
    at com.ibm.mq.jmqi.remote.internal.RemoteFAP.jmqiConnect(RemoteFAP.java:2072) ~[com.ibm.mq.jmqi-7.0.1.8.jar:7.0.1.8 - k701-108-120201]
    at com.ibm.mq.jmqi.remote.internal.RemoteFAP.jmqiConnect(RemoteFAP.java:1286) ~[com.ibm.mq.jmqi-7.0.1.8.jar:7.0.1.8 - k701-108-120201]
    at com.ibm.msg.client.wmq.internal.WMQConnection.<init>(WMQConnection.java:345) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    ... 25 common frames omitted
com.ibm.mq.jmqi.JmqiException: CC=2;RC=2009
    at com.ibm.mq.jmqi.remote.internal.RemoteRcvThread.run(RemoteRcvThread.java:362) ~[com.ibm.mq.jmqi-7.0.1.8.jar:7.0.1.8 - k701-108-120201]
    at com.ibm.msg.client.commonservices.workqueue.WorkQueueItem.runTask(WorkQueueItem.java:209) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.commonservices.workqueue.SimpleWorkQueueItem.runItem(SimpleWorkQueueItem.java:100) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.commonservices.workqueue.WorkQueueItem.run(WorkQueueItem.java:224) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.commonservices.workqueue.WorkQueueManager.runWorkQueueItem(WorkQueueManager.java:298) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]
    at com.ibm.msg.client.commonservices.j2se.workqueue.WorkQueueManagerImplementation$ThreadPoolWorker.run(WorkQueueManagerImplementation.java:1220) ~[com.ibm.mqjms-7.0.1.1.jar:7.0.1.1 - k701-101-091116]

我的 spring 集成和 Atomikos 配置如下:

<bean id="xaConnectionFactory" class="com.ibm.mq.jms.MQXAQueueConnectionFactory">               
        <property name="hostName">
            <value>${receiving.queue.hostname}</value>
        </property>
        <property name="port">
            <value>${receiving.queue.port}</value>
        </property>
        <property name="queueManager">
            <value>${receiving.queue.manager}</value>
        </property>
        <property name="channel">
            <value>${receiving.queue.channel}</value>
        </property>
        <property name="transportType">
            <value>1</value>
        </property>
    </bean> 

    <bean id="jmsQueueConnectionFactory"
        class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
        <property name="targetConnectionFactory" ref="xaConnectionFactory" />       
        <property name="username" value="${mqSeriesUserName}" />
        <property name="password" value="${mqSeriesPassword}" />
    </bean> 

    <!-- lets wrap in a pool to avoid creating a connection per send -->
    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
        <property name="targetConnectionFactory" ref="jmsQueueConnectionFactory"/>
        <property name="sessionCacheSize" value="5"/>
        <property name="reconnectOnException" value="true"/>
    </bean>

    <!-- 
    <bean id="requestQueue1" class="com.ibm.mq.jms.MQQueue">
        <property name="baseQueueName" value="${receiving.queue1}" />   
        JMSC.MQJMS_CLIENT_NONJMS_MQ is one
        <property name="targetClient" value="1" />  
    </bean>

    <bean id="requestQueue2" class="com.ibm.mq.jms.MQQueue">
        <property name="baseQueueName" value="${receiving.queue2}" />   
        JMSC.MQJMS_CLIENT_NONJMS_MQ is one
        <property name="targetClient" value="1" />  
    </bean>

    <bean id="requestQueue3" class="com.ibm.mq.jms.MQQueue">
        <property name="baseQueueName" value="${receiving.queue3}" />   
        JMSC.MQJMS_CLIENT_NONJMS_MQ is one
        <property name="targetClient" value="1" />  
    </bean> -->

    <!--  XA related changes -->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
        <property name="transactionTimeout" value="120"/> 
        <property name="forceShutdown">
            <value>false</value>
        </property>
    </bean>

    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" >
    </bean>

    <bean id="atomikos_ConnectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean"> 
        <property name="xaConnectionFactory" ref="xaConnectionFactory"/> 
        <property name="uniqueResourceName" value="MQSeries_XA_RMI"/>
        <property name="poolSize" value="2" />
        <property name="maxPoolSize" value="10" />
        <property name="maxIdleTime" value="15" />      
    </bean>

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
        <property name="transactionManager"> <ref bean ="atomikosTransactionManager"/></property>
        <property name="userTransaction"> <ref bean="atomikosUserTransaction" /></property>
    </bean>

<beans profile="SINGLE_REQUEST_Q">
        <jms:message-driven-channel-adapter id="exch" destination="requestQueue"    channel="jmsInChannel" 
                        transaction-manager="transactionManager" acknowledge="transacted" connection-factory="atomikos_ConnectionFactory" />
        <bean id="requestQueue" class="com.ibm.mq.jms.MQQueue">
                <property name="baseQueueName" value="${receiving.queue.${exch}}" />    
                <property name="targetClient" value="1" />
        </bean>             
    </beans>

我需要將帶有用戶 ID 和密碼的緩存工廠引用傳遞給AtomikosConnectionFactoryBean但除了MQXAQueueConnectionFactory之外,它不需要任何東西。 請讓我知道您將UserCredentialsConnectionFactoryAdapterCachingConnectionFactoryAtomikosConnectionFactoryBean bean 的意見或AtomikosConnectionFactoryBean

嘗試在UserCredentialsConnectionFactoryAdapterCachingConnectionFactory<jms:message-driven-channel-adapter>使用atomikos_ConnectionFactory 像這樣的東西:

 <bean id="jmsQueueConnectionFactory"
        class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
        <property name="targetConnectionFactory" ref="atomikos_ConnectionFactory" />       
        <property name="username" value="${mqSeriesUserName}" />
        <property name="password" value="${mqSeriesPassword}" />
    </bean> 

...

 <jms:message-driven-channel-adapter 
       transaction-manager="transactionManager" connection-factory="connectionFactory" />

一個解決方案是創建一個擴展 com.ibm.mq.jms.MQXAQueueConnectionFactory 的類並使用這個類代替 com.ibm.mq.jms.MQXAQueueConnectionFactory

當您擴展 MQXAConnectionFactory 時,定義屬性 username 和 password(以及 setter)並覆蓋方法 createXAConnection() 並創建這樣的上下文

public class MyMQXAConnectionFactory extends MQXAConnectionFactory {

private String username;
private String password;

public void setUsername(String username) {
    this.username = username;
}

public void setPassword(String password) {
    this.password = password;
}

/**
 * create a connection with a context user/password if username is present
 * @return
 * @throws JMSException
 */
@Override
public XAConnection createXAConnection() throws JMSException {
    if(username != null) {
        createXAContext(this.username, this.password);
    }
    return super.createXAConnection(this.username, this.password);
}}

在您可以像這樣在 xml 配置文件中引用新類之后

<bean id="xaConnectionFactory" class="my.package.MyMQXAConnectionFactory">               
    <property name="hostName">
        <value>${receiving.queue.hostname}</value>
    </property>
    <property name="port">
        <value>${receiving.queue.port}</value>
    </property>
    <property name="queueManager">
        <value>${receiving.queue.manager}</value>
    </property>
    <property name="channel">
        <value>${receiving.queue.channel}</value>
    </property>
    <property name="transportType">
        <value>1</value>
    </property>
    <property name="username" >
        <value>${usernmame}/<value
    </property>
    <property name="password" >
        <value>${password}</value>
    </password>
</bean> 

之后,您不需要 UserCredentialsConnectionFactoryAdapter 或 CachingConnectionFactory 並且您可以立即傳遞您的 XA bean

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM