SpringBoot Autowiring a generic type fails because of multiple possible beans

oussama :

I'm trying to create a class that Autowire an object of type T.

@component    
public class TaskScheduler<T extends TaskService>{
    @Autowired
    private T taskService;
}

the problem is that I have two components that extend TaskService.

@component
public class firstTaskService extends TaskService {

}

and

@component
public class secondTaskService extends TaskService {

}

so when this line is executed (ts is being created)

@Autowired
TaskScheduler<firstTaskService> ts;

I get this error :

Description: Parameter 1 of constructor in TaskScheduler required a single bean, but 2 were found

the message I got suggested this :

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.

But from what I understood, the @Primary and @Qualifier annotations make me choose 1 of the components, which not what I want because I want to use firstTaskService and secondTaskService with that same class (TaskScheduler).

How could this be done?

Edit: Clarification: My objective is to reuse the TaskScheduler class with different classes that extend the TaskService class (not to use multiple classes that extend TaskService together in TaskScheduler).

Lorelorelore :

If you want to autowire all beans that extends TaskService maybe you should change the autowired field to a List:

@Component    
public class TaskScheduler<T extends TaskService>{
    @Autowired
    private List<T> taskService;
}

In this way Spring should put in the List all autowireable beans that extends TaskService.

EDIT: since you want to dinamically select the type of TaskService the only way I've found is the following. First, redefine your TaskScheduler:

public class TaskScheduler <T extends TaskService>{

    private T taskService;

    public void setTaskService(T taskService) {
        this.taskService = taskService;
    }
}

Your TaskService and related subclasses should remain untouched. Set up a configuration class as it follows:

@Configuration
public class TaskConf {

    @Autowired
    private FirstTaskService firstTaskService;

    @Autowired
    private SecondTaskService secondTaskService;

    @Bean
    public TaskScheduler<FirstTaskService> firstTaskServiceTaskScheduler(){
        TaskScheduler<FirstTaskService> t =  new TaskScheduler<>();
        t.setTaskService(firstTaskService);
        return t;
    }

    @Bean
    public TaskScheduler<SecondTaskService> secondTaskServiceTaskScheduler(){
        TaskScheduler<SecondTaskService> t =  new TaskScheduler<>();
        t.setTaskService(secondTaskService);
        return t;
    }

}

And then test your TaskScheduler in this way:

@Autowired
TaskScheduler<firstTaskService> ts;

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=93532&siteId=1