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.