From 96574d04f5dc22a7fd930062b9a7ef733e9002f6 Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Wed, 5 May 2021 09:36:00 +1000 Subject: [PATCH] Enable synthetic beans to be application classes Even if the superclass is not ann application class if the generated bytecode references application classes then it may be nessesary for the synthetic bean to be an application class. --- .../deployment/SyntheticBeanBuildItem.java | 1 - .../arc/processor/BeanConfigurator.java | 1 + .../arc/processor/BeanConfiguratorBase.java | 13 +++++++++++++ .../quarkus/arc/processor/BeanGenerator.java | 9 +++++---- .../io/quarkus/arc/processor/BeanInfo.java | 19 ++++++++++++++++--- 5 files changed, 35 insertions(+), 8 deletions(-) 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 26d614e751315..5c3be13e7017c 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 @@ -141,6 +141,5 @@ Supplier getSupplier() { RuntimeValue getRuntimeValue() { return runtimeValue; } - } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java index 0d4e41ce96c1d..be64a8b40bf5b 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfigurator.java @@ -62,6 +62,7 @@ public void done() { .params(params) .defaultBean(defaultBean) .removable(removable) + .forceApplicationClass(forceApplicationClass) .build()); } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java index c5f30c1e8b1b4..0a4e3f244fefb 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanConfiguratorBase.java @@ -40,6 +40,7 @@ public abstract class BeanConfiguratorBase, protected boolean removable; protected final Map params; protected Type providerType; + protected boolean forceApplicationClass; protected BeanConfiguratorBase(DotName implClazz) { this.implClazz = implClazz; @@ -63,6 +64,7 @@ public B read(BeanConfiguratorBase base) { types.addAll(base.types); qualifiers.clear(); qualifiers.addAll(base.qualifiers); + forceApplicationClass = base.forceApplicationClass; scope(base.scope); if (base.alternativePriority != null) { alternativePriority(base.alternativePriority); @@ -171,6 +173,17 @@ public B unremovable() { return self(); } + /** + * Forces the bean to be considered an 'application class', so it will be defined in the runtime + * ClassLoader and re-created on each redeployment. + * + * @return self + */ + public B forceApplicationClass() { + this.forceApplicationClass = true; + return self(); + } + public B alternativePriority(int priority) { this.alternativePriority = priority; return self(); diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java index e6ff29894500b..abec759713caa 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java @@ -150,7 +150,8 @@ Collection generateSyntheticBean(BeanInfo bean) { return Collections.emptyList(); } - boolean isApplicationClass = applicationClassPredicate.test(bean.getImplClazz().name()); + boolean isApplicationClass = applicationClassPredicate.test(bean.getImplClazz().name()) + || bean.isForceApplicationClass(); ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass, name -> name.equals(generatedName) ? SpecialType.BEAN : null, generateSources); @@ -267,7 +268,7 @@ Collection generateClassBean(BeanInfo bean, ClassInfo beanClass) { return Collections.emptyList(); } - boolean isApplicationClass = applicationClassPredicate.test(beanClass.name()); + boolean isApplicationClass = applicationClassPredicate.test(beanClass.name()) || bean.isForceApplicationClass(); ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass, name -> name.equals(generatedName) ? SpecialType.BEAN : null, generateSources); @@ -373,7 +374,7 @@ Collection generateProducerMethodBean(BeanInfo bean, MethodInfo produc return Collections.emptyList(); } - boolean isApplicationClass = applicationClassPredicate.test(declaringClass.name()); + boolean isApplicationClass = applicationClassPredicate.test(declaringClass.name()) || bean.isForceApplicationClass(); ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass, name -> name.equals(generatedName) ? SpecialType.BEAN : null, generateSources); @@ -465,7 +466,7 @@ Collection generateProducerFieldBean(BeanInfo bean, FieldInfo producer return Collections.emptyList(); } - boolean isApplicationClass = applicationClassPredicate.test(declaringClass.name()); + boolean isApplicationClass = applicationClassPredicate.test(declaringClass.name()) || bean.isForceApplicationClass(); ResourceClassOutput classOutput = new ResourceClassOutput(isApplicationClass, name -> name.equals(generatedName) ? SpecialType.BEAN : null, generateSources); diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java index 960b7ae59ccd7..43a6b4647ff26 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java @@ -83,6 +83,8 @@ public class BeanInfo implements InjectionTargetInfo { private final Map params; + private final boolean forceApplicationClass; + BeanInfo(AnnotationTarget target, BeanDeployment beanDeployment, ScopeInfo scope, Set types, Set qualifiers, List injections, BeanInfo declaringBean, DisposerInfo disposer, Integer alternativePriority, @@ -91,7 +93,7 @@ public class BeanInfo implements InjectionTargetInfo { this(null, null, target, beanDeployment, scope, types, qualifiers, injections, declaringBean, disposer, alternativePriority, stereotypes, name, isDefaultBean, null, null, - Collections.emptyMap(), true); + Collections.emptyMap(), true, false); } BeanInfo(ClassInfo implClazz, Type providerType, AnnotationTarget target, BeanDeployment beanDeployment, ScopeInfo scope, @@ -101,7 +103,7 @@ public class BeanInfo implements InjectionTargetInfo { List stereotypes, String name, boolean isDefaultBean, Consumer creatorConsumer, Consumer destroyerConsumer, - Map params, boolean isRemovable) { + Map params, boolean isRemovable, boolean forceApplicationClass) { this.target = Optional.ofNullable(target); if (implClazz == null && target != null) { implClazz = initImplClazz(target, beanDeployment); @@ -140,6 +142,7 @@ public class BeanInfo implements InjectionTargetInfo { this.interceptedMethods = new ConcurrentHashMap<>(); this.decoratedMethods = new ConcurrentHashMap<>(); this.lifecycleInterceptors = new ConcurrentHashMap<>(); + this.forceApplicationClass = forceApplicationClass; } @Override @@ -337,6 +340,10 @@ boolean hasDefaultDestroy() { } } + public boolean isForceApplicationClass() { + return forceApplicationClass; + } + /** * * @return an ordered list of all interceptors associated with the bean @@ -792,6 +799,8 @@ static class Builder { private boolean removable = true; + private boolean forceApplicationClass; + Builder() { injections = Collections.emptyList(); stereotypes = Collections.emptyList(); @@ -890,9 +899,13 @@ Builder removable(boolean val) { BeanInfo build() { return new BeanInfo(implClazz, providerType, target, beanDeployment, scope, types, qualifiers, injections, declaringBean, disposer, alternativePriority, stereotypes, name, isDefaultBean, creatorConsumer, - destroyerConsumer, params, removable); + destroyerConsumer, params, removable, forceApplicationClass); } + public Builder forceApplicationClass(boolean forceApplicationClass) { + this.forceApplicationClass = forceApplicationClass; + return this; + } } }