Micronaut: Declarative HTTP Client
Tags: java, microunaut, microservices
Published: 2019-10-19 21:01:47

---
title: Micronaut: Declarative HTTP Client
published: true
description: Just a hint of what can you do with the declarative HTTP Client of Micronaut
tags: java,microunaut,microservices
---

Currently I'm working on a side project and I decided to use [Microunat](https://micronaut.io/) (if you don't know anything about [Microunat](https://micronaut.io/) [here](https://www.baeldung.com/micronaut) you can read what it is and how it works) and  there is a lot of cool stuff within this "new" framework. 

Some I like the most is the really low memory footprint, [Micronaut Data](https://micronaut-projects.github.io/micronaut-data/latest/guide/) and the possibility to be compiled to native code using [GraalVM](https://www.graalvm.org/). But those are not the only "cool" features this framework has out of the box. 

In order to make our lives easier as developers the [Microunat](https://micronaut.io/) guys included a declarative client to easily test our endpoints, also less verbose. Is a very simple to use, first you'll need to create a simple `interface` to "declare" the operations to be tested and delegate to the `application-context` the binding using the `url` and the requested operations. 

Let's assume we need to test the `get by id operation` for users:

```java 
@Controller(value = "/user")
class UserController {

  @Inject
  private UserService userService;

  @Get(value = "/{id}")
  public User getById(@PathVariable("id") final Long id) {
    return userService.get(id);s
  } 

}
```
So, we can use the `EmbeddedServer` and the `HttpClient` (or the `RxHttpClient`) to test the operation, as it shows the following example: 

```java 
@MicronautTest
class UserControllerTest {
  
  @Inject
  private EmbeddedServer embeddedServer;

  @Test
  void testGet_WithBlocking() throws MalformedURLException {
    final var url = format("http://%s:%s", embeddedServer.getHost(), 
        embeddedServer.getPort());
    final var client = HttpClient.create(new URL(url));

    final HttpResponse<User> response = client.toBlocking()
        .exchange(HttpRequest.GET("/user/1"), User.class);

    Assertions.assertEquals(response.getStatus(), HttpStatus.OK);
    Assertions.assertNotNull(response.body());
  }
}
```

As you can see is a lot of things to be done, quite easily nevertheless a lot of things to do. But *Is there less verbose way?* The answer is **yes**. Now let's try using the `declarative client`, first of all we need to create an `interface` to "declare" the operations to be tested: 

```java 
@Client(value = "/user")
interface UserClient {

    @Get(value = "/{id}")
    User getById(final Long id);

}
```

As you can see is only a *contract* to be satisfied and the annotation `@Client` will tell to the `test application context` that we're are creating a `HttpClient` and it has to look for an implmentation or `Controller` to satisfy the operations we're requesting. 

And now our `test-class` will look as the following: 
```java 
@MicronautTest
class UserControllerTest {
  
  @Inject
  private UserClient userClient;

  @Test
  void testGet_WithBlocking() {
    final var user = userClient.getById(1L);
    Assertions.assertNotNull(user);
  }
}
```
As you can see is pretty simple and we're avoiding using the server and the creation of the request, we're delegating the binding to the context itself the satisfaction of our contract. Using the `declarative client` we can improve our code defining a simple contract to be used as based for the implementation and the client. 
```java 
class UserController {

    @Get("/{id}")
    User getById(final Long id);
    
}
```
For the implementation
```java 
@Controller(value = "/user")
class UserControllerImpl implements UserController {

  @Inject
  private UserService userService;

  @Override
  public User getById(@PathVariable("id") final Long id) {
    return userService.get(id);
  } 

}
``` 
For the test class
```java 
@MicronautTest
class UserControllerTest {
  
  @Client(value = "/user")
  @Inject
  private UserClient userClient;

  @Test
  void testGet_WithBlocking() throws MalformedURLException {
    final var user = userClient.getById(1L);
    Assertions.assertNotNull(user);
  }
}
```
Leaving us with a version more clear and simplier, avoiding the unecessary classes or interfaces, now we can ensure we're satisfaying exactly the same contract in the implematation and the test. 

I'll leave the official documentation for the [Declarative Http Client](https://guides.micronaut.io/micronaut-http-client-groovy/guide/index.html). 

Great coding!