1

I understand the role of CDI in JavaEE web apps where they help pass on user session data between beans. Is there a good reason to use CDI in a Java SE or Java EE app, in the absence of user sessions?

seinecle
  • 10,118
  • 14
  • 61
  • 120
  • CDI stands for "Context- and Dependency Injection". The whole dependency injection is based on CDI (e.g. everything you annotate with `@Inject` is processed by CDI). – Turing85 Dec 22 '19 at 15:29
  • And what is it used for? – seinecle Dec 22 '19 at 15:30
  • 2
    "*And what is it used for?*" - [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection). – Turing85 Dec 22 '19 at 15:31
  • Sure, and is there a use case for dependency injection beyond managing stateful sessions? – seinecle Dec 22 '19 at 15:33
  • Yes: decoupling. Less coupling leads to less rigidity, which, in turn, leads to less bugs, better testability and faster development cycles. It can also lead to a cleaner architecture, e.g. by separating your endpoints from the actual business-logic (services) and the business logic from the persistence layer (although this is a subjective metric). I would recommend looking up [SOLID-principles](https://en.wikipedia.org/wiki/SOLID) or other well-known architecture principles for a more in-depth explanation. – Turing85 Dec 22 '19 at 15:36
  • I understand what decoupling is. But practically, in a Java app with two pojos, I can instantiate one in another by using a constructor. Or use an @Inject annotation with the CDI approach. How does the CDI approach achieves a higher level of decoupling, compared to the constructor approach? – seinecle Dec 22 '19 at 15:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/204676/discussion-between-turing85-and-seinecle). – Turing85 Dec 22 '19 at 15:43
  • See [Introduction to Contexts and Dependency Injection for Java EE](https://docs.oracle.com/javaee/7/tutorial/cdi-basic.htm) – Jonathan Rosenne Dec 22 '19 at 15:49
  • In a Java app with two beans it probably doesn't matter. Any real Java app will be... slightly more complex. – Dave Newton Dec 22 '19 at 15:51
  • I've written two articles on this: 1. https://lairdnelson.wordpress.com/2019/05/18/a-cdi-primer-part-0/ 2. https://lairdnelson.wordpress.com/2016/11/15/cdi-2-0/ – Laird Nelson Dec 22 '19 at 19:11
  • @Turing85 Your comments built up a whole answer Would you mind _refactoring_ them to a coherent answer, or should I – hc_dev Dec 23 '19 at 14:11
  • 1
    @hc_dev [Done](https://stackoverflow.com/a/59459360/4216641). – Turing85 Dec 23 '19 at 17:48

2 Answers2

3

There seems to be a misunderstanding about what CDI is. I will explain what it is and then present some use cases and their benefits.


What is CDI?

CDI stands for "Contexts and Dependency Injection". It is the JEE-framwork for Dependency Injection. More information are available on the github tutorial of the project. I skip the explanation of dependency injection, the interested reader can look it up, e.g. on wikipedia.


What are the benefits of Dependency Injection?

The main benefit of deploying dependency injection is less friction: by injecting a dependency into a class, the class is decoupled from its dependency, and the dependency can be swapped without changing the code. I gave an in-depth example in this answer.

Dependency Injection can also lead to a cleaner architecture: a class defining REST-endpoints injects the necessary services. The services, in return, inject the necessary repositories/DAOs. A three-layered architecture is the most typical one, but not necessarily the only/right form. Keep in mind, however, that an architecture is

  • a) alive, i.e. it changes as the project evolves
  • b) something that should always be decided, or at lest discussed, with the project team. If the team is not fond of the architecture, it will not follow it and thus render it useless.
  • c) a subjective metric. Seldom will one find cases where one architecture is the best architeture. Most of the time, it is a matter of taste.

Examples of architectures/principles that are to a major part based on Dependency Injection are the SOLID-principles and hexagonal architecture.

Another benefit stemming from less coupling is better testability. By injecting mocks of the dependencies, one can test, for example, a single service in isolation.


Closing words

With great power comes great responsibility. Software engineering is not about decoupling everything from everything else. Most of the time, it is deciding where decoupling is needed and where coupling is wanted. Too much abstraction and decoupling can lead to an unreadable mess that is hard to maintain. As an example: As much as I like CDI events, they have the tendency to obscure the actual workflow of the business logic, especially if events are fired and observed at multiple places.

On a technical note, one should avoid field injection. The DI-framework must employ reflection in order to make field injection viable. This alone should be a deal breaker. Furthermore, the dependencies of a class get obscured. If a dependency is added or removed, the bean will still be created, possibly with a null value where another bean should be. The same holds true for setter injection. This is why constructor injection is considered the cleanest of the three methods.

Turing85
  • 18,217
  • 7
  • 33
  • 58
0

Here are some use cases for Java EE CDI in a JavaSE app

1 Event Bus

public void someMethod(@Observes @SomeFilter(SomeContext.SOME_FLAG) SomeEvent event) { ....

2 Patterns

@Produces
@Dependent
@ChartCanvasResult(DataFlow.CTS_FLOW)
Canvas canvasChart;

@Inject
@ModelResult(SomeContext.SOME_FLAG)
List<Double> someDataSinkList;

@Dependent
@Named("SomeService")
class SomeServiceImpl  implements SomeService {

3 Application bootstrap context

 Weld weld = new Weld();
 WeldSEShutdownHook shutdownHook = new WeldSEShutdownHook(weld);
 Runtime.getRuntime().addShutdownHook(shutdownHook);
 weldContainer = weld.initialize();

4 Runtime Context

   public Object call(Class<?> clazz) {
    log.debug("creating controller= {}", clazz.getSimpleName());

    try {
        return WeldSe.get(clazz);
    } catch (Exception e) {
        log.error("Error creating controller= " + clazz, e);
        throw new RuntimeException(e);
    }
}

1 to 4 above allow me to manage the bootstrap, runtime object graph, shutdown, and layout my code with enterprise patterns.
Weld

Nigel Savage
  • 991
  • 13
  • 26