Quarkus - Contexts and Dependency Injection

Quarkus DI solution (also called ArC) is based on the Contexts and Dependency Injection for Java 2.0 specification. However, it is not a full CDI implementation verified by the TCK. Only a subset of the CDI features is implemented - see also the list of supported features and the list of limitations.

If you’re new to CDI then we recommend you to read the Introduction to CDI first.
Most of the existing CDI code should work just fine but there are some small differences which follow from the Quarkus architecture and goals.

1. Bean Discovery

Bean discovery in CDI is a complex process which involves legacy deployment structures and accessibility requirements of the underlying module architecture. However, Quarkus is using a simplified bean discovery. There is only single bean archive with the bean discovery mode annotated and no visibility boundaries.

The bean archive is synthesized from:

  • the application classes,

  • dependencies that contain a beans.xml descriptor (content is ignored),

  • dependencies that contain a Jandex index - META-INF/jandex.idx,

  • dependencies referenced by quarkus.index-dependency in application.properties,

  • and Quarkus integration code.

Bean classes that don’t have a bean defining annotation are not discovered. This behavior is defined by CDI. But producer methods and fields and observer methods are discovered even if the declaring class is not annotated with a bean defining annotation (this behavior is different to what is defined in CDI). In fact, the declaring bean classes are considered annotated with @Dependent.

Quarkus extensions may declare additional discovery rules. For example, @Scheduled business methods are registered even if the declaring class is not annotated with a bean defining annotation.

1.1. How to Generate a Jandex Index

A dependency with a Jandex index is automatically scanned for beans. To generate the index just add the following to your pom.xml:

<build>
  <plugins>
    <plugin>
      <groupId>org.jboss.jandex</groupId>
      <artifactId>jandex-maven-plugin</artifactId>
      <version>1.1.0</version>
      <executions>
        <execution>
          <id>make-index</id>
          <goals>
            <goal>jandex</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

If you are are using gradle, you can apply the following plugin to your build.gradle:

plugins {
    id 'org.kordamp.gradle.jandex' version '0.11.0'
}

If you can’t modify the dependency, you can still index it by adding quarkus.index-dependency entries to your application.properties:

quarkus.index-dependency.<name>.group-id=
quarkus.index-dependency.<name>.artifact-id=
quarkus.index-dependency.<name>.classifier=(this one is optional)

For example, the following entries ensure that the org.acme:acme-api dependency is indexed:

Example application.properties
quarkus.index-dependency.acme.group-id=org.acme (1)
quarkus.index-dependency.acme.artifact-id=acme-api (2)
1 Value is a group id for a dependency identified by name acme.
2 Value is an artifact id for a dependency identified by name acme.

1.2. How To Exclude Types and Dependencies from Discovery

It may happen that some beans from third-party libraries do not work correctly in Quarkus. A typical example is a bean injecting a portable extension. In such case, it’s possible to exclude types and dependencies from the bean discovery. The quarkus.arc.exclude-types property accepts a list of string values that are used to match classes that should be excluded.

Table 1. Value Examples

Value

Description

org.acme.Foo

Match the fully qualified name of the class

org.acme.*

Match classes with package org.acme

org.acme.**

Match classes where the package starts with org.acme

Bar

Match the simple name of the class

Example application.properties
quarkus.arc.exclude-types=org.acme.Foo,org.acme.*,Bar (1)(2)(3)
1 Exclude the type org.acme.Foo.
2 Exclude all types from the org.acme package.
3 Exclude all types whose simple name is Bar

It is also possible to exclude a dependency artifact that would be otherwise scanned for beans. For example, because it contains a beans.xml descriptor.

Example application.properties
quarkus.arc.exclude-dependency.acme.group-id=org.acme (1)
quarkus.arc.exclude-dependency.acme.artifact-id=acme-services (2)
1 Value is a group id for a dependency identified by name acme.
2 Value is an artifact id for a dependency identified by name acme.

2. Native Executables and Private Members

Quarkus is using GraalVM to build a native executable. One of the limitations of GraalVM is the usage of Reflection. Reflective operations are supported but all relevant members must be registered for reflection explicitly. Those registrations result in a bigger native executable.

And if Quarkus DI needs to access a private member it has to use reflection. That’s why Quarkus users are encouraged not to use private members in their beans. This involves injection fields, constructors and initializers, observer methods, producer methods and fields, disposers and interceptor methods.

How to avoid using private members? You can use package-private modifiers:

@ApplicationScoped
public class CounterBean {

    @Inject
    CounterService counterService; (1)

    void onMessage(@Observes Event msg) { (2)
    }
}
1 A package-private injection field.
2 A package-private observer method.

Or constructor injection:

@ApplicationScoped
public class CounterBean {

    private CounterService service;

    CounterBean(CounterService service) { (1)
      this.service = service;
    }
}
1 A package-private constructor injection. @Inject is optional in this particular case.

3. Supported Features

  • Programming model

    • Managed beans implemented by a Java class

      • @PostConstruct and @PreDestroy lifecycle callbacks

    • Producer methods and fields, disposers

    • Qualifiers

    • Alternatives

    • Stereotypes

  • Dependency injection and lookup

    • Field, constructor and initializer/setter injection

    • Type-safe resolution

    • Programmatic lookup via javax.enterprise.inject.Instance

    • Client proxies

    • Injection point metadata

  • Scopes and contexts

    • @Dependent, @ApplicationScoped, @Singleton, @RequestScoped and @SessionScoped

    • Custom scopes and contexts

  • Interceptors

    • Business method interceptors: @AroundInvoke

    • Interceptors for lifecycle event callbacks: @PostConstruct, @PreDestroy, @AroundConstruct

  • Decorators

  • Events and observer methods, including asynchronous events and transactional observer methods

4. Limitations

  • @ConversationScoped is not supported

  • Portable Extensions are not supported

  • BeanManager - only the following methods are implemented: getBeans(), createCreationalContext(), getReference(), getInjectableReference() , resolve(), getContext(), fireEvent(), getEvent() and createInstance()

  • Specialization is not supported

  • beans.xml descriptor content is ignored

  • Passivation and passivating scopes are not supported

  • Interceptor methods on superclasses are not implemented yet

  • @Interceptors is not supported

5. Non-standard Features

5.1. Eager Instantiation of Beans

5.1.1. Lazy By Default

By default, CDI beans are created lazily, when needed. What exactly "needed" means depends on the scope of a bean.

  • A normal scoped bean (@ApplicationScoped, @RequestScoped, etc.) is needed when a method is invoked upon an injected instance (contextual reference per the specification).

    In other words, injecting a normal scoped bean will not suffice because a client proxy is injected instead of a contextual instance of the bean.

  • A bean with a pseudo-scope (@Dependent and @Singleton ) is created when injected.

Lazy Instantiation Example
@Singleton // => pseudo-scope
class AmazingService {
  String ping() {
    return "amazing";
  }
}

@ApplicationScoped // => normal scope
class CoolService {
  String ping() {
    return "cool";
  }
}

@Path("/ping")
public class PingResource {

  @Inject
  AmazingService s1; (1)

  @Inject
  CoolService s2; (2)

  @GET
  public String ping() {
    return s1.ping() + s2.ping(); (3)
  }
}
1 Injection triggers the instantiation of AmazingService.
2 Injection itself does not result in the instantiation of CoolService. A client proxy is injected.
3 The first invocation upon the injected proxy triggers the instantiation of CoolService.

5.1.2. Startup Event

However, if you really need to instantiate a bean eagerly you can:

  • Declare an observer of the StartupEvent - the scope of the bean does not matter in this case:

    @ApplicationScoped
    class CoolService {
      void startup(@Observes StartupEvent event) { (1)
      }
    }
    1 A CoolService is created during startup to service the observer method invocation.
  • Use the bean in an observer of the StartupEvent - normal scoped beans must be used as described in Lazy By Default:

    @Dependent
    class MyBeanStarter {
    
      void startup(@Observes StartupEvent event, AmazingService amazing, CoolService cool) { (1)
        cool.toString(); (2)
      }
    }
    1 The AmazingService is created during injection.
    2 The CoolService is a normal scoped bean so we have to invoke a method upon the injected proxy to force the instantiation.
  • Annotate the bean with @io.quarkus.runtime.Startup as described in Startup annotation:

    @Startup (1)
    @ApplicationScoped
    public class EagerAppBean {
    
       private final String name;
    
       EagerAppBean(NameGenerator generator) { (2)
         this.name = generator.createName();
       }
    }
    1. For each bean annotated with @Startup a synthetic observer of StartupEvent is generated. The default priority is used.

    2. The bean constructor is called when the application starts and the resulting contextual instance is stored in the application context.

Quarkus users are encouraged to always prefer the @Observes StartupEvent to @Initialized(ApplicationScoped.class) as explained in the Application Initialization and Termination guide.

5.2. Request Context Lifecycle

The request context is also active:

  • during notification of a synchronous observer method.

The request context is destroyed:

  • after the observer notification completes for an event, if it was not already active when the notification started.

An event with qualifier @Initialized(RequestScoped.class) is fired when the request context is initialized for an observer notification. Moreover, the events with qualifiers @BeforeDestroyed(RequestScoped.class) and @Destroyed(RequestScoped.class) are fired when the request context is destroyed.

5.3. Qualified Injected Fields

In CDI, if you declare a field injection point you need to use @Inject and optionally a set of qualifiers.

  @Inject
  @ConfigProperty(name = "cool")
  String coolProperty;

In Quarkus, you can skip the @Inject annotation completely if the injected field declares at least one qualifier.

  @ConfigProperty(name = "cool")
  String coolProperty;
With the notable exception of one special case discussed below, @Inject is still required for constructor and method injection.

5.4. Simplified Constructor Injection

In CDI, a normal scoped bean must always declare a no-args constructor (this constructor is normally generated by the compiler unless you declare any other constructor). However, this requirement complicates constructor injection - you need to provide a dummy no-args constructor to make things work in CDI.

@ApplicationScoped
public class MyCoolService {

  private SimpleProcessor processor;

  MyCoolService() { // dummy constructor needed
  }

  @Inject // constructor injection
  MyCoolService(SimpleProcessor processor) {
    this.processor = processor;
  }
}

There is no need to declare dummy constructors for normal scoped bean in Quarkus - they are generated automatically. Also if there’s only one constructor there is no need for @Inject.

@ApplicationScoped
public class MyCoolService {

  private SimpleProcessor processor;

  MyCoolService(SimpleProcessor processor) {
    this.processor = processor;
  }
}
We don’t generate a no-args constructor automatically if a bean class extends a class that does not declare a no-args constructor.

5.5. Removing Unused Beans

The container attempts to remove all unused beans during build by default. This optimization can be disabled by setting quarkus.arc.remove-unused-beans to none or false.

An unused bean:

  • is not a built-in bean or an interceptor,

  • is not eligible for injection to any injection point,

  • is not excluded by any extension,

  • does not have a name,

  • does not declare an observer,

  • does not declare any producer which is eligible for injection to any injection point,

  • is not directly eligible for injection into any javax.enterprise.inject.Instance or javax.inject.Provider injection point

This optimization applies to all forms of bean declarations: bean class, producer method, producer field.

Users can instruct the container to not remove any of their specific beans (even if they satisfy all the rules specified above) by annotating them with io.quarkus.arc.Unremovable. This annotation can be placed on the types, producer methods, and producer fields.

Since this is not always possible, there is an option to achieve the same via application.properties. The quarkus.arc.unremovable-types property accepts a list of string values that are used to match beans based on their name or package.

Table 2. Value Examples

Value

Description

org.acme.Foo

Match the fully qualified name of the bean class

org.acme.*

Match beans where the package of the bean class is org.acme

org.acme.**

Match beans where the package of the bean class starts with org.acme

Bar

Match the simple name of the bean class

Example application.properties
quarkus.arc.unremovable-types=org.acme.Foo,org.acme.*,Bar

Furthermore, extensions can eliminate possible false positives by producing UnremovableBeanBuildItem.

Finally, Quarkus provides a middle ground for the bean removal optimization where application beans are never removed whether or not they are unused, while the optimization proceeds normally for non application classes. To use this mode, set quarkus.arc.remove-unused-beans to fwk or framework.

When using the dev mode (running ./mvnw clean compile quarkus:dev), you can see more information about which beans are being removed by enabling additional logging via the following line in your application.properties.

quarkus.log.category."io.quarkus.arc.processor".level=DEBUG

5.6. Default Beans

Quarkus adds a capability that CDI currently does not support which is to conditionally declare a bean if no other bean with equal types and qualifiers was declared by any available means (bean class, producer, synthetic bean, …​) This is done using the @io.quarkus.arc.DefaultBean annotation and is best explained with an example.

Say there is a Quarkus extension that among other things declares a few CDI beans like the following code does:

@Dependent
public class TracerConfiguration {

    @Produces
    public Tracer tracer(Reporter reporter, Configuration configuration) {
        return new Tracer(reporter, configuration);
    }

    @Produces
    @DefaultBean
    public Configuration configuration() {
        // create a Configuration
    }

    @Produces
    @DefaultBean
    public Reporter reporter(){
        // create a Reporter
    }
}

The idea is that the extension auto-configures things for the user, eliminating a lot of boilerplate - we can just @Inject a Tracer wherever it is needed. Now imagine that in our application we would like to utilize the configured Tracer, but we need to customize it a little, for example by providing a custom Reporter. The only thing that would be needed in our application would be something like the following:

@Dependent
public class CustomTracerConfiguration {

    @Produces
    public Reporter reporter(){
        // create a custom Reporter
    }
}

@DefaultBean allows extensions (or any other code for that matter) to provide defaults while backing off if beans of that type are supplied in any way Quarkus supports.

5.7. Enabling Beans for Quarkus Build Profile

Quarkus adds a capability that CDI currently does not support which is to conditionally enable a bean when a Quarkus build time profile is enabled, via the @io.quarkus.arc.profile.IfBuildProfile and @io.quarkus.arc.profile.UnlessBuildProfile annotations. When used in conjunction with @io.quarkus.arc.DefaultBean, these annotations allow for the creation of different bean configurations for different build profiles.

Imagine for instance that an application contains a bean named Tracer, which needs to be do nothing when in tests or dev-mode, but works in its normal capacity for the production artifact. An elegant way to create such beans is the following:

@Dependent
public class TracerConfiguration {

    @Produces
    @IfBuildProfile("prod")
    public Tracer realTracer(Reporter reporter, Configuration configuration) {
        return new RealTracer(reporter, configuration);
    }

    @Produces
    @DefaultBean
    public Tracer noopTracer() {
        return new NoopTracer();
    }
}

If instead, it is required that the Tracer bean also works in dev-mode and only default to doing nothing for tests, then @UnlessBuildProfile would be ideal. The code would look like:

@Dependent
public class TracerConfiguration {

    @Produces
    @UnlessBuildProfile("test") // this will be enabled for both prod and dev build time profiles
    public Tracer realTracer(Reporter reporter, Configuration configuration) {
        return new RealTracer(reporter, configuration);
    }

    @Produces
    @DefaultBean
    public Tracer noopTracer() {
        return new NoopTracer();
    }
}
The runtime profile has absolutely no effect on the bean resolution using @IfBuildProfile and @UnlessBuildProfile.

5.8. Enabling Beans for Quarkus Build Properties

Quarkus adds a capability that CDI currently does not support which is to conditionally enable a bean when a Quarkus build time property has a specific value, via the @io.quarkus.arc.properties.IfBuildProperty and @io.quarkus.arc.properties.UnlessBuildProperty annotation. When used in conjunction with @io.quarkus.arc.DefaultBean, this annotation allow for the creation of different bean configurations for different build properties.

The scenario we mentioned above with Tracer could also be implemented in the following way:

@Dependent
public class TracerConfiguration {

    @Produces
    @IfBuildProperty(name = "some.tracer.enabled", stringValue = "true")
    public Tracer realTracer(Reporter reporter, Configuration configuration) {
        return new RealTracer(reporter, configuration);
    }

    @Produces
    @DefaultBean
    public Tracer noopTracer() {
        return new NoopTracer();
    }
}

If instead, it is required that the RealTracer bean is only used if the some.tracer.enabled property is not false, then @UnlessBuildProperty would be ideal. The code would look like:

@Dependent
public class TracerConfiguration {

    @Produces
    @UnlessBuildProperty(name = "some.tracer.enabled", stringValue = "false")
    public Tracer realTracer(Reporter reporter, Configuration configuration) {
        return new RealTracer(reporter, configuration);
    }

    @Produces
    @DefaultBean
    public Tracer noopTracer() {
        return new NoopTracer();
    }
}
Properties set at runtime have absolutely no effect on the bean resolution using @IfBuildProperty.

5.9. Declaring Selected Alternatives

In CDI, an alternative bean may be selected either globally for an application by means of @Priority, or for a bean archive using a beans.xml descriptor. Quarkus has a simplified bean discovery and the content of beans.xml is ignored.

The disadvantage of @Priority is that it has @Target({ TYPE, PARAMETER }) and so it cannot be used for producer methods and fields. To address this problem and to simplify the code Quarkus provides the io.quarkus.arc.AlternativePriority annotation. It’s basically a shortcut for @Alternative plus @Priority. Additionally, it can be used for producers.

However, it is also possible to select alternatives for an application using the unified configuration. The quarkus.arc.selected-alternatives property accepts a list of string values that are used to match alternative beans. If any value matches then the priority of Integer#MAX_VALUE is used for the relevant bean. The priority declared via @Priority or @AlternativePriority is overridden.

Table 3. Value Examples

Value

Description

org.acme.Foo

Match the fully qualified name of the bean class or the bean class of the bean that declares the producer

org.acme.*

Match beans where the package of the bean class is org.acme

org.acme.**

Match beans where the package of the bean class starts with org.acme

Bar

Match the simple name of the bean class or the bean class of the bean that declares the producer

Example application.properties
quarkus.arc.selected-alternatives=org.acme.Foo,org.acme.*,Bar

5.10. Simplified Producer Method Declaration

In CDI, a producer method must be always annotated with @Produces.

class Producers {

  @Inject
  @ConfigProperty(name = "cool")
  String coolProperty;

  @Produces
  @ApplicationScoped
  MyService produceService() {
    return new MyService(coolProperty);
  }
}

In Quarkus, you can skip the @Produces annotation completely if the producer method is annotated with a scope annotation, a stereotype or a qualifier.

class Producers {

  @ConfigProperty(name = "cool")
  String coolProperty;

  @ApplicationScoped
  MyService produceService() {
    return new MyService(coolProperty);
  }
}

5.11. Interception of Static Methods

The Interceptors specification is clear that around-invoke methods must not be declared static. However, this restriction was driven mostly by technical limitations. And since Quarkus is a build-time oriented stack that allows for additional class transformations, those limitations don’t apply anymore. It’s possible to annotate a non-private static method with an interceptor binding:

class Services {

  @Logged (1)
  static BigDecimal computePrice(long amount) { (2)
    BigDecimal price;
    // Perform computations...
    return price;
  }
}
1 Logged is an interceptor binding.
2 Each method invocation is intercepted if there is an interceptor associated with Logged.

5.11.1. Limitations

  • Only method-level bindings are considered for backward compatibility reasons (otherwise static methods of bean classes that declare class-level bindings would be suddenly intercepted)

  • Private static methods are never intercepted

  • InvocationContext#getTarget() returns null for obvious reasons; therefore not all existing interceptors may behave correctly when intercepting static methods

    Interceptors can use InvocationContext.getMethod() to detect static methods and adjust the behavior accordingly.

5.12. Ability to handle 'final' classes and methods

In normal CDI, classes that are marked as final and / or have final methods are not eligible for proxy creation, which in turn means that interceptors and normal scoped beans don’t work properly. This situation is very common when trying to use CDI with alternative JVM languages like Kotlin where classes and methods are final by default.

Quarkus however, can overcome these limitations when quarkus.arc.transform-unproxyable-classes is set to true (which is the default value).

5.13. Container-managed Concurrency

There is no standard concurrency control mechanism for CDI beans. Nevertheless, a bean instance can be shared and accessed concurrently from multiple threads. In that case it should be thread-safe. You can use standard Java constructs (volatile, synchronized, ReadWriteLock, etc.) or let the container control the concurrent access. Quarkus provides @io.quarkus.arc.Lock and a built-in interceptor for this interceptor binding. Each interceptor instance associated with a contextual instance of an intercepted bean holds a separate ReadWriteLock with non-fair ordering policy.

io.quarkus.arc.Lock is a regular interceptor binding and as such can be used for any bean with any scope. However, it is especially useful for "shared" scopes, e.g. @Singleton and @ApplicationScoped.
Container-managed Concurrency Example
import io.quarkus.arc.Lock;

@Lock (1)
@ApplicationScoped
class SharedService {

  void addAmount(BigDecimal amount) {
    // ...changes some internal state of the bean
  }

  @Lock(value = Lock.Type.READ, time = 1, unit = TimeUnit.SECONDS) (2) (3)
  BigDecimal getAmount() {
    // ...it is safe to read the value concurrently
  }
}
1 @Lock (which maps to @Lock(Lock.Type.WRITE)) declared on the class instructs the container to lock the bean instance for any invocation of any business method, i.e. the client has "exclusive access" and no concurrent invocations will be allowed.
2 @Lock(Lock.Type.READ) overrides the value specified at class level. It means that any number of clients can invoke the method concurrently, unless the bean instance is locked by @Lock(Lock.Type.WRITE).
3 You can also specify the "wait time". If it’s not possible to acquire the lock in the given time a LockException is thrown.

5.14. Repeatable interceptor bindings

Quarkus has limited support for @Repeatable interceptor binding annotations.

When binding an interceptor to a component, you can declare multiple @Repeatable annotations on methods. Repeatable interceptor bindings declared on classes and stereotypes are not supported, because there are some open questions around interactions with the Interceptors specification. This might be added in the future.

As an example, suppose we have an interceptor that clears a cache. The corresponding interceptor binding would be called @CacheInvalidateAll and would be declared as @Repeatable. If we wanted to clear two caches at the same time, we would add @CacheInvalidateAll twice:

@ApplicationScoped
class CachingService {
  @CacheInvalidateAll(cacheName = "foo")
  @CacheInvalidateAll(cacheName = "bar")
  void heavyComputation() {
    // ...
    // some computation that updates a lot of data
    // and requires 2 caches to be invalidated
    // ...
  }
}

This is how interceptors are used. What about creating an interceptor?

When declaring interceptor bindings of an interceptor, you can add multiple @Repeatable annotations to the interceptor class as usual. This is useless when the annotation members are @Nonbinding, as would be the case for the @Cached annotation, but is important otherwise.

For example, suppose we have an interceptor that can automatically log method invocations to certain targets. The interceptor binding annotation @Logged would have a member called target, which specifies where to store the log. Our implementation could be restricted to console logging and file logging:

@Interceptor
@Logged(target = "console")
@Logged(target = "file")
class NaiveLoggingInterceptor {
  // ...
}

Other interceptors could be provided to log method invocations to different targets.

5.15. Caching the Result of Programmatic Lookup

In certain situations, it is practical to obtain a bean instance programmatically via an injected javax.enterprise.inject.Instance and Instance.get(). However, according to the specification the get() method must identify the matching bean and obtain a contextual reference. As a consequence, a new instance of a @Dependent bean is returned from each invocation of get(). Moreover, this instance is a dependent object of the injected Instance. This behavior is well-defined but it may lead to unexpected errors and memory leaks. Therefore, Quarkus comes with the io.quarkus.arc.WithCaching annotation. An injected Instance annotated with this annotation will cache the result of the Instance#get() operation. The result is computed on the first call and the same value is returned for all subsequent calls, even for @Dependent beans.

class Producer {

  AtomicLong nextLong = new AtomicLong();
  AtomicInteger nextInt = new AtomicInteger();

   @Dependent
   @Produces
   Integer produceInt() {
     return nextInt.incrementAndGet();
   }

   @Dependent
   @Produces
   Long produceLong() {
     return nextLong.incrementAndGet();
   }
}

class Consumer {

  @Inject
  Instance<Long> longInstance;

  @Inject
  @WithCaching
  Instance<Integer> intInstance;

  // this method should always return true
  // Producer#produceInt() is only called once
  boolean pingInt() {
    return intInstance.get().equals(intInstance.get());
  }

  // this method should always return false
  // Producer#produceLong() is called twice per each pingLong() invocation
  boolean pingLong() {
    return longInstance.get().equals(longInstance.get());
  }
}
It is also possible to clear the cached value via io.quarkus.arc.InjectableInstance.clearCache(). In this case, you’ll need to inject the Quarkus-specific io.quarkus.arc.InjectableInstance instead of javax.enterprise.inject.Instance.

6. Build Time Extensions

Quarkus incorporates build-time optimizations in order to provide instant startup and low memory footprint. The downside of this approach is that CDI Portable Extensions cannot be supported. Nevertheless, most of the functionality can be achieved using Quarkus extensions. See the integration guide for more information.

7. Development Mode

In the development mode, two special endpoints are registered automatically to provide some basic debug info in the JSON format:

These endpoints are only available in the development mode, i.e. when you run your application via mvn quarkus:dev (or ./gradlew quarkusDev).

8. ArC Configuration Reference

Configuration property fixed at build time - All other configuration properties are overridable at runtime

Configuration property

Type

Default

  • If set to all (or true) the container will attempt to remove all unused beans.

  • If set to none (or false) no beans will ever be removed even if they are unused (according to the criteria set out below)

  • If set to fwk, then all unused beans will be removed, except the unused beans whose classes are declared in the application code An unused bean:

  • is not a built-in bean or interceptor,

  • is not eligible for injection to any injection point,

  • is not excluded by any extension,

  • does not have a name,

  • does not declare an observer,

  • does not declare any producer which is eligible for injection to any injection point,

  • is not directly eligible for injection into any javax.enterprise.inject.Instance injection point

string

all

If set to true @Inject is automatically added to all non-static fields that are annotated with one of the annotations defined by AutoInjectAnnotationBuildItem.

boolean

true

If set to true, the bytecode of unproxyable beans will be transformed. This ensures that a proxy/subclass can be created properly. If the value is set to false, then an exception is thrown at build time indicating that a subclass/proxy could not be created. Quarkus performs the following transformations when this setting is enabled: - Remove 'final' modifier from classes and methods when a proxy is required. - Create a no-args constructor if needed. - Makes private no-args constructors package-private if necessary.

boolean

true

The default naming strategy for ConfigProperties.NamingStrategy. The allowed values are determined by that enum

from-config, verbatim, kebab-case

kebab-case

The list of selected alternatives for an application. An element value can be: - a fully qualified class name, i.e. org.acme.Foo - a simple class name as defined by Class#getSimpleName(), i.e. Foo - a package name with suffix .*, i.e. org.acme.*, matches a package - a package name with suffix .**, i.e. org.acme.**, matches a package that starts with the value Each element value is used to match an alternative bean class, an alternative stereotype annotation type or a bean class that declares an alternative producer. If any value matches then the priority of Integer#MAX_VALUE is used for the relevant bean. The priority declared via javax.annotation.Priority or io.quarkus.arc.AlternativePriority is overriden.

list of string

If set to true then javax.enterprise.inject.Produces is automatically added to all non-void methods that are annotated with a scope annotation, a stereotype or a qualifier, and are not annotated with Inject or Produces, and no parameter is annotated with Disposes, Observes or ObservesAsync.

boolean

true

The list of types that should be excluded from discovery. An element value can be: - a fully qualified class name, i.e. org.acme.Foo - a simple class name as defined by Class#getSimpleName(), i.e. Foo - a package name with suffix .*, i.e. org.acme.*, matches a package - a package name with suffix .**, i.e. org.acme.**, matches a package that starts with the value If any element value matches a discovered type then the type is excluded from discovery, i.e. no beans and observer methods are created from this type.

list of string

List of types that should be considered unremovable regardless of whether they are directly used or not. This is a configuration option equivalent to using io.quarkus.arc.Unremovable annotation. An element value can be: - a fully qualified class name, i.e. org.acme.Foo - a simple class name as defined by Class#getSimpleName(), i.e. Foo - a package name with suffix .*, i.e. org.acme.*, matches a package - a package name with suffix .**, i.e. org.acme.**, matches a package that starts with the value If any element value matches a discovered bean, then such a bean is considered unremovable.

list of string

If set to true then the container attempts to detect "unused removed beans" false positives during programmatic lookup at runtime. You can disable this feature to conserve some memory when running your application in production.

boolean

true

If set to true then the container attempts to detect wrong usages of annotations and eventually fails the build to prevent unexpected behavior of a Quarkus application. A typical example is @javax.ejb.Singleton which is often confused with @javax.inject.Singleton. As a result a component annotated with @javax.ejb.Singleton would be completely ignored. Another example is an inner class annotated with a scope annotation - this component would be again completely ignored.

boolean

true

If set to true then the container monitors business method invocations and fired events during the development mode.

boolean

true

If set to true then disable StartupEvent and ShutdownEvent observers declared on application bean classes during the tests.

boolean

false

The list of packages that will not be checked for split package issues. A package string representation can be: - a full name of the package, i.e. org.acme.foo - a package name with suffix .*, i.e. org.acme.*, which matches a package that starts with provided value

list of string

Artifacts that should be excluded from discovery

Type

Default

string

required

The maven artifactId of the artifact.

string

required

The maven classifier of the artifact.

string