# Introduction to Contexts and Dependency Injection (CDI)

In this guide we’re going to describe the basic principles of the Quarkus programming model that is based on the Jakarta Contexts and Dependency Injection 4.1 specification. The CDI reference guide describes the bean discovery, non-standard features and configuration properties. The CDI integration guide has more detail on common CDI-related integration use cases, and example code for solutions.

## 1. OK. Let’s start simple. What is a bean?

Well, a bean is a container-managed object that supports a set of basic services, such as injection of dependencies, lifecycle callbacks and interceptors.

## 2. Wait a minute. What does "container-managed" mean?

Simply put, you don’t control the lifecycle of the object instance directly. Instead, you can affect the lifecycle through declarative means, such as annotations, configuration, etc. The container is the environment where your application runs. It creates and destroys the instances of beans, associates the instances with a designated context, and injects them into other beans.

## 3. What is it good for?

An application developer can focus on the business logic rather than finding out "where and how" to obtain a fully initialized component with all of its dependencies.

| You’ve probably heard of the inversion of control (IoC) programming principle. Dependency injection is one of the implementation techniques of IoC.

## 4. What does a bean look like?

There are several kinds of beans. The most common ones are class-based beans:

Simple Bean Example

    import jakarta.inject.Inject;
    import jakarta.enterprise.context.ApplicationScoped;
    import org.eclipse.microprofile.metrics.annotation.Counted;

    @ApplicationScoped (1)
    public class Translator {

        @Inject
        Dictionary dictionary; (2)

        @Counted  (3)
        String translate(String sentence) {
          // ...
        }
    }

1 | This is a scope annotation. It tells the container which context to associate the bean instance with. In this particular case, a single bean instance is created for the application and used by all other beans that inject `Translator`.
2 | This is a field injection point. It tells the container that `Translator` depends on the `Dictionary` bean. If there is no matching bean the build fails.
3 | This is an interceptor binding annotation. In this case, the annotation comes from the MicroProfile Metrics. The relevant interceptor intercepts the invocation and updates the relevant metrics. We will talk about interceptors later.

## 5. Nice. How does the dependency resolution work? I see no names or identifiers.

That’s a good question. In CDI the process of matching a bean to an injection point is type-safe. Each bean declares a set of bean types. In our example above, the `Translator` bean has two bean types: `Translator` and `java.lang.Object`. Subsequently, a bean is assignable to an injection point if the bean has a bean type that matches the required type and has all the required qualifiers. We’ll talk about qualifiers later. For now, it’s enough to know that the bean above is assignable to an injection point of type `Translator` and `java.lang.Object`.

## 6. Hm, wait a minute. What happens if multiple beans declare the same type?

There is a simple rule: exactly one bean must be assignable to an injection point, otherwise the build fails. If none is assignable the build fails with `UnsatisfiedResolutionException`. If multiple are assignable the build fails with `AmbiguousResolutionException`. This is very useful because your application fails fast whenever the container is not able to find an unambiguous dependency for any injection point.

| You can use programmatic lookup via `jakarta.enterprise.inject.Instance` to resolve ambiguities at runtime and even iterate over all beans implementing a given type:
    public class Translator {

        @Inject
        Instance<Dictionary> dictionaries; (1)

        String translate(String sentence) {
          for (Dictionary dict : dictionaries) { (2)
             // ...
          }
        }
    }
1 | This injection point will not result in an ambiguous dependency even if there are multiple beans that implement the `Dictionary` type.
2 | `jakarta.enterprise.inject.Instance` extends `Iterable`.

## 7. Can I use setter and constructor injection?

Yes, you can. In fact, in CDI the "setter injection" is superseded by more powerful initializer methods. Initializers may accept multiple parameters and don’t have to follow the JavaBean naming conventions.

Initialized and Constructor Injection Example

    @ApplicationScoped
    public class Translator {

        private final TranslatorHelper helper;

        Translator(TranslatorHelper helper) { (1)
           this.helper = helper;
        }

        @Inject (2)
        void setDeps(Dictionary dic, LocalizationService locService) { (3)
          / ...
        }
    }

1 | This is a constructor injection. In fact, this code would not work in regular CDI implementations where a bean with a normal scope must always declare a no-args constructor and the bean constructor must be annotated with `@Inject`. However, in Quarkus we detect the absence of no-args constructor and "add" it directly in the bytecode. It’s also not necessary to add `@Inject` if there is only one constructor present.
2 | An initializer method must be annotated with `@Inject`.
3 | An initializer may accept multiple parameters - each one is an injection point.

## 8. You talked about some qualifiers?

Qualifiers are annotations that help the container to distinguish beans that implement the same type. As we already said a bean is assignable to an injection point if it has all the required qualifiers. If you declare no qualifier at an injection point the `@Default` qualifier is assumed.

A qualifier type is a Java annotation defined as `@Retention(RUNTIME)` and annotated with the `@jakarta.inject.Qualifier` meta-annotation:

Qualifier Example

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

The qualifiers of a bean are declared by annotating the bean class or producer method or field with the qualifier types:

Bean With Custom Qualifier Example

    @Superior (1)
    @ApplicationScoped
    public class SuperiorTranslator extends Translator {

        String translate(String sentence) {
          // ...
        }
    }

1 | `@Superior` is a qualifier annotation.

This bean would be assignable to `@Inject @Superior Translator` and `@Inject @Superior SuperiorTranslator` but not to `@Inject Translator`. The reason is that `@Inject Translator` is automatically transformed to `@Inject @Default Translator` during typesafe resolution. And since our `SuperiorTranslator` does not declare `@Default` only the original `Translator` bean is assignable.

| The `@Named` qualifier, which you might be familiar with, is somewhat different in CDI to all other qualifiers. See the corresponding section in CDI Reference Guide for why you typically shouldn’t use it.

## 9. Looks good. What is the bean scope?

The scope of a bean determines the lifecycle of its instances, i.e. when and where an instance should be created and destroyed.

| Every bean has exactly one scope.

## 10. What scopes can I actually use in my Quarkus application?

You can use all the built-in scopes mentioned by the specification except for `jakarta.enterprise.context.ConversationScoped`.

Annotation | Description
--- | ---
`@jakarta.enterprise.context.ApplicationScoped` | A single bean instance is used for the application and shared among all injection points. The instance is created lazily, i.e. once a method is invoked upon the client proxy.
`@jakarta.inject.Singleton` | Just like `@ApplicationScoped` except that no client proxy is used. The instance is created when an injection point that resolves to a @Singleton bean is being injected.
`@jakarta.enterprise.context.RequestScoped` | The bean instance is associated with the current request (usually an HTTP request).
`@jakarta.enterprise.context.Dependent` | This is a pseudo-scope. The instances are not shared and every injection point spawns a new instance of the dependent bean. The lifecycle of dependent bean is bound to the bean injecting it - it will be created and destroyed along with the bean injecting it.
`@jakarta.enterprise.context.SessionScoped` | This scope is backed by a `jakarta.servlet.http.HttpSession` object. It’s only available if the `quarkus-undertow` extension is used.

| There can be other custom scopes provided by Quarkus extensions. For example, `quarkus-narayana-jta` provides `jakarta.transaction.TransactionScoped`.

## 11. `@ApplicationScoped` and `@Singleton` look very similar. Which one should I choose for my Quarkus application?

It depends ;-).

A `@Singleton` bean has no client proxy and hence an instance is created eagerly when the bean is injected. By contrast, an instance of an `@ApplicationScoped` bean is created lazily, i.e. when a method is invoked upon an injected instance for the first time.

Furthermore, client proxies only delegate method invocations and thus you should never read/write fields of an injected `@ApplicationScoped` bean directly. You can read/write fields of an injected `@Singleton` safely.

`@Singleton` should have a slightly better performance because there is no indirection (no proxy that delegates to the current instance from the context).

On the other hand, you cannot mock `@Singleton` beans using QuarkusMock.

`@ApplicationScoped` beans can be also destroyed and recreated at runtime. Existing injection points just work because the injected proxy delegates to the current instance.

Therefore, we recommend to stick with `@ApplicationScoped` by default unless there’s a good reason to use `@Singleton`.

## 12. I don’t understand the concept of client proxies.

Indeed, the client proxies could be hard to grasp, but they provide some useful functionality. A client proxy is basically an object that delegates all method invocations to a target bean instance. It’s a container construct that implements `io.quarkus.arc.ClientProxy` and extends the bean class.

| Client proxies only delegate method invocations. So never read or write a field of a normal scoped bean, otherwise you will work with non-contextual or stale data.

Generated Client Proxy Example

    @ApplicationScoped
    class Translator {

        String translate(String sentence) {
          // ...
        }
    }

    // The client proxy class is generated and looks like...
    class Translator_ClientProxy extends Translator { (1)

        String translate(String sentence) {
          // Find the correct translator instance...
          Translator translator = getTranslatorInstanceFromTheApplicationContext();
          // And delegate the method invocation...
          return translator.translate(sentence);
        }
    }

1 | The `Translator_ClientProxy` instance is always injected instead of a direct reference to a contextual instance of the `Translator` bean.

Client proxies allow for:

- Lazy instantiation - the instance is created once a method is invoked upon the proxy.

- Ability to inject a bean with "narrower" scope to a bean with "wider" scope; i.e. you can inject a `@RequestScoped` bean into an `@ApplicationScoped` bean.

- Circular dependencies in the dependency graph. Having circular dependencies is often an indication that a redesign should be considered, but sometimes it’s inevitable.

- In rare cases it’s practical to destroy the beans manually. A direct injected reference would lead to a stale bean instance.

## 13. OK. You said that there are several kinds of beans?

Yes. In general, we distinguish:

1. Class beans

2. Producer methods

3. Producer fields

4. Synthetic beans

| Synthetic beans are usually provided by extensions. Therefore, we are not going to cover them in this guide.

Producer methods and fields are useful if you need additional control over instantiation of a bean. They are also useful when integrating third-party libraries where you don’t control the class source and may not add additional annotations etc.

Producers Example

    @ApplicationScoped
    public class Producers {

        @Produces (1)
        double pi = Math.PI; (2)

        @Produces (3)
        List<String> names() {
           List<String> names = new ArrayList<>();
           names.add("Andy");
           names.add("Adalbert");
           names.add("Joachim");
           return names; (4)
        }
    }

    @ApplicationScoped
    public class Consumer {

       @Inject
       double pi;

       @Inject
       List<String> names;

       // ...
    }

1 | The container analyses the field annotations to build a bean metadata. The type is used to build the set of bean types. In this case, it will be `double` and `java.lang.Object`. No scope annotation is declared and so it’s defaulted to `@Dependent`.
2 | The container will read this field when creating the bean instance.
3 | The container analyses the method annotations to build a bean metadata. The return type is used to build the set of bean types. In this case, it will be `List<String>`, `Collection<String>`, `Iterable<String>` and `java.lang.Object`. No scope annotation is declared and so it’s defaulted to `@Dependent`.
4 | The container will call this method when creating the bean instance.

There’s more about producers. You can declare qualifiers, inject dependencies into the producer methods parameters, etc. You can read more about producers for example in the Weld docs.

## 14. OK, injection looks cool. What other services are provided?

### 14.1. Lifecycle Callbacks

A bean class may declare lifecycle `@PostConstruct` and `@PreDestroy` callbacks:

Lifecycle Callbacks Example

    import jakarta.annotation.PostConstruct;
    import jakarta.annotation.PreDestroy;

    @ApplicationScoped
    public class Translator {

        @PostConstruct (1)
        void init() {
           // ...
        }

        @PreDestroy (2)
        void destroy() {
          // ...
        }
    }

1 | This callback is invoked before the bean instance is put into service. It is safe to perform some initialization here.
2 | This callback is invoked before the bean instance is destroyed. It is safe to perform some cleanup tasks here.

| It’s a good practice to keep the logic in the callbacks "without side effects", i.e. you should avoid calling other beans inside the callbacks.

### 14.2. Interceptors

Interceptors are used to separate cross-cutting concerns from business logic. There is a separate specification - Java Interceptors - that defines the basic programming model and semantics.

Simple Interceptor Binding Example

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Inherited;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import jakarta.interceptor.InterceptorBinding;

    @InterceptorBinding (1)
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR}) (2)
    @Inherited (3)
    public @interface Logged {
    }

1 | This is an interceptor binding annotation. See the following examples for how it’s used.
2 | An interceptor binding annotation is always put on the interceptor type, and may be put on target types or methods.
3 | Interceptor bindings are often `@Inherited`, but don’t have to be.

Simple Interceptor Example

    import jakarta.annotation.Priority;
    import jakarta.interceptor.AroundInvoke;
    import jakarta.interceptor.Interceptor;
    import jakarta.interceptor.InvocationContext;

    @Logged (1)
    @Priority(2020) (2)
    @Interceptor (3)
    public class LoggingInterceptor {

       @Inject (4)
       Logger logger;

       @AroundInvoke (5)
       Object logInvocation(InvocationContext context) {
          // ...log before
          Object ret = context.proceed(); (6)
          // ...log after
          return ret;
       }

    }

1 | The interceptor binding annotation is used to bind our interceptor to a bean. Simply annotate a bean class with `@Logged`, as in the following example.
2 | `Priority` enables the interceptor and affects the interceptor ordering. Interceptors with smaller priority values are called first.
3 | Marks an interceptor component.
4 | An interceptor may inject dependencies.
5 | `AroundInvoke` denotes a method that interposes on business methods.
6 | Proceed to the next interceptor in the interceptor chain or invoke the intercepted business method.

| Instances of interceptors are dependent objects of the bean instance they intercept, i.e. a new interceptor instance is created for each intercepted bean.

Simple Example of Interceptor Usage

    import jakarta.enterprise.context.ApplicationScoped;

    @Logged  (1) (2)
    @ApplicationScoped
    public class MyService {
       void doSomething() {
           ...
       }
    }

1 | The interceptor binding annotation is put on a bean class so that all business methods are intercepted. The annotation can also be put on individual methods, in which case, only the annotated methods are intercepted.
2 | Remember that the `@Logged` annotation is `@Inherited`. If there’s a bean class that inherits from `MyService`, the `LoggingInterceptor` will also apply to it.

### 14.3. Decorators

Decorators are similar to interceptors, but because they implement interfaces with business semantics, they are able to implement business logic.

Simple Decorator Example

    import jakarta.decorator.Decorator;
    import jakarta.decorator.Delegate;
    import jakarta.annotation.Priority;
    import jakarta.inject.Inject;
    import jakarta.enterprise.inject.Any;

    public interface Account {
       void withdraw(BigDecimal amount);
    }

    @Priority(10) (1)
    @Decorator (2)
    public class LargeTxAccount implements Account { (3)

       @Inject
       @Any
       @Delegate
       Account delegate; (4)

       @Inject
       @Decorated
       Bean<Account> delegateInfo; (5)

       @Inject
       LogService logService; (6)

       void withdraw(BigDecimal amount) {
          delegate.withdraw(amount); (7)
          if (amount.compareTo(1000) > 0) {
             logService.logWithdrawal(delegate, amount);
          }
       }

    }

1 | `@Priority` enables the decorator. Decorators with smaller priority values are called first.
2 | `@Decorator` marks a decorator component.
3 | The set of decorated types includes all bean types which are Java interfaces, except for `java.io.Serializable`.
4 | Each decorator must declare exactly one delegate injection point. The decorator applies to beans that are assignable to this delegate injection point.
5 | It is possible to obtain information about the decorated bean by using the `@Decorated` qualifier.
6 | Decorators can inject other beans.
7 | The decorator may invoke any method of the delegate object. And the container invokes either the next decorator in the chain or the business method of the intercepted instance.

| Instances of decorators are dependent objects of the bean instance they intercept, i.e. a new decorator instance is created for each intercepted bean.

### 14.4. Events and Observers

Beans may also produce and consume events to interact in a completely decoupled fashion. Any Java object can serve as an event payload. The optional qualifiers act as topic selectors.

Simple Event Example

    class TaskCompleted {
      // ...
    }

    @ApplicationScoped
    class ComplicatedService {

       @Inject
       Event<TaskCompleted> event; (1)

       void doSomething() {
          // ...
          event.fire(new TaskCompleted()); (2)
       }

    }

    @ApplicationScoped
    class Logger {

       void onTaskCompleted(@Observes TaskCompleted task) { (3)
          // ...log the task
       }

    }

1 | `jakarta.enterprise.event.Event` is used to fire events.
2 | Fire the event synchronously.
3 | This method is notified when a `TaskCompleted` event is fired.

| For more info about events/observers visit Weld docs.

## 15. Conclusion

In this guide, we’ve covered some basic topics of the Quarkus programming model that is based on the Jakarta Contexts and Dependency Injection 4.1 specification. Quarkus implements the CDI Lite specification, but not CDI Full. See also the list of supported features and limitations. There are also quite a few non-standard features and Quarkus-specific APIs.

| If you wish to learn more about Quarkus-specific features and limitations there is a Quarkus CDI Reference Guide. We also recommend you to read the CDI specification and the Weld documentation (Weld is a CDI Reference Implementation) to get acquainted with more complex topics.