I have a requirement to Inject the same instance of an ApplicationScoped bean into several places of my application and have created the following factory class which uses the @PostConstruct annotation to initialize the bean and the @Produces annotation to return the same instance of the bean.
@ApplicationScoped
public class CommandBusFactory implements Serializable {
private static final long serialVersionUID = 1L;
private CommandBus commandBus;
@PostConstruct
public void init() {
commandBus = new BasicCommandBus();
// Do some stuff to configure the command bus
}
@Produces
public CommandBus produceCommandBus() {
return commandBus;
}
}
The problem I've got is when I deploy the application GlassFish returns the following error message:
Exception while loading the app : CDI deployment failure:WELD-001409 Ambiguous dependencies for type [CommandBus] with qualifiers [@Default] at injection point [[BackedAnnotatedField] @Inject private myapp.web.ToDoItemCommandController.commandBus]. Possible dependencies [[Producer Method [CommandBus] with qualifiers [@Any @Default] declared as [[BackedAnnotatedMethod] @Produces public myapp.core.cdi.CommandBusFactory.produceCommandBus()], Managed Bean [class myapp.core.commandhandling.BasicCommandBus] with qualifiers [@Any @Default]]]
I can overcome this exception by adding the @Alternative annotation to the BasicCommandBus class, however this doesn't seem to be the best way of solving the problem.
I don't want to add a qualifier everywhere that I inject CommandBus into my application as using a different implementation of CommandBus would require changing the code in multiple places. The intention is that a later version of the factory will read a configuration file and depending upon a value in the configuration file it may create a different type of CommandBus.
I have read the answer to this question (https://stackoverflow.com/a/18782027/1274662) and understand why the Ambiguous dependencies exception is being thrown but what I don't know is the best way to deal with the fact that there are two possible beans that could be injected given that I want to decide which implementation is used and how it is initialised in a central location.
The questions I've got are:
Is using the
@Alternativeannotation on theBasicCommandBusclass the right approach?Is there a better approach that I should be using to Inject the same instance of an
ApplicationScopedbean (i.e.CommandBus) into several places of my application whilst controlling which implementation created (i.e.BasicCommandBusorEnhancedCommandBus) and how it is initialised in a central location?