:toc: macro toc::[] = Dependency Injection Dependency injection is one of the most important design patterns and is a key principle to a modular and component based architecture. The Java Standard for dependency injection is http://docs.oracle.com/javaee/6/api/javax/inject/package-summary.html[javax.inject (JSR330)] that we use in combination with http://docs.oracle.com/javaee/5/api/javax/annotation/package-summary.html[JSR250]. Additionally, for scoping you can use CDI (Context and Dependency Injection) from https://jcp.org/en/jsr/detail?id=365[JSR365]. There are many frameworks which support this standard including all recent Java EE application servers. Therefore in devonfw we rely on these open standards and can propagate patterns and code examples that work independent from the underlying frameworks. == Key Principles Within dependency injection a _bean_ is typically a reusable unit of your application providing an encapsulated functionality. This _bean_ can be injected into other beans and it should in general be replaceable. As an example we can think of a link:guide-usecase[use-case], a link:guide-repository[repository], etc. As best practice we use the following principles: * *Stateless implementation* + By default such beans shall be implemented link:coding-conventions#stateless-programming[stateless]. If you store state information in member variables you can easily run into concurrency problems and nasty bugs. This is easy to avoid by using local variables and separate state classes for complex state-information. Try to avoid stateful beans wherever possible. Only add state if you are fully aware of what you are doing and properly document this as a warning in your JavaDoc. * *Usage of Java standards* + We use common standards (see above) that makes our code portable. Therefore we use standardized annotations like `@Inject` (`javax.inject.Inject`) instead of proprietary annotations such as `@Autowired`. Generally we avoid proprietary annotations in business code (link:guide-logic-layer[logic layer]). * *Simple injection-style* + In general you can choose between constructor, setter or field injection. For simplicity we recommend to do private field injection as it is very compact and easy to maintain. We believe that constructor injection is bad for maintenance especially in case of inheritance (if you change the dependencies you need to refactor all sub-classes). Private field injection and public setter injection are very similar but setter injection is much more verbose (often you are even forced to have javadoc for all public methods). If you are writing re-usable library code setter injection will make sense as it is more flexible. In a business application you typically do not need that and can save a lot of boiler-plate code if you use private field injection instead. Nowadays you are using container infrastructure also for your tests (see link:guide-testing[testing]) so there is no need to inject manually (what would require a public setter). * *KISS* + To follow the KISS (keep it small and simple) principle we avoid advanced features (e.g. custom link:guide-aop[AOP], non-singleton beans) and only use them where necessary. * *Separation of API and implementation* + For important components we should separate a self-contained API documented with JavaDoc from its implementation. Code from other components that wants to use the implementation shall only rely on the API. However, for things that will never be exchanged no API as interface is required you can skip such separation. == Example Bean Here you can see the implementation of an example bean using dependency injection: [source, java] ---- @ApplicationScoped @Named("MyComponent") public class MyComponentImpl implements MyComponent { @Inject private MyOtherComponent myOtherComponent; @PostConstruct public void init() { // initialization if required (otherwise omit this method) } @PreDestroy public void dispose() { // shutdown bean, free resources if required (otherwise omit this method) } ... } ---- Here `MyComponentImpl` depends on `MyOtherComponent` that is injected into the field `myOtherComponent` because of the `@Inject` annotation. To make this work there must be exactly one bean in the container (e.g. link:spring[spring] or link:quarkus[quarkus]) that is an instance of `MyOtherComponent`. In order to put a bean into the container, we can use `@ApplicationScoped` in case of CDI (required for quarkus) for a stateless bean. In spring we can ommit a CDI annotation and the `@Named` annotation is already sufficient as a bean is stateless by default in spring. If we always use `@ApplicationScoped` we can make this more explicit and more portable accross different frameworks. So in our example we put `MyComponentImpl` into the container. That bean will be called `MyComponent` as we specified in the `@Named` annotation but we can also omit the name to use the classname as fallback. Now our bean can be injected into other beans using `@Inject` annotation either via `MyComponent` interface (recommended when interface is present) or even directly via `MyComponentImpl`. In case you omit the interface, you should also omit the `Impl` suffix or instead use `Bean` as suffix. == Multiple bean implementations In some cases you might have multiple implementations as beans for the same interface. The following sub-sections handle the different scenarios to give you guidance. === Only one implementation in container In some cases you still have only one implementation active as bean in the container at runtime. A typical example is that you have different implemenations for test and main usage. This case is easy, as `@Inject` will always be unique. The only thing you need to care about is how to configure your framework (spring, quarkus, etc.) to know which implementation to put in the container depending on specific configuration. In spring this can be archived via the proprietary `@Profile` annotaiton. === Injecting all of multiple implementations In some situations you may have an interface that defines a kind of "plugin". You can have multiple implementations in your container and want to have all of them injected. Then you can request a list with all the bean implementations via the interface as in the following example: [source, java] ---- @Inject private List converters; ---- Your code may iterate over all plugins (converters) and apply them sequentially. Please note that the injection will fail (at least in spring), when there is no bean available to inject. So you do not get an empty list injected but will get an exception on startup. === Injecting one of multiple implementations Another scenario is that you have multiple implementations in your container coexisting, but for injection you may want to choose a specific implementation. Here you could use the `@Named` annotation to specify a unique identifier for each implementation what is called qualified injection: [source, java] ---- @ApplicationScoped @Named("UserAuthenticator") public class UserAuthenticator implements Authenticator { ... } @ApplicationScoped @Named("ServiceAuthenticator") public class ServiceAuthenticator implements Authenticator { ... } public class MyUserComponent { @Inject @Named("UserAuthenticator") private Authenticator authenticator; ... } public class MyServiceComponent { @Inject @Named("ServiceAuthenticator") private Authenticator authenticator; ... } ---- However, we discovered that this pattern is not so great: The identifiers in the `@Named` annotation are just strings that could easily break. You could use constants instead but still this is not the best solution. In the end you can very much simplify this by just directly injecting the implementation instead: [source, java] ---- @ApplicationScoped public class UserAuthenticator implements Authenticator { ... } @ApplicationScoped public class ServiceAuthenticator implements Authenticator { ... } public class MyUserComponent { @Inject private UserAuthenticator authenticator; ... } public class MyServiceComponent { @Inject private ServiceAuthenticator authenticator; ... } ---- In case you want to strictly decouple from implementations, you can still create dedicated interfaces: [source, java] ---- public interface UserAuthenticator extends Authenticator {} @ApplicationScoped public class UserAuthenticatorImpl implements UserAuthenticator { ... } public interface ServiceAuthenticator extends Authenticator {} @ApplicationScoped public class ServiceAuthenticatorImpl implements ServiceAuthenticator { ... } public class MyUserComponent { @Inject private UserAuthenticator authenticator; ... } public class MyServiceComponent { @Inject private ServiceAuthenticator authenticator; ... } ---- However, as you can see this is again introducing additional boiler-plate code. While the principle to separate API and implementation and strictly decouple from implementation is valuable in general, you should always consider KISS, lean, and agile in contrast and balance pros and cons instead of blindly following dogmas. == Imports Here are the import statements for the most important annotations for dependency injection [source, java] ---- import javax.inject.Inject; import javax.inject.Named; import javax.enterprise.context.ApplicationScoped; // import javax.enterprise.context.RequestScoped; // import javax.enterprise.context.SessionScoped; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; ---- == Dependencies Please note that with https://jakarta.ee/[Jakarta EE] the dependencies have changed. When you want to start with Jakarta EE you should use these dependencies to get the annoations for dependency injection: [source, xml] ---- jakarta.inject jakarta.inject-api jakarta.annotation jakarta.annotation-api jakarta.enterprise jakarta.enterprise.cdi-api ---- Please note that with link:quarkus[quarkus] you will get them as transitive dependencies out of the box. The above Jakarate EE dependencies replace these JEE depdencies: [source, xml] ---- javax.inject javax.inject javax.annotation javax.annotation-api jakarta.enterprise jakarta.enterprise.cdi-api ----