6565import io .quarkus .deployment .builditem .ConfigPropertiesBuildItem ;
6666import io .quarkus .deployment .builditem .ConfigurationBuildItem ;
6767import io .quarkus .deployment .builditem .GeneratedClassBuildItem ;
68+ import io .quarkus .deployment .builditem .ServiceStartBuildItem ;
6869import io .quarkus .deployment .builditem .nativeimage .ReflectiveClassBuildItem ;
6970import io .quarkus .deployment .builditem .nativeimage .ReflectiveMethodBuildItem ;
7071import io .quarkus .deployment .pkg .NativeConfig ;
@@ -451,15 +452,28 @@ void validateConfigPropertiesInjectionPoints(
451452 toRegister .forEach (configProperties ::produce );
452453 }
453454
455+ /**
456+ * Registers the {@link org.eclipse.microprofile.config.inject.ConfigProperties} beans after
457+ * the creation of {@link io.smallrye.config.SmallRyeConfig}. It should be possible to register these in the config
458+ * builder during build time, but unfortunately the MP Config TCK requires to throw a
459+ * {@link jakarta.enterprise.inject.spi.DeploymentException} when a
460+ * {@link org.eclipse.microprofile.config.inject.ConfigProperties} bean cannot be initialized (due to missing
461+ * configuration). When {@link io.smallrye.config.SmallRyeConfig} cannot map a config class, it throws a
462+ * {@link io.smallrye.config.ConfigValidationException}. The recorder catches this exception and throws the
463+ * expected {@link jakarta.enterprise.inject.spi.DeploymentException}.
464+ */
454465 @ BuildStep
455466 @ Record (RUNTIME_INIT )
456467 void registerConfigClasses (
457468 RecorderContext context ,
458469 ConfigRecorder recorder ,
459- List <ConfigMappingBuildItem > configMappings ,
460- List <ConfigPropertiesBuildItem > configProperties ) throws Exception {
470+ List <ConfigPropertiesBuildItem > configProperties ,
471+ BuildProducer <ServiceStartBuildItem > serviceStart ) throws Exception {
472+
473+ if (configProperties .isEmpty ()) {
474+ return ;
475+ }
461476
462- // TODO - Register ConfigProperties during build time
463477 context .registerNonDefaultConstructor (
464478 ConfigClass .class .getDeclaredConstructor (Class .class , String .class ),
465479 configClass -> Stream .of (configClass .getType (), configClass .getPrefix ())
@@ -469,6 +483,9 @@ void registerConfigClasses(
469483 configProperties .stream ()
470484 .map (p -> configClass (p .getConfigClass (), p .getPrefix ()))
471485 .collect (toSet ()));
486+
487+ // Ensure that @ConfigProperties are registered before Startup events
488+ serviceStart .produce (new ServiceStartBuildItem ("microprofile-config-properties" ));
472489 }
473490
474491 private static String getPropertyName (String name , ClassInfo declaringClass ) {
0 commit comments