-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
13 changed files
with
370 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
...nsions/arc/deployment/src/main/java/io/quarkus/arc/deployment/NativeBuildConfigSteps.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<String> 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); | ||
})); | ||
} | ||
|
||
} |
19 changes: 19 additions & 0 deletions
19
extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Fail.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) { | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
.../test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionFailTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...rc/test/java/io/quarkus/arc/test/config/nativebuild/NativeBuildConfigInjectionOkTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() { | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
extensions/arc/deployment/src/test/java/io/quarkus/arc/test/config/nativebuild/Ok.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) { | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
extensions/arc/runtime/src/main/java/io/quarkus/arc/config/NativeBuildTime.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. | ||
* <p> | ||
* If it's intentional and expected then use this annotation to eliminate the false positive. | ||
*/ | ||
@Retention(RUNTIME) | ||
@Target({ FIELD, PARAMETER }) | ||
public @interface NativeBuildTime { | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
extensions/arc/runtime/src/main/java/io/quarkus/arc/runtime/NativeBuildConfigCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 { | ||
|
||
} |
Oops, something went wrong.