DEV Community

Pedro Henrique
Pedro Henrique

Posted on

Um Guia Prático com Quarkus, SAM e GraalVM - Parte 1 Criando o projeto Quarkus e fazendo deploy com SAM

Introdução

Bem-vindo a esta série de artigos, um guia prático para construir uma aplicação serverless moderna com Java. Nosso objetivo é usar a combinação de Quarkus (com compilação nativa GraalVM) e AWS SAM para enfrentar desafios comuns do Java no ambiente serverless, como o tempo de inicialização (cold starts) e o consumo de memória.

Ao longo desta série, vamos cobrir o ciclo completo de desenvolvimento, desde a fundação até a segurança e a persistência de dados. O nosso roteiro será:

  1. Nesta Parte 1 (o artigo atual), focaremos nos fundamentos: a configuração do projeto, a criação de múltiplas funções Lambda e o deploy automatizado na AWS.
  2. Na Parte 2, adicionaremos uma camada de segurança, integrando nossa aplicação com o Amazon Cognito para gerenciar a autenticação e usando as Lambdas para interagir com a API de usuários.
  3. Na Parte 3, implementaremos a persistência de dados, adicionando uma tabela do Amazon DynamoDB à nossa infraestrutura e manipulando os dados através das Lambdas.

O nosso objetivo hoje é deixar a estrutura básica pronta e funcionando na nuvem. Vamos cobrir:

  • A criação e estruturação de um projeto Java com Quarkus.
  • A implementação das nossas primeiras funções Lambda.
  • O deploy automatizado de toda a estrutura na AWS.

Pré-requisitos

Para acompanhar este tutorial da melhor forma, é ideal que você tenha um ambiente de desenvolvimento preparado. Não vamos cobrir a instalação detalhada de cada ferramenta, mas aqui estão os links e os comandos para você verificar se está tudo pronto para começar.

  • Java (JDK 21): Essencial para rodar o Quarkus e compilar o código. Neste tutorial, usamos a versão 21.

    • Verifique sua versão com: java --version
  • Gradle (8.5+): Usado para gerenciar as dependências e o build do projeto.

  • AWS CLI v2: A ferramenta de linha de comando para interagir com a AWS. É importante que ela esteja configurada com suas credenciais.

  • AWS SAM CLI: A ferramenta principal que usaremos para o build e deploy da nossa aplicação serverless.

  • Container Runtime (Docker ou Podman): Requisito indispensável em nosso fluxo. Embora seja possível compilar uma imagem nativa instalando o GraalVM diretamente na sua máquina, neste tutorial usaremos a abordagem de build via contêiner. Isso garante que o executável seja gerado em um ambiente Linux consistente e compatível com o da AWS Lambda, evitando problemas de compatibilidade entre sistemas operacionais.

    Precisaremos de um contêiner por dois motivos:

    1. Para o build nativo do Quarkus, usando a flag -Dquarkus.native.container-build=true.
    2. Para o AWS SAM CLI, que o utiliza para simular o ambiente da AWS Lambda localmente.
    3. Verifique se está rodando com: docker info ou podman info
    4. Opções de Instalação: Docker Desktop (mais comum) ou Podman (alternativa).
  • Noções de Quarkus: Este guia presume uma familiaridade básica com os conceitos do Quarkus (como injeção de dependência com CDI e anotações JAX-RS para endpoints).

Criando o Projeto com Quarkus

Existem várias maneiras de se iniciar um projeto Quarkus, cada uma adequada a um estilo de trabalho diferente. As principais são:

  • Via Linha de Comando (CLI): Para desenvolvedores que preferem o terminal, é possível usar a CLI oficial do Quarkus ou o próprio wrapper do Gradle para criar o projeto. É uma abordagem rápida e excelente para automação.
  • Via Gerador Web (code.quarkus.io): Uma interface web interativa onde você pode selecionar visualmente as dependências e configurações do seu projeto. É a maneira mais fácil e visual para começar.

Para este tutorial, seguiremos o caminho mais simples e intuitivo, que não exige a instalação de nenhuma ferramenta de linha de comando adicional: o site code.quarkus.io.

Se você já usou o Spring Initializr, a experiência será muito familiar. Ele nos permite configurar tudo visualmente e, ao final, baixar um arquivo .zip com o projeto pronto para ser aberto na sua IDE preferida.

Vamos configurar nosso projeto com as seguintes especificações:

  • Build Tool: Gradle
  • Java Version: 21
  • Group: (use o de sua preferência, ex: br.com.seudominio)
  • Artifact: (use o de sua preferência, ex: sam-quarkus-app)

Em seguida, adicione as seguintes extensões (dependências), que são a base para nossa aplicação serverless:

  1. quarkus-amazon-lambda: A extensão principal que adapta a aplicação Quarkus para ser executada como uma função AWS Lambda.
  2. quarkus-rest (anteriormente RESTEasy Reactive): Fornece o framework JAX-RS para a criação de endpoints REST.
  3. quarkus-rest-jackson: Adiciona o suporte para serialização e desserialização de objetos Java para JSON usando a biblioteca Jackson.

Após selecionar essas opções, clique em "Generate your application" para baixar o .zip com o projeto. Descompacte-o e abra na sua IDE preferida.

Criando projeto java quarkus no code.quarkus.io

Criando nossas primeiras Lambdas

Com o projeto devidamente configurado em nossa IDE, é hora de escrever o código que dará vida às nossas funções. O ponto central da nossa implementação girará em torno de duas dependências essenciais que já adicionamos via code.quarkus.io.

A primeira e mais importante é a io.quarkus:quarkus-amazon-lambda. É ela que faz a ponte entre o ecossistema Quarkus e o runtime da AWS Lambda. Essa extensão é a responsável por nos permitir criar classes que atuam como handlers e nos dá acesso direto às interfaces cruciais da AWS, como RequestHandler, APIGatewayProxyRequestEvent (para receber dados do API Gateway) e APIGatewayProxyResponseEvent (para formular a resposta).

A segunda peça-chave é a io.quarkus:quarkus-rest-jackson. No contexto de uma API, nossos dados trafegam em formato JSON. Esta biblioteca nos fornece o poder da serialização e desserialização de forma transparente. Com ela, conseguimos facilmente converter um JSON recebido no corpo da requisição em um objeto Java (um DTO, por exemplo) e, no caminho inverso, transformar nossos objetos de resposta em uma string JSON válida para o cliente.

Com essas duas ferramentas em mãos, estamos prontos para estruturar nosso código.

Criando nossos primeiros handlers

Com o projeto estruturado, vamos criar e analisar nossas classes Handler. Começaremos com um exemplo mínimo e depois avançaremos para um que manipula dados de entrada e saída em JSON.

Exemplo 1: Um "Olá, Mundo" Simples (GreetingsHandler)

Nosso primeiro handler é o mais básico possível: ele não recebe dados de entrada e retorna uma mensagem de texto simples.

// Em: src/main/java/.../handler/GreetingsHandler.java
@ApplicationScoped
@Named("greetingsHandler")
public class GreetingsHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
        // Lógica para criar e retornar uma resposta HTTP 200 OK
        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
        response.setStatusCode(200);
        response.setHeaders(Collections.singletonMap("Content-Type", "text/plain; charset=utf-8"));
        response.setBody("Olá do Quarkus Lambda!");
        return response;
    }
}
Enter fullscreen mode Exit fullscreen mode

Vamos nos concentrar nos três pontos fundamentais que já discutimos:

  1. Gerenciamento com CDI (@ApplicationScoped): Integra o handler ao Quarkus, transformando-o em um bean gerenciável.
  2. A Identidade da Lambda (@Named("greetingsHandler")): Atribui um ID único que usaremos no template.yaml para conectar a infraestrutura a esta classe específica.
  3. O Contrato com a AWS (RequestHandler): Define a classe como um ponto de entrada de Lambda, especificando os tipos de evento de entrada e saída do API Gateway.

Exemplo 2: Uma Lambda com Lógica e JSON (CalculatorHandler)

Agora, vamos criar um exemplo mais prático. O CalculatorHandler receberá um JSON com dois números, fará uma soma e retornará o resultado em outro JSON.

Definindo as Estruturas de Dados (DTOs)

Primeiro, precisamos de classes para modelar os dados de entrada (CalculationRequest) e saída (CalculationResponse). Crie estes dois arquivos no seu pacote dto.

// Em: src/main/java/.../dto/CalculationRequest.java
package br.com.seudominio.samquarkusapp.dto;

import io.quarkus.runtime.annotations.RegisterForReflection;

@RegisterForReflection
public class CalculationRequest {
    private double number1;
    private double number2;

    // Getters e Setters
    public double getNumber1() { return number1; }
    public void setNumber1(double number1) { this.number1 = number1; }
    public double getNumber2() { return number2; }
    public void setNumber2(double number2) { this.number2 = number2; }
}
Enter fullscreen mode Exit fullscreen mode
// Em: src/main/java/.../dto/CalculationResponse.java
package br.com.seudominio.samquarkusapp.dto;

import io.quarkus.runtime.annotations.RegisterForReflection;

@RegisterForReflection
public class CalculationResponse {
    private double result;
    private String operation;

    public CalculationResponse(double result, String operation) {
        this.result = result;
        this.operation = operation;
    }

    // Getters e Setters
    public double getResult() { return result; }
    public void setResult(double result) { this.result = result; }
    public String getOperation() { return operation; }
    public void setOperation(String operation) { this.operation = operation; }
}
Enter fullscreen mode Exit fullscreen mode

Ponto de Atenção: @RegisterForReflection
Esta anotação é essencial para a compilação nativa com GraalVM. A biblioteca Jackson usa reflexão para criar instâncias dessas classes a partir de um JSON e para ler seus campos ao gerar um JSON. Na compilação nativa, o GraalVM elimina qualquer código que ele acha que não é usado. A anotação @RegisterForReflection avisa ao Quarkus para preservar as informações dessas classes (construtores, getters, setters), garantindo que o Jackson consiga usá-las em tempo de execução.

Implementando o Handler

Agora, crie a classe CalculatorHandler no pacote handler.

// Em: src/main/java/.../handler/CalculatorHandler.java
@ApplicationScoped
@Named("calculatorHandler")
public class CalculatorHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {

    // Para fins didáticos, mas a injeção de dependência é preferível.
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
        try {
            // 1. pega o corpo da requisição (que é uma string json)
            String body = input.getBody();

            // 2. desserializa a string JSON em um objeto Java
            CalculationRequest data = objectMapper.readValue(body, CalculationRequest.class);

            // 3. executa a lógica de negócio
            double sum = data.getNumber1() + data.getNumber2();

            context.getLogger().log(String.format("Calculando: %f + %f = %f",
                    data.getNumber1(), data.getNumber2(), sum));

            // 4. cria o objeto de resposta
            CalculationResponse responsePayload = new CalculationResponse(sum, "soma");

            // 5. serializa o objeto de resposta de volta para uma string JSON e retorna
            return new APIGatewayProxyResponseEvent()
                    .withStatusCode(200)
                    .withHeaders(Map.of("Content-Type", "application/json"))
                    .withBody(objectMapper.writeValueAsString(responsePayload));

        } catch (Exception e) {
            context.getLogger().log("Erro ao processar: " + e.getMessage());
            return new APIGatewayProxyResponseEvent()
                    .withStatusCode(400) // Bad Request
                    .withHeaders(Map.of("Content-Type", "application/json"))
                    .withBody("{\"message\":\"Corpo da requisição inválido.\"}");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Este handler segue o mesmo padrão, mas sua lógica interna é mais rica:

  1. Ele recebe o corpo da requisição, que esperamos ser um JSON como {"number1": 10, "number2": 20}.
  2. Usa o objectMapper.readValue para converter essa string em um objeto CalculationRequest.
  3. Executa a soma.
  4. Cria um objeto CalculationResponse.
  5. Usa o objectMapper.writeValueAsString para converter o objeto de resposta em uma string JSON antes de enviá-lo de volta com um status 200 OK.

Buildando nosso executável nativo

Com nosso handler Java pronto, o próximo passo é compilá-lo. No entanto, este não é um build comum que gera um .jar; nosso objetivo é criar um executável nativo para Linux, a chave para obtermos a performance excepcional que o Quarkus com GraalVM promete.

Lembre-se que, como definimos nos pré-requisitos, este processo exige um container runtime (como Docker ou Podman) ativo, pois usaremos a estratégia de build dentro de um contêiner para garantir total compatibilidade com o ambiente da AWS Lambda.

Temos duas maneiras principais de executar o build. Ambas chegam ao mesmo resultado.


Opção 1: Usando o Gradle Wrapper (Recomendado)

Esta é a forma mais direta, pois não exige a instalação de nenhuma ferramenta adicional, utilizando apenas o Gradle que já vem configurado no projeto.

Abra seu terminal na raiz do projeto e execute o comando:

./gradlew build -x test "-Dquarkus.native.enabled=true" "-Dquarkus.native.container-build=true" "-Dquarkus.package.jar.enabled=false"
Enter fullscreen mode Exit fullscreen mode

Vamos entender cada parte:

  • ./gradlew build: O comando padrão para iniciar o build com o Gradle.
  • -x test: Um comando do Gradle para pular a execução dos testes, agilizando o processo de build.
  • "-Dquarkus.native.enabled=true": A chave que liga o "modo nativo", instruindo o Quarkus a iniciar a compilação com GraalVM.
  • "-Dquarkus.native.container-build=true": Informa ao Quarkus para realizar o build dentro de um contêiner. Isso garante que o executável seja gerado em um ambiente Linux consistente e compatível com o da AWS.
  • "-Dquarkus.package.jar.enabled=false": Uma pequena otimização. Como nosso foco é 100% no executável nativo, dizemos ao Quarkus para não se preocupar em gerar os .jars tradicionais.

Opção 2: Usando a Quarkus CLI

Para quem prefere uma linha de comando mais limpa e tem a CLI do Quarkus instalada, o comando é um pouco mais enxuto:

quarkus build --native --no-tests "-Dquarkus.native.container-build=true"
Enter fullscreen mode Exit fullscreen mode

As flags --native e --no-tests são atalhos para as propriedades equivalentes que vimos no comando do Gradle.


O Resultado

Independentemente do comando escolhido, o processo será o mesmo. Você verá o terminal exibir bastante informação, incluindo o download da imagem do builder (na primeira vez) e os passos da compilação GraalVM. Este processo pode levar alguns minutos!

Output final do terminal após a execução do build, mostrando a mensagem 'BUILD SUCCESSFUL in 3m 32s', confirmando o sucesso da compilação.

Ao final, se tudo correu bem, você terá o nosso tão esperado artefato pronto para o deploy no seguinte caminho:

build/function.zip

Visualização da pasta 'build' em um editor de código, destacando o arquivo 'function.zip', que é o pacote de deploy para a AWS Lambda gerado pelo build nativo.

Este arquivo .zip contém nosso executável Linux (bootstrap) pronto para ser executado na AWS Lambda. É este o artefato que, na próxima seção, diremos ao AWS SAM para usar.

A Receita da Nossa Infraestrutura: O template.yaml

Com nosso código Java agora contendo dois handlers, precisamos atualizar nosso arquivo de manifesto, o template.yaml, para dizer à AWS como expor ambas as funções.

Pense neste arquivo como a planta da nossa aplicação serverless. É um documento que descreve, de forma declarativa, toda a infraestrutura que a AWS deve construir e gerenciar para nós. Agora, ele descreverá duas funções Lambda e seus respectivos endpoints de API.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: provided.al2023
    Handler: io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest
    Architectures: [ x86_64 ]
    MemorySize: 128
    Timeout: 15
    CodeUri: build/function.zip
    Environment:
      Variables:
        DISABLE_SIGNAL_HANDLERS: "true"

Resources:
  GreetingsFunction:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          QUARKUS_LAMBDA_HANDLER: greetingsHandler
      Events:
        GetGreetings:
          Type: Api
          Properties:
            Path: /greetings
            Method: get

  CalculatorFunction:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          QUARKUS_LAMBDA_HANDLER: calculatorHandler
      Events:
        PostCalculate:
          Type: Api
          Properties:
            Path: /calculator/sum
            Method: post

Outputs:
  ApiUrl:
    Description: "URL do endpoint do Api Gateway:"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/"
Enter fullscreen mode Exit fullscreen mode

Pode parecer complexo, mas é bastante lógico. Vamos analisar cada bloco.


Globals: Os Padrões da Construção

A seção Globals nos ajuda a não repetir código. As configurações definidas aqui valem como padrão para todas as funções do nosso projeto, o que é especialmente útil agora que temos duas.

  • Runtime: provided.al2023: Como nosso build com GraalVM gera um executável Linux autossuficiente, usamos provided para dizer à AWS: "nós estamos fornecendo nosso próprio executável". A imagem al2023 garante a presença de bibliotecas essenciais, como a glibc, que nosso executável nativo precisa.
  • Handler: io.quarkus.amazon.lambda.runtime.QuarkusStreamHandler::handleRequest: Este é o "roteador" genérico do Quarkus. A AWS sempre chamará este ponto de entrada, que por sua vez se encarregará de direcionar a requisição para o nosso bean @Named correto.
  • CodeUri: build/function.zip: Aponta para o arquivo .zip que contém nosso executável nativo. Note que ambas as funções usam o mesmo artefato de código.
  • Environment -> DISABLE_SIGNAL_HANDLERS: "true": Uma variável de ambiente crucial para a execução nativa, que resolve incompatibilidades entre o Quarkus e o ambiente Custom Runtime da AWS.

Resources: Desenhando a Estrutura Principal

Agora, definimos dois componentes na nossa infraestrutura.

A primeira função: GreetingsFunction
  • GreetingsFunction:: O nome lógico da nossa primeira função Lambda.
  • Type: AWS::Serverless::Function: Especifica que estamos criando uma função Lambda.
  • Properties: As configurações específicas deste "cômodo".
    • Environment -> Variables -> QUARKUS_LAMBDA_HANDLER: greetingsHandler: O valor greetingsHandler é o mesmo que usamos na anotação @Named("greetingsHandler"). É assim que o roteador do Quarkus sabe qual classe Java executar.
  • Events:: Define a "porta de entrada" da função.
    • Path: /greetings e Method: get: Mapeia a função para ser acionada por uma requisição GET no caminho /greetings.
A segunda função: CalculatorFunction

Observe como a definição da nossa segunda função segue exatamente o mesmo padrão. Uma vez que a estrutura está montada, adicionar novas funções se torna uma tarefa simples de "copiar, colar e ajustar".

  • CalculatorFunction:: O nome lógico da nossa nova função de cálculo.
  • Properties:
    • QUARKUS_LAMBDA_HANDLER: calculatorHandler: E aqui está a conexão para o nosso segundo handler. O valor calculatorHandler corresponde exatamente à anotação @Named("calculatorHandler") da nossa classe CalculatorHandler.java.
  • Events::
    • Path: /calculator/sum e Method: post: Mapeamos esta função para um caminho diferente (/calculator/sum) e um método HTTP diferente (post), ideal para enviar dados no corpo da requisição.

Outputs: Recebendo o Endereço Final

Esta seção não muda. Ela instrui o SAM a nos mostrar a URL base da nossa API, que agora servirá de ponto de entrada para os dois endpoints que criamos.

  • ApiUrl: Define uma saída de informação com a URL base da API.

Fazendo o deploy da nossa aplicação serverless

Com nosso executável nativo empacotado no function.zip e a planta da nossa infraestrutura definida no template.yaml, temos todas as peças do quebra-cabeça. Agora, vamos usar o AWS SAM CLI para montar tudo na nuvem.

Pré-requisitos para o Deploy

Antes de prosseguirmos, é crucial garantir que seu ambiente de linha de comando consegue se comunicar com sua conta da AWS. Verifique se você cumpriu os seguintes pontos, que mencionamos no início do artigo:

  1. AWS CLI configurada e autenticada: O SAM CLI usa as credenciais configuradas na AWS CLI. Você precisa estar autenticado em uma conta da AWS.

    • O caminho mais direto para este tutorial é configurar a CLI com uma Access Key e Secret Key de um usuário IAM.
    • Usuários mais avançados podem usar outros métodos, como o aws sso login, que foi o que utilizei para preparar este artigo, autenticando-me em uma conta filha gerenciada pelo AWS Organizations.
  2. AWS SAM CLI instalado: Essencial para interpretar nosso template e orquestrar o deploy.

Passo 1: Validando nosso template.yaml (sam validate)

Antes de pedir para o SAM construir nossa infraestrutura, é uma boa prática pedir para ele revisar nosso arquivo. O comando sam validate faz exatamente isso: ele lê seu template.yaml e verifica se há erros de sintaxe ou de lógica, sem custar nada e sem criar nenhum recurso.

Abra o terminal na raiz do projeto e execute:

sam validate
Enter fullscreen mode Exit fullscreen mode

Se tudo estiver correto, você receberá uma mensagem confirmando que o template.yaml é válido.

Terminal mostrando o comando 'sam validate' e sua saída de sucesso, com a mensagem de que o arquivo 'template.yaml' é um template SAM válido.

Passo 2: Preparando o Terreno (O Bucket S3)

O AWS SAM funciona em duas etapas: primeiro, ele faz o upload do nosso artefato (function.zip) para um "local de staging" na nuvem, que é um bucket S3. Depois, ele instrui o CloudFormation a criar a Lambda usando o artefato que está nesse bucket.

Portanto, precisamos criar esse bucket S3 antes de continuar.

Importante: Nomes de buckets S3 são globalmente únicos. Para garantir que o seu seja único, adicione um sufixo com números ou letras aleatórias.

aws s3 mb s3://[nome-do-seu-bucket] --region sa-east-1
Enter fullscreen mode Exit fullscreen mode

Se o nome estiver disponível, o comando retornará uma mensagem de sucesso, como make_bucket: s3://.... Anote o nome exato que você usou.

Terminal mostrando o comando 'aws s3 mb' criando o bucket 'teste-bucket-sam-app-123765' e a mensagem de sucesso 'make_bucket' como resultado.

Passo 3: Fazendo o deploy na AWS (sam deploy)

Agora sim, com tudo no lugar, vamos ao deploy. O comando sam deploy irá ler o template.yaml, empacotar nosso código, enviá-lo para o bucket que acabamos de criar e, finalmente, criar todos os recursos na AWS.

Use o comando abaixo, lembrando de substituir o nome do bucket pelo que você acabou de criar:

sam deploy --stack-name test-app --region sa-east-1 --s3-bucket [nome-do-seu-bucket] --capabilities CAPABILITY_IAM --confirm-changeset
Enter fullscreen mode Exit fullscreen mode

Vamos entender os parâmetros-chave:

  • --stack-name test-app: Dá um nome à nossa pilha de recursos no AWS CloudFormation. Pense nisso como o nome do nosso projeto na nuvem.
  • --region sa-east-1: Especifica a região da AWS onde os recursos serão criados.
  • --s3-bucket [nome-do-seu-bucket]: Aqui usamos o bucket S3 que criamos no passo anterior. É para onde o SAM enviará nosso function.zip.
  • --capabilities CAPABILITY_IAM: Como nosso template pode criar roles de permissão, precisamos explicitamente autorizar essa criação.
  • --confirm-changeset: Pede para o SAM nos mostrar um resumo das mudanças antes de aplicá-las.

Ao executar o comando, o SAM CLI irá te guiar com algumas perguntas:

  1. Ele mostrará as mudanças (um "changeset") e perguntará se você quer fazer o deploy. Digite y e pressione Enter.
  2. Ele avisará que a função não tem autenticação. Para nosso teste, isso está ok. Digite y e pressione Enter.

Terminal exibindo o preview do changeset do AWS SAM, com a lista de novos recursos como as duas Lambdas, Roles de IAM e o API Gateway, aguardando a confirmação 'y/N' do usuário.

Deploy Concluído com Sucesso!

Aguarde o processo terminar. O SAM mostrará o progresso da criação dos recursos. Se tudo deu certo, o final do output será a seção Outputs que definimos no nosso template:

---------------------------------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------------------------------
Key                 ApiUrl
Description         URL do endpoint do Api Gateway:
Value               https://<ID_DA_SUA_API>.execute-api.sa-east-1.amazonaws.com/
---------------------------------------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

Tela do console da AWS Lambda mostrando as duas funções, 'CalculatorFunction' e 'GreetingsFunction', criadas com sucesso pelo deploy do AWS SAM.

Com a URL base fornecida pelo SAM, nossa API está oficialmente no ar. Agora você pode testar os dois endpoints que criamos usando sua ferramenta de API preferida, como o Postman ou Insomnia.

Use a URL de saída para montar as requisições:

  • Faça uma requisição GET para o caminho /Prod/greetings para acionar a GreetingsFunction.
  • Faça uma requisição POST para o caminho /Prod/calculator/sum, enviando o JSON com os números no corpo da requisição, para acionar a CalculatorHandler.

Cada chamada irá invocar a função Lambda correspondente diretamente na AWS.

Tela de variáveis do Postman mostrando a criação da variável 'gateway-url-poc' com o valor da URL do API Gateway gerada pelo SAM

Teste bem-sucedido da rota /greetings no Postman retornando a mensagem

Requisição POST para o endpoint de cálculo, enviando um JSON com number1 e number2, e recebendo a resposta 200 OK com o resultado da soma.

Código Fonte no GitHub

O projeto completo desenvolvido neste artigo está disponível no GitHub. Para acessar o código exatamente como ele estava ao final desta Parte 1, utilize o link para a branch específica abaixo.

Acesse o repositório na branch parte1-criando-primeiras-lambdas

Agradecimentos e Fontes

A criação deste conteúdo foi inspirada e auxiliada por artigos e documentações fantásticas da comunidade. Finalizo esse artigo deixando aqui um agradecimento especial e a recomendação de leitura:

Top comments (0)