Skip to content

Commit

Permalink
Merge pull request #27658 from mkouba/bda-default-scope-rework
Browse files Browse the repository at this point in the history
Rework the BeanDefiningAnnotationBuildItem default scope
  • Loading branch information
mkouba committed Sep 1, 2022
2 parents a1f0167 + 8322420 commit e475d18
Show file tree
Hide file tree
Showing 7 changed files with 292 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.quarkus.arc.test.stereotype;
package io.quarkus.arc.test.bda;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;

import java.lang.annotation.Retention;
Expand All @@ -17,6 +18,7 @@
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Stereotype;
import javax.inject.Inject;
import javax.inject.Qualifier;

import org.jboss.jandex.DotName;
import org.junit.jupiter.api.Test;
Expand All @@ -28,12 +30,13 @@
import io.quarkus.builder.BuildStep;
import io.quarkus.test.QuarkusUnitTest;

public class BeanDefiningAnnotationStereotypeTestCase {
public class BeanDefiningAnnotationScopeTest {

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(MyBean.class, MakeItBean.class, DependentStereotype.class))
.withApplicationRoot(root -> root
.addClasses(MyBean.class, AnotherBean.class, YetAnotherBean.class, MakeItBean.class,
QualifierMakeItBean.class, DependentStereotype.class))
.addBuildChainCustomizer(buildCustomizer());

static Consumer<BuildChainBuilder> buildCustomizer() {
Expand All @@ -47,18 +50,38 @@ public void accept(BuildChainBuilder builder) {
public void execute(BuildContext context) {
context.produce(new BeanDefiningAnnotationBuildItem(DotName.createSimple(MakeItBean.class.getName()),
DotName.createSimple(ApplicationScoped.class.getName())));
context.produce(
new BeanDefiningAnnotationBuildItem(DotName.createSimple(QualifierMakeItBean.class.getName()),
DotName.createSimple(ApplicationScoped.class.getName())));
}
}).produces(BeanDefiningAnnotationBuildItem.class).build();
}
};
}

@Inject
Instance<MyBean> instance;
Instance<MyBean> my;

@Inject
Instance<AnotherBean> another;

@Inject
@QualifierMakeItBean
Instance<YetAnotherBean> yetAnother;

@Test
public void test() {
assertNotEquals(instance.get().getId(), instance.get().getId());
public void testExplicitStereotypeScopeWins() {
assertNotEquals(my.get().getId(), my.get().getId());
}

@Test
public void testDefaultScopeIsUsed() {
assertEquals(another.get().getId(), another.get().getId());
}

@Test
public void testQualifierAsBeanDefiningAnnotation() {
assertEquals(yetAnother.get().getId(), yetAnother.get().getId());
}

@DependentStereotype
Expand All @@ -78,11 +101,49 @@ void init() {

}

@MakeItBean
static class AnotherBean {

private String id;

public String getId() {
return id;
}

@PostConstruct
void init() {
this.id = UUID.randomUUID().toString();
}

}

@QualifierMakeItBean
static class YetAnotherBean {

private String id;

public String getId() {
return id;
}

@PostConstruct
void init() {
this.id = UUID.randomUUID().toString();
}

}

@Target({ TYPE, METHOD, FIELD })
@Retention(RUNTIME)
public @interface MakeItBean {
}

@Qualifier
@Target({ TYPE, METHOD, FIELD })
@Retention(RUNTIME)
public @interface QualifierMakeItBean {
}

@Dependent
@Stereotype
@Target({ TYPE, METHOD, FIELD })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ public class BeanDefiningAnnotation {
private final DotName annotation;
private final DotName defaultScope;

public BeanDefiningAnnotation(DotName annotation) {
this(annotation, null);
}

public BeanDefiningAnnotation(DotName annotation, DotName defaultScope) {
this.annotation = annotation;
this.defaultScope = defaultScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public class BeanDeployment {

private final Map<ScopeInfo, Function<MethodCreator, ResultHandle>> customContexts;

private final Collection<BeanDefiningAnnotation> beanDefiningAnnotations;
private final Map<DotName, BeanDefiningAnnotation> beanDefiningAnnotations;

final boolean transformUnproxyableClasses;

Expand All @@ -113,9 +113,11 @@ public class BeanDeployment {

BeanDeployment(BuildContextImpl buildContext, BeanProcessor.Builder builder) {
this.buildContext = buildContext;
Set<BeanDefiningAnnotation> beanDefiningAnnotations = new HashSet<>();
Map<DotName, BeanDefiningAnnotation> beanDefiningAnnotations = new HashMap<>();
if (builder.additionalBeanDefiningAnnotations != null) {
beanDefiningAnnotations.addAll(builder.additionalBeanDefiningAnnotations);
for (BeanDefiningAnnotation bda : builder.additionalBeanDefiningAnnotations) {
beanDefiningAnnotations.put(bda.getAnnotation(), bda);
}
}
this.beanDefiningAnnotations = beanDefiningAnnotations;
this.resourceAnnotations = new HashSet<>(builder.resourceAnnotations);
Expand Down Expand Up @@ -180,8 +182,8 @@ public class BeanDeployment {
additionalStereotypes.addAll(stereotypeRegistrar.getAdditionalStereotypes());
}

this.stereotypes = findStereotypes(this.beanArchiveIndex, interceptorBindings, beanDefiningAnnotations, customContexts,
additionalStereotypes, annotationStore);
this.stereotypes = findStereotypes(this.beanArchiveIndex, interceptorBindings, customContexts, additionalStereotypes,
annotationStore);
buildContextPut(Key.STEREOTYPES.asString(), Collections.unmodifiableMap(stereotypes));

this.transitiveInterceptorBindings = findTransitiveInterceptorBindings(interceptorBindings.keySet(),
Expand Down Expand Up @@ -221,7 +223,8 @@ public ContextConfigurator configure(Class<? extends Annotation> scopeAnnotation
return new ContextConfigurator(scopeAnnotation,
c -> {
ScopeInfo scope = new ScopeInfo(c.scopeAnnotation, c.isNormal);
beanDefiningAnnotations.add(new BeanDefiningAnnotation(scope.getDotName(), null));
beanDefiningAnnotations.put(scope.getDotName(),
new BeanDefiningAnnotation(scope.getDotName(), null));
customContexts.put(scope, c.creator);
});
}
Expand All @@ -242,8 +245,9 @@ void registerScopes() {

BeanRegistrar.RegistrationContext registerBeans(List<BeanRegistrar> beanRegistrars) {
List<InjectionPointInfo> injectionPoints = new ArrayList<>();
this.beans.addAll(findBeans(initBeanDefiningAnnotations(beanDefiningAnnotations, stereotypes.keySet()), observers,
injectionPoints, jtaCapabilities));
this.beans.addAll(
findBeans(initBeanDefiningAnnotations(beanDefiningAnnotations.values(), stereotypes.keySet()), observers,
injectionPoints, jtaCapabilities));
// Note that we use unmodifiable views because the underlying collections may change in the next phase
// E.g. synthetic beans are added and unused interceptors removed
buildContextPut(Key.BEANS.asString(), Collections.unmodifiableList(beans));
Expand Down Expand Up @@ -615,6 +619,10 @@ StereotypeInfo getStereotype(DotName name) {
return stereotypes.get(name);
}

BeanDefiningAnnotation getBeanDefiningAnnotation(DotName name) {
return beanDefiningAnnotations.get(name);
}

Set<DotName> getResourceAnnotations() {
return resourceAnnotations;
}
Expand Down Expand Up @@ -738,7 +746,6 @@ private static Set<AnnotationInstance> recursiveBuild(DotName name,
}

private Map<DotName, StereotypeInfo> findStereotypes(IndexView index, Map<DotName, ClassInfo> interceptorBindings,
Collection<BeanDefiningAnnotation> additionalBeanDefiningAnnotations,
Map<ScopeInfo, Function<MethodCreator, ResultHandle>> customContexts,
Set<DotName> additionalStereotypes, AnnotationStore annotationStore) {

Expand All @@ -756,7 +763,7 @@ private Map<DotName, StereotypeInfo> findStereotypes(IndexView index, Map<DotNam

boolean isAlternative = false;
Integer alternativePriority = null;
List<ScopeInfo> scopes = new ArrayList<>();
Set<ScopeInfo> scopes = new HashSet<>();
List<AnnotationInstance> bindings = new ArrayList<>();
List<AnnotationInstance> parentStereotypes = new ArrayList<>();
boolean isNamed = false;
Expand Down Expand Up @@ -794,25 +801,9 @@ private Map<DotName, StereotypeInfo> findStereotypes(IndexView index, Map<DotNam
final ScopeInfo scope = getValidScope(scopes, stereotypeClass);
boolean isInherited = stereotypeClass.classAnnotation(DotNames.INHERITED) != null;
stereotypes.put(stereotypeName, new StereotypeInfo(scope, bindings, isAlternative, alternativePriority,
isNamed, false, isAdditionalStereotype, stereotypeClass, isInherited, parentStereotypes));
isNamed, isAdditionalStereotype, stereotypeClass, isInherited, parentStereotypes));
}
}
//if an additional bean defining annotation has a default scope we register it as a stereotype
if (additionalBeanDefiningAnnotations != null) {
for (BeanDefiningAnnotation i : additionalBeanDefiningAnnotations) {
if (i.getDefaultScope() != null) {
ScopeInfo scope = getScope(i.getDefaultScope(), customContexts);
ClassInfo stereotypeClassInfo = getClassByName(index, i.getAnnotation());
boolean isInherited = stereotypeClassInfo.classAnnotation(DotNames.INHERITED) != null;
if (stereotypeClassInfo != null) {
stereotypes.put(i.getAnnotation(), new StereotypeInfo(scope, Collections.emptyList(),
false, null, false, true,
false, stereotypeClassInfo, isInherited, Collections.emptyList()));
}
}
}
}

return stereotypes;
}

Expand All @@ -830,15 +821,15 @@ private static ScopeInfo getScope(DotName scopeAnnotationName,
return null;
}

static ScopeInfo getValidScope(Collection<ScopeInfo> stereotypeScopes, AnnotationTarget target) {
switch (stereotypeScopes.size()) {
static ScopeInfo getValidScope(Set<ScopeInfo> scopes, AnnotationTarget target) {
switch (scopes.size()) {
case 0:
return null;
case 1:
return stereotypeScopes.iterator().next();
return scopes.iterator().next();
default:
throw new DefinitionException("All stereotypes must specify the same scope or the bean must declare a scope: "
+ target + " declares scopes " + stereotypeScopes.stream().map(ScopeInfo::getDotName)
throw new DefinitionException(
"Different scopes defined for: " + target + "; scopes: " + scopes.stream().map(ScopeInfo::getDotName)
.map(DotName::toString).collect(Collectors.joining(", ")));
}
}
Expand Down

0 comments on commit e475d18

Please sign in to comment.