我想用spring-boot和IBM MQ创建一个共享持久的订户。我已经做了一个持久的订阅者,但是共享订阅失败了。
调试程序时,我发现了空指针异常问题
java.lang.NoSuchMethodError: javax.jms.Session.createSharedDurableConsumer(Ljavax/jms/Topic;Ljava/lang/String;Ljava/lang/String;)Ljavax/jms/MessageConsumer;
内部类 AbstractMessageListenerContainer 中,方法 createConsumer 。这是因为它尝试调用session.createSharedDurableConsumerMethod,其中会话对象为javax.jms.Session和IntelliJ将其指向库 geronimo-jms_1.1_spec-1.1.1.jar
我的pom.xml使用的是JMS 2.0:
<dependency>
<groupId>javax.jms</groupId>
<artifactId>javax.jms-api</artifactId>
<version>2.0.1</version>
</dependency>
这是Java代码:
import com.ibm.mq.jms.*;
...
public class JmsConfig {
...
@Bean
public MQTopicConnectionFactory mqTopicConnectionFactory(){
MQTopicConnectionFactory factory = new MQTopicConnectionFactory();
try{
factory.setHostName(mqHostname);
factory.setChannel(mqChannel);
factory.setPort(Integer.parseInt(mqPort));
factory.setQueueManager(mqQManager);
factory.setTransportType(WMQConstants.WMQ_CM_CLIENT);
factory.setClientReconnectTimeout(0);
} catch (Exception e) {
e.printStackTrace();
}
return factory;
}
@Bean
@Primary
UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter(MQTopicConnectionFactory mqTopicConnectionFactory) {
UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter = new UserCredentialsConnectionFactoryAdapter();
userCredentialsConnectionFactoryAdapter.setTargetConnectionFactory(mqTopicConnectionFactory);
userCredentialsConnectionFactoryAdapter.setUsername(mqUsername);
if(!mqPassword.equals("")) {
userCredentialsConnectionFactoryAdapter.setPassword(mqPassword);
}
return userCredentialsConnectionFactoryAdapter;
}
@Bean
public CachingConnectionFactory cachingConnectionFactory(UserCredentialsConnectionFactoryAdapter userCredentialsConnectionFactoryAdapter) {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
cachingConnectionFactory.setTargetConnectionFactory(userCredentialsConnectionFactoryAdapter);
cachingConnectionFactory.setSessionCacheSize(1000);
cachingConnectionFactory.setReconnectOnException(true);
return cachingConnectionFactory;
}
@Bean
public JmsOperations jmsOperations(CachingConnectionFactory cachingConnectionFactory) {
JmsTemplate jmsTemplate = new JmsTemplate(cachingConnectionFactory);
jmsTemplate.setPubSubDomain(true);
jmsTemplate.setReceiveTimeout(2000);
return jmsTemplate;
}
@Bean
public JmsListenerContainerFactory<?> topicListenerFactory(ConnectionFactory connectionFactory, DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
configurer.configure(factory, connectionFactory);
factory.setPubSubDomain(true);//must follow the configurer.configure(), because it will set the factory as default as connectionFactory
factory.setConcurrency("1");
factory.setSubscriptionShared(true);
factory.setSubscriptionDurable(true);
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setClientId(mqClientID);
return factory;
}
}
是否缺少任何配置,或者需要重写该方法来管理Session对象,以便它可以创建持久共享的连接?
答案 0 :(得分:0)
最后,我弄清楚了为什么该程序使用JMS1.1。这是因为程序的另一部分从pom加载了AWS SQS库,并且该库将JMS1.1(geronimo-jms_1.1_spec-1.1.1.jar)用于ActiveMQ。
因此,我在pom中为AWS SQS库添加了排除项,以防止它覆盖JMS2.0库。