1
 
 
Account
In your account you can view the status of your application, save incomplete applications and view current news and events
wMetadata:title
September 21, 2020

Writing an AWS Lambda using Micronaut

What is the article about?

In this article, we will look at one option to write a Java AWS Lambda using the still rather new microframework Micronaut and we’re going to deploy our code to production by means of Serverless.

If you’re reading this, you’re probably already familiar with AWS Lambda, an AWS product which allows developers to run small applications without having to worry about any infrastructure that backs it up. One just needs to upload a piece of code to AWS and the program is called. Then, AWS will take care of finding out where and how to execute it (on demand). 

In this article we’ll see one way to write a Java AWS Lambda using the still rather new micro framework Micronaut and we’re going to deploy our code to production by means of Serverless.

The problem to be solved

In this example, we want to write an AWS Lambda which implements a REST endpoint called /capital/{country}. This endpoint will consume the REST Countries API and reply to us with the capital of a given country. Finally, we use an AWS API Gateway to call our Lambda as follows:

Response:

{
      "capital”: “<capital>”
}

Request:

 curl <api-gateway-url>/capital/{country}

The solution

We’re building a classic class structure which begins with a Controller, which calls a Service and this Service then calls a Client:

test
test

A controller class is always annotated with @Controller and has a path as a parameter. Similarly, our public endpoint is annotated with @Get:

@Controller("/")
public class CapitalController {
   @Inject
   public RestCountriesService restCountriesService;
   @Get("/capital/{country}")
   public String getCapital(@PathVariable @NotBlank String country) {
     return "{\"capital\": \"" + 
restCountriesService.getCapital(country) + "\"}";
   }
}

As you can see, this controller injects a service, which is typically annotated with @Prototype:

@Prototype
public class RestCountriesService {

  @Inject
  public RestCountriesClient restCountriesClient;

  public String getCapital(String country) {
    returnOptional.ofNullable
     (restCountriesClient.fetchCountry(country))
       .flatMap(restCountriesResponses -> 
restCountriesResponses.stream().findFirst())
       .map(RestCountriesResponse::getCapital)
       .orElseThrow(() -> new HttpStatusException(NOT_FOUND,
         "Couldn't find country " + country));
  }
}

@Prototype tells Micronaut to create a new instance of the annotated class on every injection point. This is equivalent to @Component in Spring Boot. 

In order to carry out an HTTP call, Micronaut provides us with a feature called "declarative client", which consists of an interface that calls a given endpoint and maps the response to a DTO by means of Jackson:

@Client("${restCountries.apiUrl}")
interface RestCountriesClient  {



      @Get("/name/{country}")
      List<RestCountriesResponse> fetchCountry(@PathVariable String 
country);
}

This interface needs to be annotated with @Client and the base URL of the endpoint we want to call. In this case, we defined this URL in an application.yml file, just as one would do it in Spring Boot:

restCountries:
  apiUrl: https://restcountries.eu/rest/v2

Then, we need to define a method for each endpoint which is annotated with the desired HTTP method and optionally a path that is appended to the base URL, previously defined in @Client. Additional parameters such as headers or query parameters must be provided to the method. 

You can find the complete list of possible parameters here: https://docs.micronaut.io/latest/guide/index.html#binding

After calling fetchCountry(), the class RestCountriesResponse will be already initialised with the values from the request's response body.

Deployment

As we want to deploy our service using Serverless, we first need to install it using npm:

   npm install

Then, we deploy the service using this script: deploy.sh 

This will run the Gradle build and deploy the service to AWS. As a result, we'll be able to call our endpoint from anywhere in the Internet.

Learnings

While working with Micronaut we realized that it’s easy to learn, especially having previous experience with other frameworks such as Spring Boot and it's well documented, with lots of examples and guides. 

Although we haven’t talked about it in this article, we also used GraalVM, which is a very promising solution to reduce Lambda cold starts. However, it is a rather complex solution which is certainly not easy to set up, particularly if third-party libraries are required. 

The whole application together with tests is available in GitHub from the link below.

Resources

1 person likes it.

0No comments yet.

Write a comment
Answer to: Reply directly to the topic

Written by

Henrik Horeis
Software Developer
Xavier Juste Alvarez
Software Developer

Similar Articles

We want to improve out content with your feedback.

How interesting is this blogpost?

We have received your feedback.

Allow cookies?

OTTO and three partners need your consent (click on "OK") for individual data uses in order to store and/or retrieve information on your device (IP address, user ID, browser information).
Data is used for personalized ads and content, ad and content measurement, and to gain insights about target groups and product development. More information on consent can be found here at any time. You can refuse your consent at any time by clicking on the link "refuse cookies".

Data uses

OTTO works with partners who also process data retrieved from your end device (tracking data) for their own purposes (e.g. profiling) / for the purposes of third parties. Against this background, not only the collection of tracking data, but also its further processing by these providers requires consent. The tracking data will only be collected when you click on the "OK" button in the banner on otto.de. The partners are the following companies:
Google Ireland Limited, Meta Platforms Ireland Limited, LinkedIn Ireland Unlimited Company
For more information on the data processing by these partners, please see the privacy policy at otto.de/jobs. The information can also be accessed via a link in the banner.