I have a configuration which provide more than one implementations for a bean:
package demo.config; import org.apache.http.auth.UsernamePasswordCredentials; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.transport.http.HttpComponentsMessageSender; @Configuration public class WebServicesClientConfig { @Value("${webservice.username}") private String userName; @Value("${webservice.password}") private String password; @Bean (name = "webServiceTemplate") public Jaxb2Marshaller jaxb2Marshaller() { Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); jaxb2Marshaller.setPackagesToScan("demo.ws.bind"); return jaxb2Marshaller; } @Bean public WebServiceTemplate webServiceTemplate() { WebServiceTemplate webServiceTemplate = new WebServiceTemplate(); webServiceTemplate.setMarshaller(jaxb2Marshaller()); webServiceTemplate.setUnmarshaller(jaxb2Marshaller()); webServiceTemplate.setMessageSender(httpComponentsMessageSender()); return webServiceTemplate; } @Bean (name = "oq2WebServiceTemplate") public Jaxb2Marshaller jaxb2Marshaller2() { Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); jaxb2Marshaller.setPackagesToScan("demo.ws.bind2"); return jaxb2Marshaller; } @Bean public WebServiceTemplate oq2WebServiceTemplate() { WebServiceTemplate oq2WebServiceTemplate = new WebServiceTemplate(); oq2WebServiceTemplate.setMarshaller(jaxb2Marshaller2()); oq2WebServiceTemplate.setUnmarshaller(jaxb2Marshaller2()); oq2WebServiceTemplate.setMessageSender(httpComponentsMessageSender()); return oq2WebServiceTemplate; } @Bean public HttpComponentsMessageSender httpComponentsMessageSender() { HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender(); httpComponentsMessageSender.setCredentials(usernamePasswordCredentials()); return httpComponentsMessageSender; } @Bean public UsernamePasswordCredentials usernamePasswordCredentials() { return new UsernamePasswordCredentials(userName, password); } }
The client bean looks like:
package demo.client; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.ws.client.core.WebServiceTemplate; @Component public class OiClient { @Autowired @Qualifier("webServiceTemplate") private WebServiceTemplate webServiceTemplate; public Response getInfoByIdno() { // ignore details } }
But as I start up spring boot, it throws the following exception:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'oiService': Unsatisfied dependency expressed through field 'oiClient'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'oiClient': Unsatisfied dependency expressed through field 'webServiceTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.ws.client.core.WebServiceTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=webServiceTemplate)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:251) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1135) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
How-To
The configuration class should be fixed as bellows:
package demo.config; import org.apache.http.auth.UsernamePasswordCredentials; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.transport.http.HttpComponentsMessageSender; @Configuration public class WebServicesClientConfig { @Value("${webservice.username}") private String userName; @Value("${webservice.password}") private String password; @Bean @Qualifier("webServiceTemplate") public Jaxb2Marshaller jaxb2Marshaller() { Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); jaxb2Marshaller.setPackagesToScan("demo.ws.bind"); return jaxb2Marshaller; } @Bean public WebServiceTemplate webServiceTemplate() { WebServiceTemplate webServiceTemplate = new WebServiceTemplate(); webServiceTemplate.setMarshaller(jaxb2Marshaller()); webServiceTemplate.setUnmarshaller(jaxb2Marshaller()); webServiceTemplate.setMessageSender(httpComponentsMessageSender()); return webServiceTemplate; } @Bean @Qualifier("oq2WebServiceTemplate") public Jaxb2Marshaller jaxb2Marshaller2() { Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); jaxb2Marshaller.setPackagesToScan("demo.ws.bind2"); return jaxb2Marshaller; } @Bean public WebServiceTemplate oq2WebServiceTemplate() { WebServiceTemplate oq2WebServiceTemplate = new WebServiceTemplate(); oq2WebServiceTemplate.setMarshaller(jaxb2Marshaller2()); oq2WebServiceTemplate.setUnmarshaller(jaxb2Marshaller2()); oq2WebServiceTemplate.setMessageSender(httpComponentsMessageSender()); return oq2WebServiceTemplate; } @Bean public HttpComponentsMessageSender httpComponentsMessageSender() { HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender(); httpComponentsMessageSender.setCredentials(usernamePasswordCredentials()); return httpComponentsMessageSender; } @Bean public UsernamePasswordCredentials usernamePasswordCredentials() { return new UsernamePasswordCredentials(userName, password); } }
Reference
[1] https://www.logicbig.com/tutorials/spring-framework/spring-core/inject-bean-by-name.html