Build time CDI dependency injection framework for Quarkus applications with conditional bean support and context management
npx @tessl/cli install tessl/maven-io-quarkus--quarkus-arc@3.23.0Quarkus Arc is a build-time CDI (Contexts and Dependency Injection) dependency injection framework that is part of the Quarkus ecosystem. This extension provides compile-time dependency injection capabilities optimized for cloud-native and containerized Java applications. Arc processes CDI annotations at build time rather than runtime, enabling faster startup times and reduced memory footprint typical of traditional CDI implementations.
pom.xml:<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc</artifactId>
<version>3.23.0</version>
</dependency>import io.quarkus.arc.profile.IfBuildProfile;
import io.quarkus.arc.profile.UnlessBuildProfile;
import io.quarkus.arc.properties.IfBuildProperty;
import io.quarkus.arc.properties.UnlessBuildProperty;
import io.quarkus.arc.lookup.LookupIfProperty;
import io.quarkus.arc.lookup.LookupUnlessProperty;
import io.quarkus.arc.log.LoggerName;
import io.quarkus.arc.runtime.BeanContainer;
import io.quarkus.arc.runtime.BeanContainerListener;
import io.quarkus.arc.runtime.BeanInvoker;
import io.quarkus.arc.runtime.BeanLookupSupplier;
import io.quarkus.arc.runtime.InterceptorBindings;For accessing the Arc container at runtime:
import io.quarkus.arc.Arc;
import io.quarkus.arc.ArcContainer;import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.quarkus.arc.profile.IfBuildProfile;
import io.quarkus.arc.log.LoggerName;
import org.jboss.logging.Logger;
// Conditional bean based on build profile
@ApplicationScoped
@IfBuildProfile("dev")
public class DevService {
@Inject
@LoggerName("dev.service")
Logger logger;
public void process() {
logger.info("Processing in development mode");
}
}
// Property-based conditional bean
@ApplicationScoped
@IfBuildProperty(name = "feature.enabled", stringValue = "true")
public class FeatureService {
public void execute() {
// Feature implementation
}
}
// Runtime bean container access
@ApplicationScoped
public class ContainerManager {
public void demonstrateContainerAccess() {
// Access the bean container
BeanContainer container = Arc.container();
DevService service = container.beanInstance(DevService.class);
service.process();
}
}Quarkus Arc is built around several key components:
Control bean activation based on Quarkus build profiles, enabling different implementations for development, testing, and production environments.
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
public @interface IfBuildProfile {
String value() default "";
String[] allOf() default {};
String[] anyOf() default {};
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
public @interface UnlessBuildProfile {
String value() default "";
String[] allOf() default {};
String[] anyOf() default {};
}Enable beans based on build-time configuration properties, allowing feature toggles and environment-specific configurations.
@Repeatable(IfBuildProperty.List.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
public @interface IfBuildProperty {
String name();
String stringValue();
boolean enableIfMissing() default false;
}
@Repeatable(UnlessBuildProperty.List.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
public @interface UnlessBuildProperty {
String name();
String stringValue();
boolean enableIfMissing() default false;
}Control which beans are available for programmatic lookup based on runtime properties, enabling dynamic behavior without bean activation overhead.
@Repeatable(LookupIfProperty.List.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
public @interface LookupIfProperty {
String name();
String stringValue();
boolean lookupIfMissing() default false;
}
@Repeatable(LookupUnlessProperty.List.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE, ElementType.FIELD })
public @interface LookupUnlessProperty {
String name();
String stringValue();
boolean lookupIfMissing() default false;
}CDI-based logger injection with support for custom logger names and automatic bean-specific logger creation.
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
public @interface LoggerName {
String value();
public static final class Literal extends AnnotationLiteral<LoggerName> implements LoggerName {
public Literal(String value);
public String value();
}
}Programmatic access to the CDI bean container for runtime bean resolution, context management, and lifecycle control.
public interface BeanContainer {
<T> T beanInstance(Class<T> beanType, Annotation... beanQualifiers);
<T> Factory<T> beanInstanceFactory(Class<T> type, Annotation... qualifiers);
<T> Factory<T> beanInstanceFactory(Supplier<Factory<T>> fallbackSupplier, Class<T> type, Annotation... qualifiers);
ManagedContext requestContext();
interface Factory<T> {
Instance<T> create();
}
interface Instance<T> extends AutoCloseable {
T get();
default void close();
}
}
public interface BeanContainerListener {
void created(BeanContainer container);
}Utility interfaces for invoking bean methods with automatic context management and lookup operations.
public interface BeanInvoker<T> {
default void invoke(T param) throws Exception;
void invokeBean(T param) throws Exception;
}
public class BeanLookupSupplier implements Supplier<Object> {
public BeanLookupSupplier();
public BeanLookupSupplier(Class<?> type);
public Class<?> getType();
public BeanLookupSupplier setType(Class<?> type);
public Object get();
}Utilities for working with interceptor bindings and context data within interceptor implementations.
public final class InterceptorBindings {
public static Set<Annotation> getInterceptorBindings(InvocationContext invocationContext);
public static Set<AbstractAnnotationLiteral> getInterceptorBindingLiterals(InvocationContext invocationContext);
}