Vert.x Spring Integration

1. Overview

In this quick article, we’ll discuss the integration of Spring with
Vert-x and leverage the best of both worlds: the powerful and well-known
Spring feature, and the reactive single-event loop from Vert.x.

To understand more about Vert.x, please refer to our introductory
article here.

2. Setup

First, let’s get our dependencies in place:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-web</artifactId>
    <version>3.4.1</version>
</dependency>

Notice that we’ve excluded the embedded Tomcat dependency from
spring-boot-starter-web since we are going to deploy our services
using verticles.

You may find the latest dependencies
here.

3. Spring Vert.x Application

Now, we’ll build a sample application with two verticles deployed.

The first Verticle routes requests to the handler that sends them as
messages to the given address. The other Verticle listens at a given
address.

Let’s look at these in action.

3.1. Sender Verticle

ServerVerticle accepts HTTP requests and sends them as messages to a
designated address.
Let’s create a ServerVerticle class extending the
AbstractVerticle, and override the start() method to create our HTTP
Server:

@Override
public void start() throws Exception {
    super.start();

    Router router = Router.router(vertx);
    router.get("/api/baeldung/articles")
      .handler(this::getAllArticlesHandler);

    vertx.createHttpServer()
      .requestHandler(router::accept)
      .listen(config().getInteger("http.port", 8080));
}

In the server request handler, we passed a router object, which
redirects any incoming request to the getAllArticlesHandler handler:

private void getAllArticlesHandler(RoutingContext routingContext) {
    vertx.eventBus().<String>send(ArticleRecipientVerticle.GET_ALL_ARTICLES, "",
      result -> {
        if (result.succeeded()) {
            routingContext.response()
              .putHeader("content-type", "application/json")
              .setStatusCode(200)
              .end(result.result()
              .body());
        } else {
            routingContext.response()
              .setStatusCode(500)
              .end();
        }
      });
}

In the handler method, we’re passing an event to the Vert.x Event bus,
with an event id as GET_ALL_ARTICLES. Then we process the callback
accordingly for success and error scenarios.

The message from the event bus will be consumed by the
ArticleRecipientVerticle, discussed in the following section.

3.2. Recipient Verticle

ArticleRecipientVerticle listens for incoming messages and injects a
Spring bean
. It acts as the rendezvous point for Spring and Vert.x.

We’ll inject Spring service bean into a Verticle and invoke respective
methods:

@Override
public void start() throws Exception {
    super.start();
    vertx.eventBus().<String>consumer(GET_ALL_ARTICLES)
      .handler(getAllArticleService(articleService));
}

Here, articleService is an injected Spring bean:

@Autowired
private ArticleService articleService;

This Verticle will keep listening to the event bus on an address
GET_ALL_ARTICLES. Once it receives a message, it delegates it to the
getAllArticleService handler method:

private Handler<Message<String>> getAllArticleService(ArticleService service) {
    return msg -> vertx.<String> executeBlocking(future -> {
        try {
            future.complete(
            mapper.writeValueAsString(service.getAllArticle()));
        } catch (JsonProcessingException e) {
            future.fail(e);
        }
    }, result -> {
        if (result.succeeded()) {
            msg.reply(result.result());
        } else {
            msg.reply(result.cause().toString());
        }
    });
}

This performs the required service operation and replies to the message
with the status. The message reply is being referenced at the
ServerVerticle and the callback result as we saw in the earlier
section.

4. Service Class

The service class is a simple implementation, providing methods to
interact with the repository layer:

@Service
public class ArticleService {

    @Autowired
    private ArticleRepository articleRepository;

    public List<Article> getAllArticle() {
        return articleRepository.findAll();
    }
}

The ArticleRepository extends,
org.springframework.data.repository.CrudRepository and provides basic
CRUD functionalities.

5. Deploying Verticles

We will be deploying the application, just the way we would do for a
regular Spring Boot application. We have to create a Vert.X instance,
and deploy verticles in it, after the Spring context initialization in
completed:

public class VertxSpringApplication {

    @Autowired
    private ServerVerticle serverVerticle;

    @Autowired
    private ArticleRecipientVerticle articleRecipientVerticle;

    public static void main(String[] args) {
        SpringApplication.run(VertxSpringApplication.class, args);
    }

    @PostConstruct
    public void deployVerticle() {
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(serverVerticle);
        vertx.deployVerticle(articleRecipientVerticle);
    }
}

Notice that, we are injecting verticle instances into the Spring
application class. So, we will have to annotate the Verticle classes,

So, we will have to annotate the Verticle classes, ServerVerticle and
ArticleRecipientVerticle with @Component.

Let’s test the application:

@Test
public void givenUrl_whenReceivedArticles_thenSuccess() {
    ResponseEntity<String> responseEntity = restTemplate
      .getForEntity("http://localhost:8080/api/baeldung/articles", String.class);

    assertEquals(200, responseEntity.getStatusCodeValue());
}

6. Conclusion

In this article, we learned about how to build a RESTful WebService
using Spring and Vert.x.

As usual, the example is available
over on
GitHub.

Leave a Reply

Your email address will not be published.