Is there a way to inject the SeContainer
itself?
I am working on a Picocli CLI application where I create the instances of the commands by using CDI. I do not want to depend on a specific CDI implementation, and I would like to achieve something like this:
@ApplicationScoped
public class PicocliCDIFactory implements CommandLine.IFactory {
private final SeContainer container;
@Inject
public PicocliCDIFactory(SeContainer container) {
this.container = container;
}
@Override
public <K> K create(Class<K> cls) throws Exception {
return container.select(cls).get();
}
}
An instance of CDI<?> would also be fine.
I am currently using Weld and this fails with:
Exception in thread "main" org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type SeContainer with qualifiers @Default
at injection point [BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject public com.example.project.PicocliCDIFactory(SeContainer)
at com.example.project.PicocliCDIFactory.<init>(PicocliCDIFactory.java:0)
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:397)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:312)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:159)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:181)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:552)
at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:65)
at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:63)
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62)
at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55)
at org.jboss.weld.executor.CommonForkJoinPoolExecutorServices.lambda$wrap$0(CommonForkJoinPoolExecutorServices.java:70)
at java.base/java.util.concurrent.ForkJoinTask$AdaptedInterruptibleCallable.exec(ForkJoinTask.java:1489)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1312)
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1843)
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1808)
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:188)
I also tried to inject an Instance<SeContainer>
, but it is unresolvable.
I am aware that with Weld I can inject the WeldContainer
, but again, I do not want to depend on a specific implementation of CDI like Weld.
The only solution I am seeing right now is using CDI.current()
to obtain a CDI
object and use it to create instances.
However, this static method does not seem super robust to me. What if there are multiple containers, and I want to make sure that my factory gets injected with the CDI object that has also been used to create it?
I just found out that you can inject the BeanContainer
.
"Any bean may obtain an instance of BeanContainer by injecting it."
From there I can just call BeanContainer.createInstance()
and use the Instance<Object>
obtained to create my objects.