I am new to building web services and I started using spring boot to build one. I created the following controller class
package controller;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import model.Time;
import service.FeedService;
#RestController
public class FeedController extends ScheduledThreadPoolExecutor{
public FeedController(int corePoolSize) {
super(corePoolSize);
// TODO Auto-generated constructor stub
}
int difference;
int a;
boolean schedule;
//static as the variable is accessed across multiple threads
#Autowired
static FeedService fs;
#RequestMapping(value="/test")
public String test(){
return "test";
}
#RequestMapping(value = "/schedule", method = RequestMethod.GET)
public int ScheduleFeed(#RequestParam(value = "difference",required = false) String y) throws InterruptedException, ExecutionException{
// if(y != null){
// difference = Integer.parseInt(y);
difference = 0;
NewScheduledThreadPoolTest.mymethod(difference);
return difference;
// }else{
// return -1;
// }
}
#RequestMapping(value = "/inquireSchedule", method = RequestMethod.GET)
public ResponseEntity<Time> RequestFeed(){
if(schedule == true){
schedule = fs.setFalse();
return new ResponseEntity<Time>(HttpStatus.OK);
}
return new ResponseEntity<Time>(HttpStatus.BAD_REQUEST);
}
//schedule the task to happen after a certain number of times
static class NewScheduledThreadPoolTest {
public static void mymethod(int difference, final String... args) throws InterruptedException, ExecutionException {
// creates thread pool with 1 thread
System.out.println("hello world");
final ScheduledExecutorService schExService = Executors.newScheduledThreadPool(2);
// Object creation of runnable thread.
final Runnable ob = new NewScheduledThreadPoolTest().new myclass();
// Thread scheduling ie run it after "difference" hours before and then after every 24 hours later on
schExService.scheduleWithFixedDelay(ob, difference, 24, TimeUnit.SECONDS);
// waits for termination for 30 seconds only
schExService.awaitTermination(30, TimeUnit.SECONDS);
// shutdown now.
schExService.shutdownNow();
System.out.println("Shutdown Complete");
}
class myclass implements Runnable{
#Override
public void run() {
try{
// the mechanism to give a positive feedback to the arduino service
fs.setTrue();
System.out.println("hello world");
}catch(Exception e){
System.out.println("task failed");
e.printStackTrace();
}
}}
}
}
Trying to run my web service causes it to throw the following exception:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'feedController' defined in file
[D:\Rishit\Java
workspaces\FeedNemo\target\classes\controller\FeedController.class]:
Unsatisfied dependency expressed through constructor parameter 0: No
qualifying bean of type [int] found for dependency [int]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {}; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [int] found for dependency [int]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {} at
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
~[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1185)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1174)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
com.example.DemoApplication.main(DemoApplication.java:17)
[classes/:na] Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [int] found for dependency [int]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {} at
org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1057)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] ... 19 common frames
omitted
However, If I remove the "ScheduledThreadPoolExecutor" and the constructor, it runs fine. Can someone please explain what is the problem with extending the class?
Note:
1) Extending the class was suggested in the below mentioned post as a solution to my initial problem. Initially, my runnable was not running without any sort of notification or error message
2) The below post makes use of abusive language. However this was the only one that provided a solution to my initial problem. The initial problem is specified just to give a clarity of why I extended the above class and may not be directly related to my current problem. Please do not open if you find such language offensive.
http://code.nomad-labs.com/2011/12/09/mother-fk-the-scheduledexecutorservice/
Do not make bean members static. The fact that they're referenced from multiple threads is irrelevant; it's Spring's job to make sure that the dependencies are populated.
Also, prefer constructor injection to field injection; it makes these sorts of issues dramatically less likely.
Related
I have tried this solution found in the following questions, but none work in my case:
#Configuration
#EnableWebMvc
#ComponentScan("myapp.framework.export")
public class WebConfig extends MyAppWebConfig {
#Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
super.configureContentNegotiation(configurer);
}
#Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
super.configureMessageConverters(converters);
}
}
Error:
INFO: Initializing Spring FrameworkServlet 'services-rest'
2017-04-11 15:25:52,774|localhost-startStop-1|NO_TID|NO_USER|ERROR|org.springframework.web.servlet.DispatcherServlet.initServletBean|Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xlsHttpMessageConverter': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
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:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1241)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1154)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4969)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
... 29 common frames omitted
Apr 11, 2017 3:25:52 PM org.apache.catalina.core.ApplicationContext log
SEVERE: StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'xlsHttpMessageConverter': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
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:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1241)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1154)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4969)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
... 29 more
Apr 11, 2017 3:25:52 PM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet /myapp threw load() exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'myapp.framework.export.ExportXlsModelService<?>[]' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#javax.annotation.Resource(shareable=true, lookup=, name=, description=, authenticationType=CONTAINER, type=class java.lang.Object, mappedName=)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:518)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:496)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:627)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:318)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
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:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:138)
at javax.servlet.GenericServlet.init(GenericServlet.java:158)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1241)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1154)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1041)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4969)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5255)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Apr 11, 2017 3:25:52 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
Apr 11, 2017 3:25:52 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-nio-8009"]
Apr 11, 2017 3:25:52 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 10565 ms
xlsHttpMessageConverter:
package myapp.framework.web.converter;
import myapp.framework.export.ExportXlsModelService;
import java.io.IOException;
import java.io.OutputStream;
import javax.annotation.Resource;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.stereotype.Service;
#Service
public class XlsHttpMessageConverter<T> extends
AbstractMyAppHttpMessageConverter<T, ExportXlsModelService<T>> {
#Resource
private ExportXlsModelService<T>[] exportServices;
public XlsHttpMessageConverter() {
super(MyAppMediaType.APPLICATION_EXCEL);
}
#Override
protected void ecrireFichier(final T toExport, final OutputStream os) throws IOException,
HttpMessageNotWritableException {
final ExportXlsModelService<T> exportService = getServiceExport(toExport);
final HSSFWorkbook model = exportService.construireXlsModel(toExport);
model.write(os);
}
#Override
protected ExportXlsModelService<T>[] getServicesExport() {
return exportServices;
}
}
Try to add classpath*: Prefix to your scan. (read here)
The * means scan in all jars on classpath
UPDATE:
Your converter has package myapp.framework.web.converter but scan checks myapp.framework.export
I think there is issue in autowiring as Generic class.
We have to specify particular Type while autowiring.
Following Reference may be useful:
Reference1
Reference2
You can't have a #Service that has a type parameter T, how would Spring know what T should be when it instantiates the bean.
If you have 5 different XlsHttpMessageConverter<T>, you have to declare 5 beans. Unfortunately even if you define each converter as a separate bean, there is no way for Spring to know which ExportXlsModelService<T>[] exportServices; to inject, as it will consider all ExportXlsModelService as candidate regardless of the type parameter (see edit below).
It is however possible to inject a bean of a specific type into a #Bean method, so the following example works (but is very impractical for large number of types).
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import static org.junit.Assert.assertNotNull;
#Configuration
public class MyConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
ConverterInjectionTarget bean = ctx.getBean(ConverterInjectionTarget.class);
System.out.println("injected Converters = " + bean.converters.size());
for (XlsHttpMessageConverter converter : bean.converters) {
assertNotNull(converter.value);
}
}
// correct version of generic bean can be autowired into #Bean method
#Bean
XlsHttpMessageConverter integerConverter(Injectable<Integer> value) {
return new XlsHttpMessageConverter<>(value);
}
#Bean
XlsHttpMessageConverter StringConverter(Injectable<String> value) {
return new XlsHttpMessageConverter<String>(value);
}
#Bean
Injectable<Integer> integerDummyBean() {
return new Injectable<>(1);
}
#Bean
Injectable<String> stringDummyBean() {
return new Injectable<>("hello");
}
#Bean
ConverterInjectionTarget myBean() {
return new ConverterInjectionTarget();
}
static class XlsHttpMessageConverter<T> {
// impossible to autowire this, it has to be set through the constructor
final Injectable<T> value;
XlsHttpMessageConverter(Injectable<T> value) {
this.value = value;
}
}
static class ConverterInjectionTarget {
#Autowired
List<XlsHttpMessageConverter> converters;
}
class Injectable<T> {
final T value;
Injectable(T value) {
this.value = value;
}
}
}
If you modify the example and try to autowire the Injectable into XlsHttpMessageConverter you will see that it fails.
The best solution may be to create a BeanFactoryPostProcessor that will create all the ExportXlsModelService instances programmatically, and provide them as input to the XlsHttpMessageConverter instances, which are then registered as singletons.
EDIT
One thing I did not mention, is that it is possible to autowire a generic type, but it requires that the bean is defined as a concrete class (not using a #Bean method), so the following would also work (multiple files).
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import static org.junit.Assert.assertNotNull;
#Configuration
#ComponentScan("myPackage")
public class MyConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class);
ConverterInjectionTarget bean = ctx.getBean(ConverterInjectionTarget.class);
System.out.println("injected Converters = " + bean.converters.size());
for (XlsHttpMessageConverter converter : bean.converters) {
assertNotNull(converter.value);
}
}
#Bean
Injectable<Integer> integerDummyBean() {
return new Injectable<>(1);
}
#Bean
Injectable<String> stringDummyBean() {
return new Injectable<>("hello");
}
#Bean
ConverterInjectionTarget myBean() {
return new ConverterInjectionTarget();
}
static class ConverterInjectionTarget {
#Autowired
List<XlsHttpMessageConverter> converters;
}
static class Injectable<T> {
final T value;
Injectable(T value) {
this.value = value;
}
}
}
abstract class XlsHttpMessageConverter<T> {
// this is possible to autowire because we have a concrete class that spring can read the bytecode from.
#Autowired
MyConfig.Injectable<T> value;
}
#Service
public class IntegerXlsHttpMessageConverter<T> extends XlsHttpMessageConverter<Integer> {
}
#Service
public class StringXlsHttpMessageConverter extends XlsHttpMessageConverter<String> {
}
But again this may not be feasible if there are many types.
I'm using a #PostCostruct annotation to get an initializing method to run code at startup of my Sprin Boot application.
#Service("jobManager")
public class JobManager {
#Autowired
SchedulerFactoryBean scheduler;
#Autowired
InterruttoreService interruttoreService;
#PostConstruct
public void createInitialJobs() throws SchedulerException {
List<Interruttore> interruttori = interruttoreService.findAllSwitches();
for (int i = 0; i < interruttori.size(); i++) {
Interruttore interruttore = interruttori.get(i);
interruttoreService.toggleSwitchOnStartup(interruttore);
}
}
interruttoreService.toggleSwitchOnStartup(interruttore)
is in a service class and is the following (job manager is auto wired in the this class)
#Override
public void toggleSwitchOnStartup(Interruttore interruttore) {
Date nextTimeout = interruttore.getTimeoutDate();
Date date = new Date();
Date now = new Timestamp(date.getTime());
if (nextTimeout == null) {
nextTimeout = now;
}
int idInterruttore = interruttore.getIdInterruttore();
if(nextTimeout.after(now)){ //c'รจ un timeout futuro
try { lightOn(idInterruttore);
jobManager.createJob(interruttore, nextTimeout);
} catch (SchedulerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
shutDown(idInterruttore);
}
}
I'm getting a NullPointerException when calling jobManager from this method, don't know why if the bean was created during #PostCostruct...
This is the stack trace of the error
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'interruttoreService': Unsatisfied dependency expressed through field 'jobManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobManager': Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:569)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:349)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
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:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
... 53 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobManager': Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1575)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
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:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:207)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1128)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1056)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:566)
... 66 more
Caused by: java.lang.NullPointerException
at it.besmart.service.InterruttoreServiceImpl.toggleSwitchOnStartup(InterruttoreServiceImpl.java:112)
at it.besmart.service.InterruttoreServiceImpl$$FastClassBySpringCGLIB$$907e162e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655)
at it.besmart.service.InterruttoreServiceImpl$$EnhancerBySpringCGLIB$$e2a6ab4b.toggleSwitchOnStartup(<generated>)
at it.besmart.quartz.JobManager.createInitialJobs(JobManager.java:47)
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:497)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:365)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:310)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
... 78 more
interruttoreService is auto wired correctly because just after the startup it starts working as usual.
Rergarding jobManager, i simply #Autowire it in InterruttoreService.class in this way
#Service("interruttoreService")
#Transactional
public class InterruttoreServiceImpl implements InterruttoreService {
#Autowired
JobManager jobManager;
....
....
This is tightly coupled code (you have InterruttoreService injected into JobManager and at the same time JobManager injected into InterruttoreService).
Why don't you remove InterruttoreService injection from JobManager and let toggleSwitchOnStartup() complete within a #PostCostruct annotated method all in InterruttoreService directly where JobManager is already wired-up.
The problem is a small typo with your service name
You have in your service
#Service("jobManager")//first j lowercase
public class JobManager {
#Autowired //In your Autowired if you dont say a qualifier name will try to find names as "JobManager" first J uppercase
JobManager jobManager;
Solution:
Remove the name in your service an keep only
#Service
public class JobManager {
Add a qualifier
#Autowired
#Qualifier("jobManager")
JobManager jobManager;
Below is my Bean configuration code, but the configuration doesn't pass the test as it says it failed to load ApplicationContext. Is there something I'm doing wrong? I added #Autowire to methods of each class that's needed (except for interface method), but I still have no idea why it's not loading
package soundsystems;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class CDPlayerConfig
{
#Bean
public CompactDisc sgtPeppers()
{
return new SgtPeppers();
}
#Bean(name = "SgtPepperPlayer")
public CDPlayer cdPlayer()
{
return new CDPlayer(sgtPeppers());
}
#Bean(name = "AnyCDPlayer")
public CDPlayer cdPlayer(CompactDisc cd)
{
return new CDPlayer(cd);
}
#Bean
public BlankDisc reallyBlankDisc()
{
return new BlankDisc();
}
#Bean
public BlankDisc blankDisc()
{
BlankDisc bd = new BlankDisc();
String title = "Sgt. Pepper's Lonely Hearts Club Band";
String artist = "The Beatles";
List<String> tracks = new ArrayList<String>();
tracks.add("Sgt. Pepper's Lonely Hearts Club Band");
tracks.add("With a Little Help from My Friends");
tracks.add("Lucy in the Sky with Diamonds");
tracks.add("Getting Better");
tracks.add("Fixing a Hole");
bd.setTitle(title);
bd.setArtist(artist);
bd.setTracks(tracks);
return bd;
}
#Bean
public Discography beatlesDiscography()
{
Discography dg = new Discography();
String artist = "The Beatles";
CompactDisc SgtPeppers = new SgtPeppers();
CompactDisc WhiteAlbum = new WhiteAlbum();
CompactDisc HardDaysNight = new HardDaysNight();
CompactDisc Revolver = new Revolver();
List<CompactDisc> cds = new ArrayList<CompactDisc>();
cds.add(SgtPeppers);
cds.add(WhiteAlbum);
cds.add(HardDaysNight);
cds.add(Revolver);
dg.setArtist(artist);
dg.setCDs(cds);
return dg;
}
}
package soundsystems;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest
{
#Rule
public final SystemOutRule log = new SystemOutRule().enableLog();
#Autowired
private CompactDisc cd;
#Autowired
private MediaPlayer player;
#Test
public void cdShouldNotBeNull()
{
assertNotNull(cd);
}
#Test
public void play()
{
player.play();
assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band" + " by The Beatles\n", log.getLog());
}
}
Thanks for having a look.
edit: Error
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AnyCDPlayer': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void soundsystems.CDPlayer.setCompactDisc(soundsystems.CompactDisc); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [soundsystems.CompactDisc] is defined: expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
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:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 25 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void soundsystems.CDPlayer.setCompactDisc(soundsystems.CompactDisc); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [soundsystems.CompactDisc] is defined: expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:661)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 41 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [soundsystems.CompactDisc] is defined: expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:618)
... 43 more
I believe that Spring's #Autowired default mode is by type. It means that Spring will try to autowire bean by interface type, btw you have 3 beans with same interface and Spring got confused which one to choose. If you want to achieve autowiring by name you should use #Qualifier: #Qualifier("beanname")
The error is quite clear:
Could not autowire method: public void soundsystems.CDPlayer.setCompactDisc(soundsystems.CompactDisc);
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [soundsystems.CompactDisc] is defined:
expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
You annotated you setCompactDisc() method in CDPlayer with #Autowired, so Spring tries to call it with a bean of type CompactDisc, but it has 3 of them, and thus can't decide which one to inject. Don't annotate this method with Autowired. Or even better, remove that method, since the CompactDisc is already initialized by the constructor.
I would like to understand whether there is a clean way to use constructor injection with arrays in spring-boot (1.3.5.RELEASE).
I've created this simple app that better explains my question:
package com.stackoverflow;
import java.util.Arrays;
import java.util.stream.IntStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class Application {
private static class Car { }
#Bean
public Car[] cars() {
return IntStream.range(0, 10).mapToObj(i -> new Car()).toArray(Car[]::new);
}
#Component
private static class Road implements CommandLineRunner {
private final Car[] cars;
#Autowired
public Road(Car[] cars) {
this.cars = cars;
}
// #Resource
// private Car[] cars;
#Override
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(cars));
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I understand that #Autowired works by type, so the reason why the previous application does not work is because when the Car[] has to be injected, Spring first tries to find all Car beans but, since there is no Car bean, the following exception is thrown:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'application.Road' defined in file [/spring-array-injection/target/classes/com/stackoverflow/Application$Road.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.stackoverflow.Application$Car[]]: No qualifying bean of type [com.stackoverflow.Application$Car] found for dependency [array of com.stackoverflow.Application$Car]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.stackoverflow.Application$Car] found for dependency [array of com.stackoverflow.Application$Car]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at com.stackoverflow.Application.main(Application.java:44) [classes/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.stackoverflow.Application$Car] found for dependency [array of com.stackoverflow.Application$Car]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
... 19 common frames omitted
I also understand that if I replace the constructor injection with field injection + #Resource everything works because the array is injected by name instead of type.
So, am I missing something or is it a real spring limitation (i.e. it is currently not possible to use constructor injection with arrays/lists of object in spring)?
UPDATE 1
Wow, I thought this question had a shorter life but the case is not solved yet. I will post the two (ugly) workarounds I've tested so far:
A wrapper around the array is injected instead of the plain array:
package com.stackoverflow.workaround.arrayholder;
import java.util.Arrays;
import java.util.stream.IntStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class Application {
private static class ArrayHolder<T> {
private final T array;
public ArrayHolder(T array) {
this.array = array;
}
public T getArray() {
return array;
}
}
private static class Car { }
#Bean
public ArrayHolder<Car[]> cars() {
return new ArrayHolder<>(IntStream.range(0, 10).mapToObj(i -> new Car()).toArray(Car[]::new));
}
#Component
private static class Road implements CommandLineRunner {
private final Car[] cars;
#Autowired
public Road(ArrayHolder<Car[]> cars) {
this.cars = cars.getArray();
}
#Override
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(cars));
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The beans are dynamically created and registered using the BeanFactoryPostProcessor:
package com.stackoverflow.workaround.dynamicregistration;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class Application implements BeanFactoryPostProcessor {
private static class Car { }
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
AtomicInteger atomicInteger = new AtomicInteger();
IntStream.range(0, 10)
.mapToObj(i -> new Car())
.forEach(car -> beanFactory.registerSingleton(String.valueOf(atomicInteger.getAndIncrement()), car));
}
#Component
private static class Road implements CommandLineRunner {
private final Car[] cars;
#Autowired
public Road(Car[] cars) {
this.cars = cars;
}
#Override
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(cars));
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Update 2
It turns out that constructor injection of arrays, collections and maps will be possible starting from Spring 4.3 (see issue).
As stated in the docs:
6.9.4 Fine-tuning annotation-based autowiring with qualifiers
If you intend to express annotation-driven injection by name, do not primarily use #Autowired, even if is technically capable of referring to a bean name through #Qualifier values. Instead, use the JSR-250 #Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through #Autowired, because type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection or map bean by unique name.
#Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, #Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.
And arrays are treated the same way as collections:
6.4.5 Autowiring collaborators
With byType or constructor autowiring mode, you can wire arrays and typed-collections. In such cases all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Maps if the expected key type is String. An autowired Maps values will consist of all bean instances that match the expected type, and the Maps keys will contain the corresponding bean names.
6.9.2 #Autowired
It is also possible to provide all beans of a particular type from the ApplicationContext by adding the annotation to a field or method that expects an array of that type: [...]
The same applies for typed collections: [...]
Even typed Maps can be autowired as long as the expected key type is String. The Map values will contain all beans of the expected type, and the keys will contain the corresponding bean names: [...]
I create simple news system with comments using Spring Boot and MongoDB. I would like to focus on code quality. I create service using generic to save data from class.
My code:
Dao.java
#Repository
public interface Dao<T, ID extends Serializable> extends MongoRepository<T, ID>{
}
DaoService.java
#Service
public class DaoService<T> extends AbstractService<T, Long> {
#Autowired
public DaoService(Dao<T, Long> dao) {
super(dao);
}
}
Service.java
#org.springframework.stereotype.Service
public interface Service<T, ID extends Serializable> {
T save(T entity);
}
AbstractService.java
public abstract class AbstractService<T, ID extends Serializable> implements
Service<T, ID> {
protected final Logger logger = LoggerFactory.getLogger(getClass());
protected Dao<T, ID> dao;
public AbstractService(Dao<T, ID> dao) {
this.dao = dao;
}
#Override
public T save(T entity) {
this.logger.debug("Create a new {} with information: {}", entity.getClass(),
entity.toString());
return this.dao.save(entity);
}
}
and 2 repo
#Repository
public interface CommentDao extends Dao<Comment, Long> {
}
and
#Repository
public interface NewsDao extends Dao<News, Long> {
}
My controller:
#RestController
#RequestMapping("/news")
public class NewsController {
private final DaoService<News> newsService;
private final DaoService<Comment> commentDaoService;
public NewsController(DaoService<News> newsService, DaoService<Comment> commentDaoService) {
this.newsService = newsService;
this.commentDaoService = commentDaoService;
}
#RequestMapping(method = RequestMethod.GET)
public void save(){
newsService.save(new News("elo","a","c"));
commentDaoService.save(new Comment("iss","we"));
}
}
error:
2016-03-02 23:22:30.265 WARN 6100 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'daoService' defined in file [C:\Users\Lukasz\IdeaProjects\NewsSystem_REST\build\classes\main\com\newssystem\lab\dao\DaoService.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.newssystem.lab.dao.Dao]: : No qualifying bean of type [com.newssystem.lab.dao.Dao] is defined: expected single matching bean but found 2: newsDao,commentDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.newssystem.lab.dao.Dao] is defined: expected single matching bean but found 2: newsDao,commentDao
2016-03-02 23:22:30.273 INFO 6100 --- [ main] o.apache.catalina.core.StandardService : Stopping service Tomcat
2016-03-02 23:22:30.296 ERROR 6100 --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'daoService' defined in file [C:\Users\Lukasz\IdeaProjects\NewsSystem_REST\build\classes\main\com\newssystem\lab\dao\DaoService.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.newssystem.lab.dao.Dao]: : No qualifying bean of type [com.newssystem.lab.dao.Dao] is defined: expected single matching bean but found 2: newsDao,commentDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.newssystem.lab.dao.Dao] is defined: expected single matching bean but found 2: newsDao,commentDao
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.2.RELEASE.jar:1.3.2.RELEASE]
at com.newssystem.lab.NewsSystemApplication.main(NewsSystemApplication.java:18) [main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na]
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.newssystem.lab.dao.Dao] is defined: expected single matching bean but found 2: newsDao,commentDao
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 24 common frames omitted
You must use the qualifier annotation to define which bean will be injected into your service. On Spring an interface can have many implementations, but if none of those implementations has the primary annotation defined Spring does not know which one to pick automatically.
#Autowired
#Qualifier("bean-name")