Quarkus ArC deployment module providing build-time CDI optimization and configuration capabilities
—
Advanced CDI features provide sophisticated capabilities for interceptors, decorators, observers, custom scopes, and build-time transformations. These features enable deep customization of CDI behavior and advanced architectural patterns.
Transform annotations on CDI components at build time for dynamic behavior modification.
/**
* Transform annotations on CDI components
*/
public class AnnotationsTransformerBuildItem extends MultiBuildItem {
public AnnotationsTransformerBuildItem(AnnotationTransformation transformation);
/**
* Get the annotation transformation
*/
public AnnotationTransformation getAnnotationTransformation();
}
/**
* Annotation transformation interface
*/
public interface AnnotationTransformation {
/**
* Check if this transformation applies to the given class
*/
boolean appliesTo(org.jboss.jandex.ClassInfo clazz);
/**
* Transform annotations on the class
*/
void transform(TransformationContext context);
}
/**
* Context for annotation transformations
*/
public interface TransformationContext {
/**
* Get the target class being transformed
*/
ClassInfo getTarget();
/**
* Transform annotations by adding, removing, or modifying them
*/
Transformation transform();
}Usage Examples:
// Transform service classes to add scopes automatically
@BuildStep
AnnotationsTransformerBuildItem autoScopeServices() {
return new AnnotationsTransformerBuildItem(new AnnotationTransformation() {
@Override
public boolean appliesTo(ClassInfo clazz) {
return clazz.name().toString().endsWith("Service") &&
!clazz.classAnnotation(DotNames.APPLICATION_SCOPED);
}
@Override
public void transform(TransformationContext context) {
context.transform()
.add(ApplicationScoped.class)
.done();
}
});
}
// Add qualifiers based on class packages
@BuildStep
AnnotationsTransformerBuildItem addPackageQualifiers() {
return new AnnotationsTransformerBuildItem(AnnotationTransformation.forClasses()
.whenContains("com.example.core")
.thenTransform(context ->
context.transform().add(createQualifier("Core")).done()));
}Modify injection points at build time to customize dependency injection behavior.
/**
* Transform injection points at build time
*/
public class InjectionPointTransformerBuildItem extends MultiBuildItem {
public InjectionPointTransformerBuildItem(InjectionPointsTransformer transformer);
/**
* Get the injection point transformer
*/
public InjectionPointsTransformer getInjectionPointsTransformer();
}
/**
* Injection point transformer interface
*/
public interface InjectionPointsTransformer {
/**
* Check if this transformer applies to the given injection point
*/
boolean appliesTo(Type requiredType, Set<AnnotationInstance> qualifiers);
/**
* Transform the injection point
*/
void transform(TransformationContext context);
}Usage Examples:
// Transform injection points to add automatic qualifiers
@BuildStep
InjectionPointTransformerBuildItem autoQualifyInjection() {
return new InjectionPointTransformerBuildItem((requiredType, qualifiers, context) -> {
if (requiredType.name().toString().startsWith("com.example.database")) {
context.transform().add(createAnnotation("Database")).done();
}
});
}Handle CDI observer methods and events with build-time processing and validation.
/**
* Transform observer methods at build time
*/
public class ObserverTransformerBuildItem extends MultiBuildItem {
public ObserverTransformerBuildItem(ObserverTransformer transformer);
/**
* Get the observer transformer instance
*/
public ObserverTransformer getInstance();
}
/**
* Observer transformer interface
*/
public interface ObserverTransformer {
/**
* Check if this transformer applies to the observer method
*/
boolean appliesTo(MethodInfo observerMethod, AnnotationInstance observes);
/**
* Transform the observer method
*/
void transform(ObserverTransformationContext context);
}
/**
* Marker for observer registration phase completion
*/
public class ObserverRegistrationPhaseBuildItem extends SimpleBuildItem {
public ObserverRegistrationPhaseBuildItem(BeanProcessor.Builder builder);
public BeanProcessor.Builder getBeanProcessor();
}Usage Examples:
// Transform observers to add transaction support
@BuildStep
ObserverTransformerBuildItem addTransactionalObservers() {
return new ObserverTransformerBuildItem((method, observes, context) -> {
if (method.declaringClass().name().toString().contains("transactional")) {
context.transform().add(Transactional.class).done();
}
});
}Register and configure interceptors and decorators with build-time binding resolution.
/**
* Register custom interceptor binding registrars
*/
public class InterceptorBindingRegistrarBuildItem extends MultiBuildItem {
public InterceptorBindingRegistrarBuildItem(InterceptorBindingRegistrar registrar);
public InterceptorBindingRegistrar getInterceptorBindingRegistrar();
}
/**
* Interceptor binding registrar interface
*/
public interface InterceptorBindingRegistrar {
/**
* Register custom interceptor bindings
*/
void register(RegistrationContext registrationContext);
}
/**
* Interceptor resolver for build-time resolution
*/
public class InterceptorResolverBuildItem extends SimpleBuildItem {
public InterceptorResolverBuildItem(InterceptorResolver resolver);
public InterceptorResolver getInterceptorResolver();
}
/**
* Interceptor resolver interface
*/
public interface InterceptorResolver {
/**
* Resolve interceptors for a given bean
*/
List<InterceptorInfo> resolve(BeanInfo bean);
/**
* Resolve interceptors for a method
*/
List<InterceptorInfo> resolve(MethodInfo method, BeanInfo bean);
}Usage Examples:
// Register custom interceptor bindings
@BuildStep
InterceptorBindingRegistrarBuildItem registerCustomInterceptors() {
return new InterceptorBindingRegistrarBuildItem(context -> {
context.register(DotName.createSimple("com.example.Audit"),
Collections.emptySet());
context.register(DotName.createSimple("com.example.Cache"),
Collections.emptySet());
});
}
// Provide custom interceptor resolver
@BuildStep
InterceptorResolverBuildItem customInterceptorResolver() {
return new InterceptorResolverBuildItem(new InterceptorResolver() {
@Override
public List<InterceptorInfo> resolve(BeanInfo bean) {
// Custom interceptor resolution logic
return resolveCustomInterceptors(bean);
}
});
}Register and manage custom CDI scopes with build-time configuration.
/**
* Register custom CDI scope annotations
*/
public class CustomScopeBuildItem extends MultiBuildItem {
public CustomScopeBuildItem(Class<? extends Annotation> scope);
public CustomScopeBuildItem(DotName annotationName);
/**
* Get the scope annotation name
*/
public DotName getAnnotationName();
}
/**
* Custom scope annotations collection
*/
public class CustomScopeAnnotationsBuildItem extends SimpleBuildItem {
public CustomScopeAnnotationsBuildItem(Set<DotName> scopes);
/**
* Get all registered custom scope annotations
*/
public Set<DotName> getScopes();
}
/**
* Automatically add scope annotations to classes
*/
public class AutoAddScopeBuildItem extends MultiBuildItem {
public static Builder builder();
public boolean isContainerServicesRequired();
public DotName getDefaultScope();
public boolean isUnremovable();
public String getReason();
public int getPriority();
public BiConsumer<DotName, String> getScopeAlreadyAdded();
/**
* Test if this auto-scope rule applies to the given class
*/
public boolean test(ClassInfo clazz, Collection<AnnotationInstance> annotations, IndexView index);
}
/**
* Builder for auto-scope rules
*/
public static class AutoAddScopeBuildItem.Builder {
public Builder containsOne(String... values);
public Builder containsAll(String... values);
public Builder anyOf(MatchPredicate... predicates);
public Builder defaultScope(DotName scope);
public Builder unremovable();
public Builder reason(String reason);
public Builder priority(int priority);
public Builder scopeAlreadyAdded(BiConsumer<DotName, String> consumer);
public AutoAddScopeBuildItem build();
}Usage Examples:
// Register custom scope
@BuildStep
CustomScopeBuildItem registerTenantScope() {
return new CustomScopeBuildItem(TenantScoped.class);
}
// Auto-add scopes based on naming conventions
@BuildStep
AutoAddScopeBuildItem autoScopeByName() {
return AutoAddScopeBuildItem.builder()
.containsOne("Repository", "Service", "Controller")
.defaultScope(DotNames.APPLICATION_SCOPED)
.reason("Auto-scope for service layer classes")
.priority(100)
.build();
}
// Provide all custom scopes
@BuildStep
CustomScopeAnnotationsBuildItem allCustomScopes() {
return new CustomScopeAnnotationsBuildItem(Set.of(
DotName.createSimple("com.example.TenantScoped"),
DotName.createSimple("com.example.RequestScoped"),
DotName.createSimple("com.example.SessionScoped")
));
}Register custom CDI qualifiers for dependency injection disambiguation.
/**
* Register custom qualifier registrars
*/
public class QualifierRegistrarBuildItem extends MultiBuildItem {
public QualifierRegistrarBuildItem(QualifierRegistrar registrar);
public QualifierRegistrar getQualifierRegistrar();
}
/**
* Qualifier registrar interface
*/
public interface QualifierRegistrar {
/**
* Register custom qualifiers
*/
void register(RegistrationContext context);
}Usage Examples:
// Register custom qualifiers
@BuildStep
QualifierRegistrarBuildItem registerCustomQualifiers() {
return new QualifierRegistrarBuildItem(context -> {
context.register(DotName.createSimple("com.example.Database"));
context.register(DotName.createSimple("com.example.Cache"));
});
}Register and manage CDI stereotypes for grouping common annotations.
/**
* Register stereotype registrars
*/
public class StereotypeRegistrarBuildItem extends MultiBuildItem {
public StereotypeRegistrarBuildItem(StereotypeRegistrar registrar);
public StereotypeRegistrar getStereotypeRegistrar();
}
/**
* Stereotype registrar interface
*/
public interface StereotypeRegistrar {
/**
* Register custom stereotypes
*/
void register(RegistrationContext context);
}Support for conditional CDI components based on build-time conditions.
/**
* Build-time condition for conditional CDI components
*/
public class BuildTimeConditionBuildItem extends MultiBuildItem {
public BuildTimeConditionBuildItem(String condition, boolean enabled);
public String getCondition();
public boolean isEnabled();
}Usage Examples:
// Register build-time conditions
@BuildStep
BuildTimeConditionBuildItem databaseCondition(DatabaseConfig config) {
return new BuildTimeConditionBuildItem(
"database.enabled",
config.enabled()
);
}Support for @Resource annotation and custom resource injection patterns.
/**
* Register resource injection annotations
*/
public class ResourceAnnotationBuildItem extends MultiBuildItem {
public ResourceAnnotationBuildItem(DotName annotationName);
public DotName getAnnotationName();
}Support for intercepting static methods at build time.
/**
* Register intercepted static methods
*/
public class InterceptedStaticMethodBuildItem extends MultiBuildItem {
public InterceptedStaticMethodBuildItem(String className, String methodName,
String descriptor, boolean needsCallerInstance);
public String getClassName();
public String getMethodName();
public String getDescriptor();
public boolean needsCallerInstance();
}These advanced features provide the foundation for sophisticated CDI customizations, architectural patterns, and framework integrations in Quarkus applications.
Install with Tessl CLI
npx tessl i tessl/maven-io-quarkus--quarkus-arc-deployment