From 6f407c82b51e88528359ff771fa2015176bd38c0 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Tue, 26 Sep 2023 17:32:09 +0200 Subject: [PATCH 1/2] Config: injection verification during the native image build - verify the current ImageMode when a config object is injected - fail if injected during the static initialization phase of a native image build --- .../arc/deployment/ConfigBuildStep.java | 12 +- .../ConfigInjectionStaticInitBuildItem.java | 6 + .../deployment/NativeBuildConfigSteps.java | 73 +++++++++++ .../arc/test/config/nativebuild/Fail.java | 19 +++ .../NativeBuildConfigInjectionFailTest.java | 24 ++++ .../NativeBuildConfigInjectionOkTest.java | 19 +++ .../arc/test/config/nativebuild/Ok.java | 22 ++++ .../quarkus/arc/config/NativeBuildTime.java | 20 +++ .../arc/runtime/ConfigMappingCreator.java | 5 + .../arc/runtime/NativeBuildConfigCheck.java | 20 +++ .../NativeBuildConfigCheckInterceptor.java | 114 ++++++++++++++++++ .../arc/runtime/NativeBuildConfigContext.java | 18 +++ .../NativeBuildConfigContextCreator.java | 22 ++++ 13 files changed, 371 insertions(+), 3 deletions(-) create mode 100644 extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/NativeBuildConfigSteps.java create mode 100644 extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Fail.java create mode 100644 extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionFailTest.java create mode 100644 extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionOkTest.java create mode 100644 extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Ok.java create mode 100644 extensions/arc/runtime/src/main/java/io/quarkus/arc/config/NativeBuildTime.java create mode 100644 extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheck.java create mode 100644 extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheckInterceptor.java create mode 100644 extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContext.java create mode 100644 extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContextCreator.java diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java index af7ad71af9a81..254c2d04fbbf6 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java @@ -70,6 +70,7 @@ import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.configuration.definition.RootDefinition; +import io.quarkus.deployment.pkg.PackageConfig; import io.quarkus.deployment.recording.RecorderContext; import io.quarkus.gizmo.ResultHandle; import io.quarkus.runtime.annotations.ConfigPhase; @@ -83,7 +84,7 @@ public class ConfigBuildStep { private static final Logger LOGGER = Logger.getLogger(ConfigBuildStep.class.getName()); private static final DotName MP_CONFIG = DotName.createSimple(Config.class.getName()); - private static final DotName MP_CONFIG_PROPERTY_NAME = DotName.createSimple(ConfigProperty.class.getName()); + static final DotName MP_CONFIG_PROPERTY_NAME = DotName.createSimple(ConfigProperty.class.getName()); private static final DotName MP_CONFIG_PROPERTIES_NAME = DotName.createSimple(ConfigProperties.class.getName()); private static final DotName MP_CONFIG_VALUE_NAME = DotName.createSimple(ConfigValue.class.getName()); @@ -290,6 +291,7 @@ void registerConfigMappingsBean( BeanRegistrationPhaseBuildItem beanRegistration, List configClasses, CombinedIndexBuildItem combinedIndex, + PackageConfig packageConfig, BuildProducer beanConfigurator) { if (configClasses.isEmpty()) { @@ -323,7 +325,8 @@ void registerConfigMappingsBean( .creator(ConfigMappingCreator.class) .addInjectionPoint(ClassType.create(DotNames.INJECTION_POINT)) .param("type", configClass.getConfigClass()) - .param("prefix", configClass.getPrefix()); + .param("prefix", configClass.getPrefix()) + .param("nativeBuild", packageConfig.type.equalsIgnoreCase(PackageConfig.BuiltInType.NATIVE.getValue())); if (configClass.getConfigClass().isAnnotationPresent(Unremovable.class)) { bean.unremovable(); @@ -338,6 +341,7 @@ void registerConfigPropertiesBean( BeanRegistrationPhaseBuildItem beanRegistration, List configClasses, CombinedIndexBuildItem combinedIndex, + PackageConfig packageConfig, BuildProducer beanConfigurator) { if (configClasses.isEmpty()) { @@ -371,7 +375,9 @@ void registerConfigPropertiesBean( .creator(ConfigMappingCreator.class) .addInjectionPoint(ClassType.create(DotNames.INJECTION_POINT)) .param("type", configClass.getConfigClass()) - .param("prefix", configClass.getPrefix()))); + .param("prefix", configClass.getPrefix()) + .param("nativeBuild", + packageConfig.type.equalsIgnoreCase(PackageConfig.BuiltInType.NATIVE.getValue())))); } } diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java index efb1919e33b02..d3674722fa64b 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java @@ -4,7 +4,13 @@ import io.quarkus.builder.item.MultiBuildItem; +/** + * + * @deprecated TODO + */ +@Deprecated(forRemoval = true) public final class ConfigInjectionStaticInitBuildItem extends MultiBuildItem { + private final DotName declaringCandidate; public ConfigInjectionStaticInitBuildItem(final DotName declaringCandidate) { diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/NativeBuildConfigSteps.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/NativeBuildConfigSteps.java new file mode 100644 index 0000000000000..51a14bfbc372b --- /dev/null +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/NativeBuildConfigSteps.java @@ -0,0 +1,73 @@ +package io.quarkus.arc.deployment; + +import java.util.HashSet; +import java.util.Set; + +import jakarta.inject.Singleton; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; + +import io.quarkus.arc.processor.AnnotationsTransformer; +import io.quarkus.arc.processor.DotNames; +import io.quarkus.arc.processor.InjectionPointInfo; +import io.quarkus.arc.runtime.NativeBuildConfigCheck; +import io.quarkus.arc.runtime.NativeBuildConfigCheckInterceptor; +import io.quarkus.arc.runtime.NativeBuildConfigContext; +import io.quarkus.arc.runtime.NativeBuildConfigContextCreator; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.ConfigurationBuildItem; +import io.quarkus.deployment.pkg.steps.NativeBuild; + +public class NativeBuildConfigSteps { + + @BuildStep(onlyIf = NativeBuild.class) + SyntheticBeanBuildItem registerNativeBuildConfigContext(ConfigurationBuildItem config, + BeanDiscoveryFinishedBuildItem beanDiscoveryFinished) { + + // Collect all @ConfigProperty injection points + Set injectedProperties = new HashSet<>(); + for (InjectionPointInfo injectionPoint : beanDiscoveryFinished.getInjectionPoints()) { + if (injectionPoint.hasDefaultedQualifier()) { + continue; + } + AnnotationInstance configProperty = injectionPoint.getRequiredQualifier(ConfigBuildStep.MP_CONFIG_PROPERTY_NAME); + if (configProperty != null) { + injectedProperties.add(configProperty.value("name").asString()); + } + } + + // Retain only BUILD_AND_RUN_TIME_FIXED properties + injectedProperties.retainAll(config.getReadResult().getBuildTimeRunTimeValues().keySet()); + + return SyntheticBeanBuildItem.configure(NativeBuildConfigContext.class) + .param( + "buildAndRunTimeFixed", + injectedProperties.toArray(String[]::new)) + .creator(NativeBuildConfigContextCreator.class) + .scope(Singleton.class) + .done(); + + } + + @BuildStep(onlyIf = NativeBuild.class) + AdditionalBeanBuildItem registerBeans() { + return AdditionalBeanBuildItem.builder().addBeanClasses(NativeBuildConfigCheckInterceptor.class, + NativeBuildConfigCheck.class).build(); + } + + @BuildStep(onlyIf = NativeBuild.class) + AnnotationsTransformerBuildItem transformConfigProducer() { + DotName configProducerName = DotName.createSimple("io.smallrye.config.inject.ConfigProducer"); + + return new AnnotationsTransformerBuildItem(AnnotationsTransformer.appliedToMethod().whenMethod(m -> { + // Apply to all producer methods declared on io.smallrye.config.inject.ConfigProducer + return m.declaringClass().name().equals(configProducerName) + && m.hasAnnotation(DotNames.PRODUCES) + && m.hasAnnotation(ConfigBuildStep.MP_CONFIG_PROPERTY_NAME); + }).thenTransform(t -> { + t.add(NativeBuildConfigCheck.class); + })); + } + +} diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Fail.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Fail.java new file mode 100644 index 0000000000000..a3096528e7efb --- /dev/null +++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Fail.java @@ -0,0 +1,19 @@ +package io.quarkus.arc.test.config.nativebuild; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Singleton; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +@Singleton +public class Fail { + + @ConfigProperty(name = "foo", defaultValue = "bar") + String value; + + // triggers init during static init of native build + void init(@Observes @Initialized(ApplicationScoped.class) Object event) { + } +} diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionFailTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionFailTest.java new file mode 100644 index 0000000000000..b3887176251a6 --- /dev/null +++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionFailTest.java @@ -0,0 +1,24 @@ +package io.quarkus.arc.test.config.nativebuild; + +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusProdModeTest; + +public class NativeBuildConfigInjectionFailTest { + + @RegisterExtension + static final QuarkusProdModeTest TEST = new QuarkusProdModeTest() + .setBuildNative(true) + .withApplicationRoot( + root -> root.addClass(Fail.class)) + // ImageGenerationFailureException is private + .setExpectedException(RuntimeException.class); + + @Test + void test() { + fail(); + } +} diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionOkTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionOkTest.java new file mode 100644 index 0000000000000..ce36e86a4ebae --- /dev/null +++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionOkTest.java @@ -0,0 +1,19 @@ +package io.quarkus.arc.test.config.nativebuild; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import io.quarkus.test.QuarkusProdModeTest; + +public class NativeBuildConfigInjectionOkTest { + + @RegisterExtension + static final QuarkusProdModeTest TEST = new QuarkusProdModeTest() + .setBuildNative(true) + .withApplicationRoot( + root -> root.addClass(Ok.class)); + + @Test + void test() { + } +} diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Ok.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Ok.java new file mode 100644 index 0000000000000..c92db100e5b32 --- /dev/null +++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Ok.java @@ -0,0 +1,22 @@ +package io.quarkus.arc.test.config.nativebuild; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Initialized; +import jakarta.enterprise.event.Observes; +import jakarta.inject.Singleton; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import io.quarkus.arc.config.NativeBuildTime; + +@Singleton +public class Ok { + + @NativeBuildTime + @ConfigProperty(name = "foo", defaultValue = "bar") + String value; + + // triggers init during static init of native build + void init(@Observes @Initialized(ApplicationScoped.class) Object event) { + } +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/config/NativeBuildTime.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/config/NativeBuildTime.java new file mode 100644 index 0000000000000..132ab2bbcc00c --- /dev/null +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/config/NativeBuildTime.java @@ -0,0 +1,20 @@ +package io.quarkus.arc.config; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * A config property injected during the static initialization phase of a native image build may result in unexpected errors + * because the injected value was obtained at build time and cannot be updated at runtime. + *

+ * If it's intentional and expected then use this annotation to eliminate the false positive. + */ +@Retention(RUNTIME) +@Target({ FIELD, PARAMETER }) +public @interface NativeBuildTime { + +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/ConfigMappingCreator.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/ConfigMappingCreator.java index 98d572aadfc9f..c3fea0a37f816 100644 --- a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/ConfigMappingCreator.java +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/ConfigMappingCreator.java @@ -2,6 +2,7 @@ import java.lang.annotation.Annotation; import java.util.Optional; +import java.util.Set; import jakarta.enterprise.inject.spi.Annotated; import jakarta.enterprise.inject.spi.InjectionPoint; @@ -23,6 +24,10 @@ public Object create(SyntheticCreationalContext context) { throw new IllegalStateException("No current injection point found"); } + if ((boolean) context.getParams().get("nativeBuild")) { + NativeBuildConfigCheckInterceptor.verifyCurrentImageMode(Set.of()); + } + Class interfaceType = (Class) context.getParams().get("type"); String prefix = (String) context.getParams().get("prefix"); diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheck.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheck.java new file mode 100644 index 0000000000000..6528b0de43f59 --- /dev/null +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheck.java @@ -0,0 +1,20 @@ +package io.quarkus.arc.runtime; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.interceptor.InterceptorBinding; + +/** + * Interceptor binding for {@link NativeBuildConfigCheckInterceptor}. + */ +@InterceptorBinding +@Retention(RUNTIME) +@Target({ TYPE, METHOD }) +public @interface NativeBuildConfigCheck { + +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheckInterceptor.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheckInterceptor.java new file mode 100644 index 0000000000000..9ef81300a8bfe --- /dev/null +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheckInterceptor.java @@ -0,0 +1,114 @@ +package io.quarkus.arc.runtime; + +import java.lang.annotation.Annotation; +import java.util.Set; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.spi.Annotated; +import jakarta.enterprise.inject.spi.AnnotatedConstructor; +import jakarta.enterprise.inject.spi.AnnotatedField; +import jakarta.enterprise.inject.spi.AnnotatedParameter; +import jakarta.enterprise.inject.spi.InjectionPoint; +import jakarta.inject.Inject; +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InvocationContext; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.jboss.logging.Logger; + +import io.quarkus.arc.config.NativeBuildTime; +import io.quarkus.arc.impl.InjectionPointProvider; +import io.quarkus.runtime.ImageMode; + +/** + * The goal of this interceptor is to verify the current ImageMode when a dependent config property is being injected. + */ +@Priority(jakarta.interceptor.Interceptor.Priority.PLATFORM_BEFORE) +@Interceptor +@NativeBuildConfigCheck +public class NativeBuildConfigCheckInterceptor { + + private static final Logger LOG = Logger.getLogger(NativeBuildConfigCheckInterceptor.class); + + @Inject + NativeBuildConfigContext nativeBuildConfigContext; + + @AroundInvoke + Object aroundInvoke(InvocationContext context) throws Exception { + verifyCurrentImageMode(nativeBuildConfigContext.getBuildAndRunTimeFixed()); + return context.proceed(); + } + + static void verifyCurrentImageMode(Set buildAndRunTimeFixed) { + if (ImageMode.current() != ImageMode.NATIVE_BUILD) { + return; + } + InjectionPoint injectionPoint = InjectionPointProvider.get(); + if (injectionPoint != null) { + // Skip injection points annotated with NativeBuildTime + Annotated annotated = injectionPoint.getAnnotated(); + if (annotated != null && annotated.isAnnotationPresent(NativeBuildTime.class)) { + return; + } + // Skip BUILD_AND_RUN_TIME_FIXED properties + if (!buildAndRunTimeFixed.isEmpty()) { + String propertyName = null; + for (Annotation qualifier : injectionPoint.getQualifiers()) { + if (qualifier instanceof ConfigProperty) { + propertyName = ((ConfigProperty) qualifier).name(); + } + } + if (propertyName != null && buildAndRunTimeFixed.contains(propertyName)) { + return; + } + } + } + StringBuilder b = new StringBuilder(); + b.append("\n\n"); + b.append("=".repeat(120)); + b.append("\nPOSSIBLE CONFIG INJECTION PROBLEM DETECTED\n"); + b.append("-".repeat(120)); + b.append("\nA config object was injected during the static initialization phase of a native image build.\n"); + b.append( + "This may result in unexpected errors.\n"); + b.append("The injected value was obtained at native image build time and cannot be updated at runtime.\n\n"); + if (injectionPoint != null) { + b.append("Injection point: "); + b.append(injectionPointToString(injectionPoint)); + b.append("\n"); + } + b.append("Solutions:\n"); + b.append("\t- If that's intentional then annotate the injected field/parameter with @"); + b.append(NativeBuildTime.class.getName()); + b.append(" to eliminate the false positive\n"); + b.append( + "\t- You can leverage the programmatic lookup to delay the retrieval of a config property; for example '@ConfigProperty(name = \"foo\") Instance foo'\n"); + b.append( + "\t- You can try to use a normal CDI scope (e.g. @ApplicationScoped) to initialize the bean lazily; this may help if the is only injected but not directly used during the static initialization phase"); + b.append("\n"); + b.append("=".repeat(120)); + b.append("\n\n"); + + LOG.error(b.toString()); + throw new IllegalStateException( + "POSSIBLE CONFIG INJECTION PROBLEM DETECTED: a config object was injected during the static initialization phase of a native image build. See the error message above for more details."); + } + + private static String injectionPointToString(InjectionPoint injectionPoint) { + Annotated annotated = injectionPoint.getAnnotated(); + if (annotated instanceof AnnotatedField) { + AnnotatedField field = (AnnotatedField) annotated; + return field.getDeclaringType().getJavaClass().getName() + "#" + field.getJavaMember().getName(); + } else if (annotated instanceof AnnotatedParameter) { + AnnotatedParameter param = (AnnotatedParameter) annotated; + if (param.getDeclaringCallable() instanceof AnnotatedConstructor) { + return param.getDeclaringCallable().getDeclaringType().getJavaClass().getName() + "()"; + } else { + return param.getDeclaringCallable().getDeclaringType().getJavaClass().getName() + "#" + + param.getDeclaringCallable().getJavaMember().getName() + "()"; + } + } + return injectionPoint.toString(); + } +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContext.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContext.java new file mode 100644 index 0000000000000..b5377cff2b718 --- /dev/null +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContext.java @@ -0,0 +1,18 @@ +package io.quarkus.arc.runtime; + +import java.util.Set; + +import io.quarkus.arc.config.NativeBuildTime; + +/** + * @see NativeBuildTime + * @see NativeBuildConfigCheckInterceptor + */ +public interface NativeBuildConfigContext { + + /** + * + * @return the injected BUILD_AND_RUN_TIME_FIXED properties + */ + Set getBuildAndRunTimeFixed(); +} diff --git a/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContextCreator.java b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContextCreator.java new file mode 100644 index 0000000000000..297ad94ec42c4 --- /dev/null +++ b/extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigContextCreator.java @@ -0,0 +1,22 @@ +package io.quarkus.arc.runtime; + +import java.util.Set; + +import io.quarkus.arc.BeanCreator; +import io.quarkus.arc.SyntheticCreationalContext; + +public class NativeBuildConfigContextCreator implements BeanCreator { + + @Override + public NativeBuildConfigContext create(SyntheticCreationalContext context) { + Set buildAndRunTimeFixed = Set.of((String[]) context.getParams().get("buildAndRunTimeFixed")); + return new NativeBuildConfigContext() { + + @Override + public Set getBuildAndRunTimeFixed() { + return buildAndRunTimeFixed; + } + }; + } + +} From db78fb2ba4f037f765c6236b3ac9be027919be3b Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Wed, 27 Sep 2023 14:16:50 +0200 Subject: [PATCH 2/2] Config: remove the warning for ConfigInjectionStaticInitBuildItem - deprecate ConfigInjectionStaticInitBuildItem --- .../arc/deployment/ConfigBuildStep.java | 68 ------------------- .../ConfigInjectionStaticInitBuildItem.java | 2 +- .../deployment/ResteasyCommonProcessor.java | 6 -- .../deployment/UndertowBuildStep.java | 6 -- 4 files changed, 1 insertion(+), 81 deletions(-) diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java index 254c2d04fbbf6..313f679dacd81 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java @@ -30,7 +30,6 @@ import jakarta.enterprise.context.Dependent; import jakarta.enterprise.inject.CreationException; -import org.eclipse.microprofile.config.Config; import org.eclipse.microprofile.config.ConfigValue; import org.eclipse.microprofile.config.inject.ConfigProperties; import org.eclipse.microprofile.config.inject.ConfigProperty; @@ -42,10 +41,8 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.FieldInfo; import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.ParameterizedType; import org.jboss.jandex.Type; import org.jboss.jandex.Type.Kind; -import org.jboss.logging.Logger; import io.quarkus.arc.Unremovable; import io.quarkus.arc.deployment.BeanRegistrationPhaseBuildItem.BeanConfiguratorBuildItem; @@ -67,7 +64,6 @@ import io.quarkus.deployment.builditem.ConfigPropertiesBuildItem; import io.quarkus.deployment.builditem.ConfigurationBuildItem; import io.quarkus.deployment.builditem.GeneratedClassBuildItem; -import io.quarkus.deployment.builditem.RunTimeConfigurationDefaultBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.configuration.definition.RootDefinition; import io.quarkus.deployment.pkg.PackageConfig; @@ -81,14 +77,11 @@ * MicroProfile Config related build steps. */ public class ConfigBuildStep { - private static final Logger LOGGER = Logger.getLogger(ConfigBuildStep.class.getName()); - private static final DotName MP_CONFIG = DotName.createSimple(Config.class.getName()); static final DotName MP_CONFIG_PROPERTY_NAME = DotName.createSimple(ConfigProperty.class.getName()); private static final DotName MP_CONFIG_PROPERTIES_NAME = DotName.createSimple(ConfigProperties.class.getName()); private static final DotName MP_CONFIG_VALUE_NAME = DotName.createSimple(ConfigValue.class.getName()); - private static final DotName SR_CONFIG = DotName.createSimple(io.smallrye.config.SmallRyeConfig.class.getName()); private static final DotName SR_CONFIG_VALUE_NAME = DotName.createSimple(io.smallrye.config.ConfigValue.class.getName()); private static final DotName MAP_NAME = DotName.createSimple(Map.class.getName()); @@ -480,67 +473,6 @@ void validateConfigPropertiesInjectionPoints( toRegister.forEach(configProperties::produce); } - @BuildStep - void warnStaticInitInjectionPoints( - CombinedIndexBuildItem indexBuildItem, - ValidationPhaseBuildItem validationPhase, - List configClasses, - List configInjectionStaticInit, - BuildProducer runTimeConfigurationDefault) { - - // Add here annotated classes that are initialized during static init - Set declaringClassCandidates = configInjectionStaticInit.stream() - .map(ConfigInjectionStaticInitBuildItem::getDeclaringCandidate).collect(toSet()); - - Set configClassesTypes = configClasses.stream().map(ConfigClassBuildItem::getTypes).flatMap(Collection::stream) - .collect(toSet()); - - for (InjectionPointInfo injectionPoint : validationPhase.getContext().getInjectionPoints()) { - if (injectionPoint.getType().name().equals(DotNames.INSTANCE)) { - continue; - } - - Type type = Type.create(injectionPoint.getRequiredType().name(), Type.Kind.CLASS); - DotName injectionTypeName = null; - if (type.name().equals(MP_CONFIG) || type.name().equals(SR_CONFIG)) { - injectionTypeName = type.name(); - } else if (injectionPoint.getRequiredQualifier(MP_CONFIG_PROPERTY_NAME) != null) { - injectionTypeName = MP_CONFIG_PROPERTY_NAME; - } else if (configClassesTypes.contains(type)) { - injectionTypeName = type.name(); - } - - if (injectionTypeName != null) { - AnnotationTarget target = injectionPoint.getTarget(); - if (FIELD.equals(target.kind())) { - FieldInfo field = target.asField(); - ClassInfo declaringClass = field.declaringClass(); - Map> annotationsMap = declaringClass.annotationsMap(); - for (DotName declaringClassCandidate : declaringClassCandidates) { - List annotationInstances = annotationsMap.get(declaringClassCandidate); - if (annotationInstances != null && annotationInstances.size() == 1) { - AnnotationInstance annotationInstance = annotationInstances.get(0); - if (annotationInstance.target().equals(declaringClass)) { - LOGGER.warn("Directly injecting a " + - injectionTypeName + - " into a " + - declaringClassCandidate + - " may lead to unexpected results. To ensure proper results, please " + - "change the type of the field to " + - ParameterizedType.create(DotNames.INSTANCE, new Type[] { type }, null) + - ". Offending field is '" + - field.name() + - "' of class '" + - field.declaringClass() + - "'"); - } - } - } - } - } - } - } - @BuildStep @Record(RUNTIME_INIT) void registerConfigClasses( diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java index d3674722fa64b..9582c46fbbd5b 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigInjectionStaticInitBuildItem.java @@ -6,7 +6,7 @@ /** * - * @deprecated TODO + * @deprecated This build item is not used anymore */ @Deprecated(forRemoval = true) public final class ConfigInjectionStaticInitBuildItem extends MultiBuildItem { diff --git a/extensions/resteasy-classic/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java b/extensions/resteasy-classic/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java index de8247f62696b..b78d5eec48b58 100644 --- a/extensions/resteasy-classic/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java +++ b/extensions/resteasy-classic/resteasy-common/deployment/src/main/java/io/quarkus/resteasy/common/deployment/ResteasyCommonProcessor.java @@ -43,7 +43,6 @@ import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem; import io.quarkus.arc.deployment.BeanContainerBuildItem; -import io.quarkus.arc.deployment.ConfigInjectionStaticInitBuildItem; import io.quarkus.arc.deployment.UnremovableBeanBuildItem; import io.quarkus.arc.processor.DotNames; import io.quarkus.deployment.Capabilities; @@ -181,11 +180,6 @@ ResteasyInjectionReadyBuildItem setupResteasyInjection( return new ResteasyInjectionReadyBuildItem(injectorFactory); } - @BuildStep - ConfigInjectionStaticInitBuildItem configInjectionStaticInitProvider() { - return new ConfigInjectionStaticInitBuildItem(ResteasyDotNames.PROVIDER); - } - @BuildStep JaxrsProvidersToRegisterBuildItem setupProviders(BuildProducer reflectiveClass, CombinedIndexBuildItem indexBuildItem, diff --git a/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java b/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java index 06fd8dd5d7169..415204b0d4fc2 100644 --- a/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java +++ b/extensions/undertow/deployment/src/main/java/io/quarkus/undertow/deployment/UndertowBuildStep.java @@ -81,7 +81,6 @@ import io.quarkus.arc.deployment.AdditionalBeanBuildItem; import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; import io.quarkus.arc.deployment.BeanContainerBuildItem; -import io.quarkus.arc.deployment.ConfigInjectionStaticInitBuildItem; import io.quarkus.arc.deployment.ContextRegistrationPhaseBuildItem; import io.quarkus.arc.deployment.ContextRegistrationPhaseBuildItem.ContextConfiguratorBuildItem; import io.quarkus.arc.deployment.CustomScopeBuildItem; @@ -685,11 +684,6 @@ SyntheticBeanBuildItem servletContextBean( .supplier(recorder.servletContextSupplier()).done(); } - @BuildStep - ConfigInjectionStaticInitBuildItem configInjectionStaticInitAnnotations() { - return new ConfigInjectionStaticInitBuildItem(WEB_FILTER); - } - /** * Process a single index. *