Reputation: 47
spring configuration: Trying to instantiate a JmsMessageListenerContainerFactory Bean that will use a specific connection factory bean instance using annotations.
@Configuration
public class DemoJmsConfig {
@Value("${jms.context.factory}")
private String initialContextFactory;
@Value("${jms.provider.url}")
String jmsProviderUrl;
//Inbound
@Value("${jms.inbound.qcf.userName}")
private String inboundQcfUserName;
@Value("${jms.inbound.qcf.password}")
private String inboundQcfPassword;
@Value("${jms.inbound.queue.connectionfactory}")
private String inboundQueueConnectionFactory;
@Value("${jms.inbound.queue.name}")
private String inboundQueueName;
@Value("${jms.inbound.initial.cache.size}")
private String inboundInitCacheSize;
//Outbound
@Value("${jms.outbound.topic.connectionfactory}")
private String outboundTopicConnectionFactory;
@Value("${jms.outbound.topic.name}")
private String outboundTopicName;
@Value("${jms.outbound.tcf.userName}")
private String outboundTcfUserName;
@Value("${jms.outbound.tcf.password}")
private String outboundTcfPassword;
@Value("${jms.outbound.initial.cache.size}")
private String outboundInitCacheSize;
@Bean
public InitialContext initialContext() throws NamingException {
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
initialContextFactory);
props.put(Context.PROVIDER_URL, jmsProviderUrl);
// Create the initial context from the properties we just created
return new InitialContext(props);
}
@Bean(name="inboundConnectionFactory")
@Qualifier("inboundConnectionFactory")
public ConnectionFactory inboundConnectionFactory() throws NamingException {
//Create a Connection Factory adapter with user credentials
UserCredentialsConnectionFactoryAdapter uccfa = new UserCredentialsConnectionFactoryAdapter();
ConnectionFactory cf = (ConnectionFactory) initialContext().lookup(inboundQueueConnectionFactory);
uccfa.setTargetConnectionFactory(cf);
uccfa.setUsername(inboundQcfUserName);
uccfa.setPassword(inboundQcfPassword);
CachingConnectionFactory ccf = new CachingConnectionFactory();
if(inboundInitCacheSize != null && Integer.parseInt(inboundInitCacheSize) > 0){
ccf.setSessionCacheSize(Integer.parseInt(inboundInitCacheSize)); //Default is 1
}
ccf.setTargetConnectionFactory(uccfa);
return ccf;
}
@Bean(name="inboundJMSTemplate")
@Qualifier("inboundJMSTemplate")
public JmsTemplate inboundJMSTemplate(@Qualifier("inboundConnectionFactory") ConnectionFactory inboundConnectionFactory ) throws NamingException{
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(inboundConnectionFactory);
jmsTemplate.setDefaultDestinationName(inboundQueueName);
return jmsTemplate;
}
@Bean(name="inboundJmsListenerContainerFactory")
@Qualifier("inboundJmsListenerContainerFactory")
public JmsListenerContainerFactory<?> inboundJmsListenerContainerFactory(
DefaultJmsListenerContainerFactoryConfigurer configurer,
@Qualifier("inboundConnectionFactory") ConnectionFactory inboundConnectionFactory)
throws NamingException {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
// This provides all boot's default to this factory, including the
// message converter
configurer.configure(factory, inboundConnectionFactory);
// You could still override some of Boot's default if necessary.
return factory;
}
@Bean(name="outboundConnectionFactory")
@Qualifier("outboundConnectionFactory")
public ConnectionFactory outboundConnectionFactory() throws NamingException {
//Create a Connection Factory adapter with user credentials
UserCredentialsConnectionFactoryAdapter uccfa = new UserCredentialsConnectionFactoryAdapter();
ConnectionFactory cf = (ConnectionFactory) initialContext().lookup(outboundTopicConnectionFactory);
uccfa.setTargetConnectionFactory(cf);
uccfa.setUsername(outboundTcfUserName);
uccfa.setPassword(outboundTcfPassword);
CachingConnectionFactory ccf = new CachingConnectionFactory();
if(outboundInitCacheSize != null && Integer.parseInt(outboundInitCacheSize) > 0){
ccf.setSessionCacheSize(Integer.parseInt(outboundInitCacheSize)); //Default is 1
}
ccf.setTargetConnectionFactory(uccfa);
return ccf;
}
@Bean(name="outboundErrorJMSTemplate")
@Qualifier("outboundErrorJMSTemplate")
public JmsTemplate outboundErrorJMSTemplate(@Qualifier("outboundConnectionFactory") ConnectionFactory outboundConnectionFactory ) throws NamingException{
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(outboundConnectionFactory);
jmsTemplate.setDefaultDestinationName(outboundTopicName);
return jmsTemplate;
}
}
Expected result: The JmsListenerContainerFactory is instantiated.
Actual:
*************************** APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of method jmsListenerContainerFactory in org.springframework.boot.autoconfigure.jms.JmsAnnotationDrivenConfiguration required a single bean, but 2 were found:
- inboundConnectionFactory: defined by method 'inboundConnectionFactory' in class path resource [com/example/demo/config/DemoJmsConfig.class]
- outboundConnectionFactory: defined by method 'outboundConnectionFactory' in class path resource [com/example/demo/config/DemoJmsConfig.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
[WARNING] java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:527) at java.lang.Thread.run(Thread.java:745) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jmsListenerContainerFactory' defined in class path resource [org/springframework/boot/autoconfigure/jms/JmsAnnotationDrivenConfiguration.class]: Unsatisfied dependency expressed through method 'jmsListenerContainerFactory' parameter 1; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.jms.ConnectionFactory' available: expected single matching bean but found 2: inboundConnectionFactory,outboundConnectionFactory at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107) at com.example.demo.DemoApplication.main(DemoApplication.java:10) ... 6 more Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.jms.ConnectionFactory' available: expected single matching bean but found 2: inboundConnectionFactory,outboundConnectionFactory at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:173) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1116) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066) at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ... 25 more
I have tried specifying qualifiers, bean names.. still getting errors. Can anyone suggest what I should do to resolve this. I need both the inbound and outbound connections since the application will consume and publish
Upvotes: 0
Views: 7064
Reputation: 699
Check this question Spring Boot multiple JMS connections that can help you. If in your case are using a mix of Spring XML and annotations to make a connection factory, maybe you can have problems with SpringBoot, in this case thy disable autostart of spring-boot-jms with this in your application:
@SpringBootApplication(exclude = {JmsAutoConfiguration.class})
this was my case.
Upvotes: 0