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
@Alternative
annotation on theBasicCommandBus
class the right approach?Is there a better approach that I should be using to Inject the same instance of an
ApplicationScoped
bean (i.e.CommandBus
) into several places of my application whilst controlling which implementation created (i.e.BasicCommandBus
orEnhancedCommandBus
) and how it is initialised in a central location?