Implementando Spring com AWS Lambda

Antes de começarmos, é importante lembrar que você precisará ter uma conta na AWS e configurar suas credenciais de acesso para poder seguir este tutorial. Além disso, você precisará ter o Spring Framework e o AWS SDK para Java instalados em sua máquina.

Para começar, crie um novo projeto Spring Boot utilizando o Spring Initializr (https://start.spring.io/) e adicione as seguintes dependências ao arquivo pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-core</artifactId>
    <version>1.2.0</version>
</dependency>

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-lambda</artifactId>
    <version>1.11.1029</version>
</dependency>

Essas dependências adicionam suporte para desenvolvermos uma aplicação Spring Boot que possa ser empacotada e executada como uma função AWS Lambda.

Em seguida, crie um arquivo de propriedades chamado application.properties no diretório src/main/resources com as seguintes configurações:

server.port=5000
  

Essa propriedade irá configurar a porta em que o servidor web embutido do Spring Boot será iniciado.

Em seguida, crie uma classe chamada MyLambdaFunction com a seguinte implementação:

package com.example.demo;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan(basePackages = "com.example.demo")
public class MyLambdaFunction implements RequestHandler<Object, Object> {

    private static ApplicationContext applicationContext;

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

    @Override
    public Object handleRequest(Object input, Context context) {
        context.getLogger().log("Input: " + input);

        return applicationContext.getBean(MyController.class).handleRequest(input);
    }
}

Essa classe é a nossa função AWS Lambda. Ela estende a classe RequestHandler<Object, Object> e implementa o método handleRequest que será invocado quando a função for chamada. O método handleRequest usa o objeto ApplicationContext do Spring para obter uma instância da classe MyController e delegar o processamento da requisição a ela.

Observe que a classe MyLambdaFunction também é anotada com @SpringBootApplication e @ComponentScan(basePackages = "com.example.demo"). A anotação @SpringBootApplication é uma combinação de outras anotações do Spring que configuram a aplicação. A anotação @ComponentScan é usada para especificar quais pacotes devem ser escaneados pelo Spring em busca de componentes e configurações.

Em seguida, crie uma classe chamada MyController com a seguinte implementação:

package com.example.demo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
@Controller
public class MyController {
  @Value("${server.port}")
  private int serverPort;

  public ResponseEntity<String> handleRequest(Object input) {
      String response = "Hello, AWS Lambda! Server port: " + serverPort;
      return ResponseEntity.ok(response);
  }
}

Essa classe é responsável por lidar com a requisição. Observe que ela é anotada com `@Controller` para indicar ao Spring que ela é um controlador web. A classe também possui um campo anotado com `@Value(“${server.port}”)`. Essa anotação injeta o valor da propriedade `server.port` do arquivo `application.properties` na variável `serverPort`. O método `handleRequest` recebe um objeto como entrada e retorna um objeto `ResponseEntity` que encapsula a resposta HTTP. Nesse caso, a resposta é uma mensagem simples que contém o número da porta do servidor. Finalmente, crie um arquivo chamado `template.yaml` na raiz do projeto com o seguinte conteúdo:

Resources:
  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: target/demo-0.0.1-SNAPSHOT.jar
      Handler: com.example.demo.MyLambdaFunction
      Runtime: java11
      MemorySize: 256
      Timeout: 30
      Events:
        GetResource:
          Type: Api
          Properties:
            Path: /hello
            Method: get

Esse arquivo define a configuração da função AWS Lambda e como ela será exposta através da API Gateway da AWS. Observe que o nome `MyLambdaFunction` precisa ser o mesmo que o nome da classe que definimos anteriormente. Para testar a nossa função AWS Lambda, execute o seguinte comando na raiz do projeto:

$ mvn package

Esse comando irá gerar um arquivo JAR que contém a nossa aplicação Spring Boot e todas as suas dependências. Em seguida, faça o upload desse arquivo JAR para a AWS Lambda usando o AWS CLI:

$ aws lambda create-function --function-name my-function
--zip-file fileb://target/demo-0.0.1-SNAPSHOT.jar
--handler com.example.demo.MyLambdaFunction
--runtime java11
--role <role-arn>
--timeout 30
--memory-size 256

Observe que você precisará substituir `<role-arn>` pelo ARN do IAM Role que a sua função AWS Lambda irá usar. Por fim, faça a configuração da API Gateway para expor a função AWS Lambda:

$ aws apigateway create-rest-api --name my-api
$ aws apigateway create-resource --rest-api-id <rest-api-id> --parent-id <parent-resource-id> --path-part hello
$ aws apigateway put-method --rest-api-id <rest-api-id> --resource-id <resource-id> --http-method GET --authorization-type NONE
$ aws apigateway put-method-response --rest-api-id <rest-api-id> --resource-id <resource-id> --http-method GET --status-code 200 --response-models "{"application/json": "Empty"}"
$ aws apigateway put-integration --rest-api-id <rest-api-id> --resource-id <resource-id> --http-method GET --type AWS --integration-http-method POST --uri arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account-id>:function:my-function/invocations
$ aws apigateway put-integration-response --rest-api-id <rest-api-id> --resource-id <resource-id> --http-method GET --status-code 200 --response-templates "{"application/json": ""}"

Observe que você precisará substituir , , , e pelos valores correspondentes na sua conta AWS.

Por fim, faça o deploy da API Gateway:

$ aws apigateway create-deployment --rest-api-id <rest-api-id> --stage-name prod

Agora a nossa função AWS Lambda está pronta para ser testada. Faça uma requisição GET para a URL da API Gateway e você deverá receber a mensagem de resposta que definimos anteriormente.

Espero que este artigo tenha ajudado você a entender como implementar uma solução utilizando AWS Lambda e Spring. Lembre-se de que essa é apenas uma das muitas maneiras de implementar soluções na nuvem, e que a AWS oferece uma ampla gama de serviços que podem ser combinados para atender às necessidades do seu projeto.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.