diff --git a/docs/src/main/asciidoc/cdi-reference.adoc b/docs/src/main/asciidoc/cdi-reference.adoc index 4db2098da326c..625ee59faf1f4 100644 --- a/docs/src/main/asciidoc/cdi-reference.adoc +++ b/docs/src/main/asciidoc/cdi-reference.adoc @@ -814,14 +814,49 @@ The extended `BeanConfigurator` accepts either a `io.quarkus.runtime.RuntimeValu [source,java] ---- @BuildStep -@Record(STATIC_INIT) +@Record(STATIC_INIT) <1> SyntheticBeanBuildItem syntheticBean(TestRecorder recorder) { return SyntheticBeanBuildItem.configure(Foo.class).scope(Singleton.class) + .runtimeValue(recorder.createFoo()) <2> + .done(); +} +---- +<1> By default, a synthetic bean is initialized during `STATIC_INIT`. +<2> The bean instance is supplied by a value returned from a recorder method. + +It is possible to mark a synthetic bean to be initialized during `RUNTIME_INIT`: + +.`RUNTIME_INIT` `SyntheticBeanBuildItem` Example +[source,java] +---- +@BuildStep +@Record(RUNTIME_INIT) <1> +SyntheticBeanBuildItem syntheticBean(TestRecorder recorder) { + return SyntheticBeanBuildItem.configure(Foo.class).scope(Singleton.class) + .setRuntimeInit() <2> .runtimeValue(recorder.createFoo()) .done(); } ---- +<1> The recorder must be executed in the `ExecutionTime.RUNTIME_INIT` phase. +<2> The bean instance is initialized during `RUNTIME_INIT`. +[IMPORTANT] +==== +Synthetic bean initialized during `RUNTIME_INIT` must not be accessed during `STATIC_INIT`. `RUNTIME_INIT` build steps that access a runtime-init synthetic bean should consume the `SyntheticBeansRuntimeInitBuildItem`: + +[source,java] +---- +@BuildStep +@Record(RUNTIME_INIT) +@Consume(SyntheticBeansRuntimeInitBuildItem.class) <1> +void accessFoo(TestRecorder recorder) { + recorder.foo(); <2> +} +---- +<1> This build step must be executed after `syntheticBean()` completes. +<2> This recorder method results in an invocation of the `Foo` bean instance. +==== === Annotation Transformations diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java index e9a9df065be05..ec38029f39620 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeanBuildItem.java @@ -16,6 +16,7 @@ * Makes it possible to register a synthetic bean whose instance can be easily produced through a recorder. * * @see BeanConfigurator + * @see ExtendedBeanConfigurator#setRuntimeInit() */ public final class SyntheticBeanBuildItem extends MultiBuildItem { @@ -83,9 +84,14 @@ public ExtendedBeanConfigurator runtimeValue(RuntimeValue> runtimeValue) { /** * By default, synthetic beans are initialized during {@link ExecutionTime#STATIC_INIT}. It is possible to mark a * synthetic bean to be initialized during {@link ExecutionTime#RUNTIME_INIT}. However, in such case a client that - * attempts to obtain such bean during {@link ExecutionTime#STATIC_INIT} will receive an exception. + * attempts to obtain such bean during {@link ExecutionTime#STATIC_INIT} or before runtime-init synthetic beans are + * initialized will receive an exception. + *
+ * {@link ExecutionTime#RUNTIME_INIT} build steps that access a runtime-init synthetic bean should consume the
+ * {@link SyntheticBeansRuntimeInitBuildItem}.
*
* @return self
+ * @see SyntheticBeansRuntimeInitBuildItem
*/
public ExtendedBeanConfigurator setRuntimeInit() {
this.staticInit = false;
diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeansProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeansProcessor.java
index 0498d1d218cb6..857bec58f595b 100644
--- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeansProcessor.java
+++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/SyntheticBeansProcessor.java
@@ -70,7 +70,7 @@ private void initSyntheticBean(ArcRecorder recorder, Map