Vertx, Guice and Config Retriever: Dependency Injection in Vertx 4.x
Tags: java, webdev, cloud, technology
Published: 2021-06-23 10:23:33

---
title: Vertx, Guice and Config Retriever: Dependency Injection in Vertx 4.x
published: true
description: 
tags: #java, #webdev, #cloud, #technology
cover_image: https://mednikov.me/wp-content/uploads/2021/06/pexels-josh-sorenson-4678283-480x320.jpg
canonical_url: https://mednikov.me/dependency-injection-in-vertx-4-x/
---

In computer science, the _dependency injection_ is defined as a pattern, whereby one component gets other components (dependencies) from outside. Numerous posts were written about various implementations of a dependency injection in Vertx using Google Guice library. All of them are good and I do not want to reinvent a bicycle here and to repeat same things again. However, in my opinion, it is a good idea to give a bit more systematic approach to this topic. In my experience, in most cases, for developers is not a big deal to implement a basic DI with Vertx, rather it seems hard to incorporate Vertx components into the DI pipeline. In this post we will review how to do a [dependency injection in Vertx](https://mednikov.me/dependency-injection-in-vertx-4-x/) with Google Guice and how to to build a basic injection that has the __ConfigRetriever__ component (Vertx's way to obtain an application configuration). Please note, that in this article we use Futures API, so it is focused on Vertx 4.x developers.

## Basic DI with Google Guice

[Google Guice](https://justin.abrah.ms/misc/an-overview-of-guice-java-dependency-injection.html) is an established solution to implement a dependency injection technique in Java applications. Like most established libraries, it is quite simple to use, yet it does not mean that it is limited in any way. This is very flexible and powerful solution. Main building blocks of the framework are modules and injectors. The module is used to define how to get dependencies. The injector serves as a main entry point of an application and is used for an actual component initialization. Let have a quick example, that uses a constructor injection technique. Imagine, that you develop a verticle, that has two external dependencies - a client class (that performes HTTP calls) and a repository class (that does database operations). For sure, we will not do here their precise implementations, because it is out of the scope of the post. In order to specify these dependencies classes inside the verticle we need to use an __@Inject__ annotation. If you are familiar with the Spring framework, you would find a process familiar. Basically, we need to create fields to keep references for components, define a constructor and annotate it with the __@Inject__, so Guice will know that we use a constructor injection. 

Take a look on the following code snippet below:

```java
class ProjectVerticle extends AbstractVerticle {

    private ProjectClient client;
    private ProjectRepository repository;

    @Inject
    ProjectVerticle(ProjectClient client, ProjectRepository repository){
        this.client = client;
        this.repository = repository;
    }

    // ...
```

Another step is to tell Guice how these classes are created. For that, we need to create a _module_. Keeping simple, this component define what is called bindings (again, if you are an experienced Spring developer, you call this wiring). Modules extend an __AbstractModule__ class, provided by Guice, and override the __configure()__ method, which is utilized for bindings. For our example, we will make it simple:

```java
class ProjectVerticleModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(ProjectClient.class).to(ProjectClientImpl.class);
        bind(ProjectRepository.class).to(ProjectRepositoryImpl.class);
    }
}
```

You can note, that we bind types (interfaces) to instances. There are several types of bindings, that are available in Guice:

- [Instance binding](https://github.com/google/guice/wiki/InstanceBindings) = we map a dependency to the specific instance; this is a good choice for simple dependencies, but for bigger it should be avoid, as it will slow down a start up time. We use it in the next section
- [Linked binding](https://github.com/google/guice/wiki/LinkedBindings) = we map a dependency to its implementation, and Guice creates an instance for us; this is what we used here
- [Provider binding](https://github.com/google/guice/wiki/ProviderBindings) = we provide an own implementation of the __Provider__ interface, that is used to create dependencies; this is a case for complex dependencies; in this post we will omit it

Once we have created a module, we can use it in order to create components. For that we need to use an _injector_, which is defined as a class, that builds graphs of objects that make up our application. An injector takes one or many modules, and uses them to understand how actually to provide requested dependencies and to create an instance of the component. Take a look on the following example:

```java
@Test
void injectTest(Vertx vertx, VertxTestContext context){
    // create a module
    ProjectVerticleModule module = new ProjectVerticleModule();

    // create an injector
    Injector injector = Guice.createInjector(module);

    // get an instance of verticle
    ProjectVerticle verticle = injector.getInstance(ProjectVerticle.class);

    // deploy the ProjectVerticle
    Future<String> deploy = vertx.deployVerticle(verticle);
    deploy.onComplete(id -> {
        context.verify(() -> {
            String client = verticle.getProjectClientName();
            String repository = verticle.getProjectRepositoryName();

            Assertions.assertThat(client).isEqualTo("ProjectClientImpl");
            Assertions.assertThat(repository).isEqualTo("ProjectRepositoryImpl");

            context.completeNow();
        });
    }).onFailure(err -> context.failNow(err));
}
```

You can note, that we use an injector to initialize the __ProjectVerticle__ component, instead of using the __new__ keyword. In other words, we can say, that we "out source" the initialization process to Guice. We could verify that dependencies were created correctly, by validating their names. This is an easy example. Now, let move to more practical topic - how we can incorporate actual Vertx components in the DI pipeline.

## Adding ConfigRetriever

In this subsection we will review a bit more complex (and real life) example. Often (if not always) you need to create components, that use configurations from the outer world. A naive example, is a repository, that listens database credentials, or an http client, that need requires API tokens. In the Vertx world, in order to read a configuration we use the [vertx config library](https://vertx.io/docs/vertx-config/java/). We will not cover all aspects of its usage; I recommend you to review my ebook [Principles of Vertx](https://mednikov.me/principles-of-vertx/), where I cover it in details. For the purpose of this post, you just need to remember, that the key component that does this job is called __ConfigRetriever__. This class abstracts particular configuration types and provides a single entry point (and also it allows to listen of configuration updates; but this is out of the scope of this article). In order to initialize it, we use a static factory method, that requires a reference to the __Vertx__ object:

```java
private ConfigRetriever configRetriever;

AppVerticleModule(Vertx vertx){
    configRetriever = ConfigRetriever.create(vertx);
}

@Override
protected void configure() {
    bind(ConfigRetriever.class)
        .annotatedWith(Names.named("ConfigRetriever"))
        .toInstance(configRetriever);
}
```

Here we define a dependency using the familiar _instance binding_. Note, we also use an optional [naming binding](https://www.tutorialspoint.com/guice/guice_named_binding.htm) here: in the consumer class (verticle) we provide a __@Named__ annotation with the constructor dependency injection. 

```java
@Inject
AppVerticle(@Named("ConfigRetriever") ConfigRetriever configRetriever){
    this.configRetriever = configRetriever;
}
```

The config retriever component is used in order to get a configuration for the application. This is done using the __getConfig__ method. In this post we use [Futures API](https://mednikov.me/an-introduction-to-vertx-4-x-futures/) (Vertx 4.x) instead of callbacks (Vertx 3.x + Vertx 4.x):

```java
Future<JsonObject> cr = configRetriever.getConfig();

Future<ProjectVerticle> vert = cr.map(c -> {
    logger.info("Configuration obtained successfully");
    Injector injector = Guice.createInjector(new ProjectVerticleModule(vertx, c));
    ProjectVerticle verticle = injector.getInstance(ProjectVerticle.class);
    return verticle;
}).onFailure(err -> {
    logger.warning("Unable to obtain configuration");
    startPromise.fail(err);
});
```

Let review this code snippet. The first step is to obtain a future of the configuration reading. Then we _map_ the result in order to create an injector and to initailize the __ProjectVerticle__. We also provide config to the module in order to use them in dependency buildings (like credentials, tokens etc). If the config retriever fails to get a configuration, we fail the whole __start(__ process of the __AppVerticle__.

The next stage is to deploy the project verticle. Take a look on the following implementation:

```java
Future<String> dr = vert.compose(v -> vertx.deployVerticle(v));

dr.onSuccess(id -> {
    logger.info("ProjectVerticle deployed");
    startPromise.complete();
}).onFailure(err -> {
    logger.warning("Unable to deploy ProjectVerticle");
    logger.warning(err.getMessage());
    startPromise.fail(err);
});
```

The future composition allows to connect two futures (configuration and deployment). The lambda parameter __v__ here is the verticle, created inside the __map()__ method in the previous step. The topic of using Futures API is out of the scope of this post, so we will not cover things in details here. Basically, we have two outcomes:

- __onSuccess__ = the verticle is successfully deployed and we complete the __AppVerticle__ starting process
- __onFailure__ = something went wrong! We fail the __AppVerticle__ starting process

Let put everyting together. Inside the __main__ method of our fictional application we create a module and an injector for the __AppVerticle__ and deploys it. Here we do not need to deploy other verticles, because the __AppVerticle__ serves as an entry point of our app and does this job:

```java
public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    Injector injector = Guice.createInjector(new AppVerticleModule(vertx));

    AppVerticle appVerticle = injector.getInstance(AppVerticle.class);
    Future<String> dr = vertx.deployVerticle(appVerticle);

    dr.onSuccess(id -> logger.info("AppVerticle started..."))
    .onFailure(err -> {
        logger.warning("Unable to start AppVerticle");
        logger.warning(err.getMessage());
    })
    .onComplete(r -> {
        vertx.close();
        logger.info("Vertx closed");
    });

}
```

## Source code

If you would like to get full source code used in examples in this post, you can find it in [this github repository](https://github.com/realyurimednikov/vertx4-examples). Feel free to explore it!

## Conslusion

Simply speaking, the dependency injection is a pattern that allows to "outsource" the creation of components. There are several proven solutions to implement this architecture in Java apps and the Google Guice library is one of them. It is simple, but in the same time powerful. In this post we reviewed how to implement dependency injection in Vertx 4.x applications. We did two examples: one is a simple demonstration of essential Guice methods. The second uses an actual Vertx component - the __ConfigRetriever__, that reads a configuration and provides it to other components (that in their turn is also used to create other dependencies). If you have questions regarding this topic, please feel free to [contact me](https://mednikov.me/who-am-i/) or drop a comment below.