JMS doesnt work in global transaction with cachingconnectionfactory

时间秒杀一切 提交于 2019-12-11 09:25:31

问题


I am using IBM mq(p800-005-160516.2) and Spring JMS template to post messages to MQ.My application is having one database resource and one MQ resource in global transaction.Problem is that it fails if i configure CachingConnnectionFactory

public class Xa {
    public ConnectionFactory connectionFactory() throws Exception {

        AtomikosConnectionFactoryBean atomikosConnectionFactoryBean = new AtomikosConnectionFactoryBean();
        atomikosConnectionFactoryBean.setUniqueResourceName("pavan");
        Properties xaProperties = new Properties();
        xaProperties.setProperty("connectionNameList", hostName);
        xaProperties.setProperty("queueManager", queueManager);
        xaProperties.setProperty("channel", channel);
        xaProperties.setProperty("transportType", 1);

        atomikosConnectionFactoryBean.setXaProperties(xaProperties);
        atomikosConnectionFactoryBean.setXaConnectionFactoryClassName("com.ibm.mq.jms.MQXAConnectionFactory");
        return atomikosConnectionFactoryBean;

    }

    public CachingConnectionFactory cachingConnectionFactory() throws Exception{
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setSessionCacheSize(5);
        factory.setTargetConnectionFactory(connectionFactory());
        factory.setReconnectOnException(true);
        factory.afterPropertiesSet();
        return factory;
    }

    public static void main(String[] args) throws Exception {
        Xa b = new Xa();
        JmsTemplate jmsQueueTemplate = new JmsTemplate(b.cachingConnectionFactory());
        long sr = System.currentTimeMillis();
        IntStream.range(0, 1000).parallel().forEach(aa->{
        UserTransaction userTransaction = new UserTransactionImp();
        try {
        userTransaction.begin();
        jmsQueueTemplate.send(queueName, new MessageCreator() {
            @Override
            public Message createMessage(javax.jms.Session session)throws JMSException {
                TextMessage textMessage = session.createTextMessage();
                textMessage.setText("pavan"+aa);
                return textMessage;

            }});
         userTransaction.commit();
        } catch (Exception e) {
            try {
                userTransaction.rollback();
            } catch (Exception e1) {
                throw new RuntimeException(e1);
            }
            throw new RuntimeException(e);
        }
        });
        System.out.println("time taken "+(System.currentTimeMillis()-sr));
    }
}

This fails with an exception

    at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:487)
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:570)
    at 
    ... 23 common frames omitted
Caused by: com.atomikos.jms.AtomikosJMSException: error during enlist: Failed to suspend branch: XAResourceTransaction: 31302E3234362E38392E31362E746D30303032363030323933:31302E3234362E38392E31362E746D3337
    at com.atomikos.jms.AtomikosJMSException.throwAtomikosJMSException(AtomikosJMSException.java:55)
    at com.atomikos.jms.ConsumerProducerSupport.enlist(ConsumerProducerSupport.java:101)
    at com.atomikos.jms.AtomikosJmsMessageProducerProxy.send(AtomikosJmsMessageProducerProxy.java:69)
    at com.atomikos.jms.AtomikosJmsMessageProducerProxy.send(AtomikosJmsMessageProducerProxy.java:147)
    at org.springframework.jms.connection.CachedMessageProducer.send(CachedMessageProducer.java:181)
    at sun.reflect.GeneratedMethodAccessor68.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.jms.connection.CachedMessageProducer$Jms2MessageProducerInvocationHandler.invoke(CachedMessageProducer.java:293)
    at com.sun.proxy.$Proxy53.send(Unknown Source)
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:626)
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:597)
    at org.springframework.jms.core.JmsTemplate$4.doInJms(JmsTemplate.java:574)
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484)
    ... 25 common frames omitted
Caused by: com.atomikos.datasource.xa.session.InvalidSessionHandleStateException: Failed to suspend branch: XAResourceTransaction: 31302E3234362E38392E31362E746D30303032363030323933:31302E3234362E38392E31362E746D3337
    at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.transactionSuspended(BranchEnlistedStateHandler.java:117)
    at com.atomikos.datasource.xa.session.TransactionContext.transactionSuspended(TransactionContext.java:112)
    at com.atomikos.datasource.xa.session.SessionHandleState.notifyBeforeUse(SessionHandleState.java:184)
    at com.atomikos.jms.ConsumerProducerSupport.enlist(ConsumerProducerSupport.java:97)
    ... 37 common frames omitted
Caused by: javax.transaction.xa.XAException: The method 'xa_end' has failed with errorCode '-4'.
    at com.ibm.mq.jmqi.JmqiXAResource.end(JmqiXAResource.java:559)
    at com.atomikos.datasource.xa.XAResourceTransaction.xaSuspend(XAResourceTransaction.java:883)
    at com.atomikos.datasource.xa.session.BranchEnlistedStateHandler.transactionSuspended(BranchEnlistedStateHandler.java:113)
    ... 40 common frames omitted

any help would be much appreciated

This works fine with transaction template

public static void main(String[] args) throws Exception {
        TXTemplateExample b = new TXTemplateExample();
        JmsTemplate jmsQueueTemplate = new JmsTemplate(b.cachingConnectionFactory());
        jmsQueueTemplate.setSessionTransacted(true);
        setAtomikosProperties();
        long sr = System.currentTimeMillis();

        JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(60);
        jtaTransactionManager.setUserTransaction(userTransactionImp);
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        jtaTransactionManager.setTransactionManager(userTransactionManager );
        TransactionTemplate txTmp = new TransactionTemplate(jtaTransactionManager);
        LongStream.range(0, 10).parallel().forEach(index -> {
            txTmp.execute(new TransactionCallbackWithoutResult() {
                @Override
                public void doInTransactionWithoutResult(TransactionStatus status) {
                    try {
                        jmsQueueTemplate.send(queueName, (session) -> {
                            TextMessage msg = session.createTextMessage();
                            msg.setText("pavan");
                            return msg;
                        });
                    } catch (Exception e) {
                        status.setRollbackOnly();
                    }
                }
            });
        });    
    }

Whats wrong in creating usertransaction instead of using spring?

来源:https://stackoverflow.com/questions/46327445/jms-doesnt-work-in-global-transaction-with-cachingconnectionfactory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!