I develop an extension that provide Injectable bean with a SyntheticBeanBuildItem. This bean is used via constructor injection in another projet that use this extension.
/**
* Bean to inject
*/
@ApplicationScoped
public class FooConfig {
private String url;
private String port;
// Only for CDI injection
@SuppressWarnings("unused")
private FooConfig() {}
public FooConfig(String url, String port) {
this.url = url;
this.port = port;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
}
@Path("")
public class Foo {
private final FooService fooService;
private final FooConfig fooConfig;
public Foo(FooService fooService, FooConfig fooConfig) {
this.fooService = fooService;
this.myConfig = fooConfig;
}
@CheckedTemplate
public static class Templates {
public static native TemplateInstance index();
public static native TemplateInstance list(Uni<List<Bar>> bars, FooConfig fooConfig);
}
@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance list() {
return Templates.list(fooService.fetchAsync(), this.fooConfig);
}
}
And here is the extension code that provide the FooConfig bean:
@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep
public void createConfigBean(List<DevServicesResultBuildItem> devServicesResultBuildItem, FooRecorder recorder, BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItemBuildProducer) {
// Retrieve config set Inside FooExtensionProcessor
String apiUrl = devServicesResultBuildItem.stream().filter(devService -> devService.getName().equals(FooServiceContainer.CONTAINER_NAME))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Can't find foo-service url"))
.getConfig().get("url");
syntheticBeanBuildItemBuildProducer.produce(SyntheticBeanBuildItem.configure(FooConfig.class)
.unremovable()
.setRuntimeInit()
.runtimeValue(recorder.createConfig("http://"+apiUrl))
.done());
}
And the recorder :
@Recorder
public class FooServiceRecorder {
public RuntimeValue<FooConfig> createConfig(String url) {
return new RuntimeValue<>(new FooConfig(url, url.split(":")[1]));
}
}
If I run quarkus dev
inside the project, everything works as expected. The bean is correctly found and injected. If I rune mvn compile
from the parent projet, again everything is ok.
But, if I run mvn package
, Quarkus maven plugin seams to check for bean availability so I got this error:
Suppressed: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type org.baz.foo.extension.runtime.FooConfig and qualifiers [@Default]
For me the quarkus plugin should either not try to validate injection during package phase or take into account beans produce with SyntheticBeanBuildItem.
Did I miss something, or it is a bug in the plugin?
I found a solution. It seems the quarkus maven plugin check for beans avilability during package phase so I need to make bean of my extension available via Jandex with the maven jandex plugin apply into the runtime pom.xml of my extension.
As my extension also provide this bean by SyntheticBeanBuildItem, I had to exclude the bean with EcludedTypeBuildItem otherwise I get Ambigous Dependency.
It seems a bit tricky but this make it works