activeMQ 不参与 Weblogic XA 事务
activeMQ does not participate in Weblogic XA transactions
我尝试让涉及 jdbc 的 XA 事务和在部署到 Weblogic 的 Spring webapp 中工作的 jms 数据源。
使用本地 Atomikos TransactionManager,这有效 - 我在 ActiveMQ 中看到 XA 调试消息,并且内容保持一致。然而,在 Weblogic 中,数据库和 ActiveMQ 在事务上并不一致。
我在 Weblogic 中添加了一个外部 JMS 服务器
JNDI 初始上下文工厂:
org.apache.activemq.jndi.ActiveMQInitialContextFactory
JNDI 连接URL:
tcp://localhost:61616
JNDI 属性:
connectionFactoryNames=XAConnectionFactory
我向该服务器添加了一个 ConnectionFactory(远程 JNDI 名称 = XAConnectionFactory)。查找有效,到目前为止一切顺利。
在我的代码中,这是我设置 Spring JTA 的方式:
@Override
@Bean
@Profile(AppConfig.PROFILE_WEBLOGIC)
public JtaTransactionManager transactionManager()
{
WebLogicJtaTransactionManager tx = new WebLogicJtaTransactionManager();
tx.afterPropertiesSet();
return tx;
}
这是我的 JMS 配置:
@Bean
@Profile(AppConfig.PROFILE_WEBLOGIC)
public ConnectionFactory connectionFactory()
{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, env.getProperty(Context.INITIAL_CONTEXT_FACTORY));
props.setProperty(Context.PROVIDER_URL, env.getProperty(Context.PROVIDER_URL));
try
{
InitialContext ctx = new InitialContext(props);
ActiveMQXAConnectionFactory connectionFactory = (ActiveMQXAConnectionFactory) ctx
.lookup(env.getProperty("jms.connectionFactory"));
return connectionFactory;
}
catch(NamingException e)
{
throw new RuntimeException("XAConnectionFactory lookup failed", e);
}
}
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() throws JMSException
{
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setTransactionManager(txConfig.transactionManager());
factory.setBackOff(new FixedBackOff());
return factory;
}
@Bean(name = "jmsTemplate")
@Override
public JmsTemplate jmsTemplate() throws JMSException
{
JmsTemplate t = new JmsTemplate();
t.setConnectionFactory(connectionFactory());
t.setMessageTimestampEnabled(true);
t.setMessageIdEnabled(true);
return t;
}
我的 JMS 消费者注释为:
@Transactional
@JmsListener(destination = "test.q1")
有什么我遗漏的吗?
事实证明这只能通过资源适配器工作,仅通过 JNDI ConnectionFactory 是不可能的。
有可能,在外部 JMS 服务器定义中使用未记录的 ActiveMQ JNDI 属性 "xa=true",请参见此处:
我尝试让涉及 jdbc 的 XA 事务和在部署到 Weblogic 的 Spring webapp 中工作的 jms 数据源。
使用本地 Atomikos TransactionManager,这有效 - 我在 ActiveMQ 中看到 XA 调试消息,并且内容保持一致。然而,在 Weblogic 中,数据库和 ActiveMQ 在事务上并不一致。
我在 Weblogic 中添加了一个外部 JMS 服务器
JNDI 初始上下文工厂:
org.apache.activemq.jndi.ActiveMQInitialContextFactory
JNDI 连接URL:
tcp://localhost:61616
JNDI 属性:
connectionFactoryNames=XAConnectionFactory
我向该服务器添加了一个 ConnectionFactory(远程 JNDI 名称 = XAConnectionFactory)。查找有效,到目前为止一切顺利。
在我的代码中,这是我设置 Spring JTA 的方式:
@Override
@Bean
@Profile(AppConfig.PROFILE_WEBLOGIC)
public JtaTransactionManager transactionManager()
{
WebLogicJtaTransactionManager tx = new WebLogicJtaTransactionManager();
tx.afterPropertiesSet();
return tx;
}
这是我的 JMS 配置:
@Bean
@Profile(AppConfig.PROFILE_WEBLOGIC)
public ConnectionFactory connectionFactory()
{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, env.getProperty(Context.INITIAL_CONTEXT_FACTORY));
props.setProperty(Context.PROVIDER_URL, env.getProperty(Context.PROVIDER_URL));
try
{
InitialContext ctx = new InitialContext(props);
ActiveMQXAConnectionFactory connectionFactory = (ActiveMQXAConnectionFactory) ctx
.lookup(env.getProperty("jms.connectionFactory"));
return connectionFactory;
}
catch(NamingException e)
{
throw new RuntimeException("XAConnectionFactory lookup failed", e);
}
}
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() throws JMSException
{
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setTransactionManager(txConfig.transactionManager());
factory.setBackOff(new FixedBackOff());
return factory;
}
@Bean(name = "jmsTemplate")
@Override
public JmsTemplate jmsTemplate() throws JMSException
{
JmsTemplate t = new JmsTemplate();
t.setConnectionFactory(connectionFactory());
t.setMessageTimestampEnabled(true);
t.setMessageIdEnabled(true);
return t;
}
我的 JMS 消费者注释为:
@Transactional
@JmsListener(destination = "test.q1")
有什么我遗漏的吗?
事实证明这只能通过资源适配器工作,仅通过 JNDI ConnectionFactory 是不可能的。
有可能,在外部 JMS 服务器定义中使用未记录的 ActiveMQ JNDI 属性 "xa=true",请参见此处: