O blog da AWS
Construindo aplicações Java Serverless com o AWS SAM CLI
Por Mehmet Nuri Deveci, Sr. Software Development Engineer; Steven Cook, Sr.Solutions Architect, e Maximilian Schellhorn, Solutions Architect.
Ao usar Java no ambiente Serverless, a Interface de Linha de Comando do AWS Serverless Application Model (AWS SAM CLI) oferece uma maneira mais fácil de construir e implantar funções AWS Lambda. Você pode usar o mecanismo de build padrão do AWS SAM ou adaptar o comportamento de build às necessidades da sua aplicação.
Como Java oferece uma variedade de plugins e ferramentas para construir sua aplicação, os desenvolvedores geralmente têm requisitos personalizados para sua configuração de build. Além disso, ao ter como alvo GraalVM ou versões não-LTS da JVM, o comportamento de build requer configuração adicional para construir um runtime personalizado do Lambda.
Esta publicação de blog fornece uma visão geral das maneiras comuns de construir aplicações Java para Lambda com o AWS SAM CLI. Isso permite que você tome decisões bem informadas com base nos requisitos dos seus projetos. Esta publicação se concentra no Apache Maven, no entanto, os mesmos conceitos se aplicam ao Gradle.
Você pode encontrar o código-fonte desses exemplos no repositório GitHub.
Visão geral
O diagrama a seguir fornece uma visão geral do processo de build e implantação com o AWS SAM CLI. O comportamento padrão inclui as seguintes etapas:
- Defina seus recursos de infraestrutura, como funções Lambda, Tabelas Amazon DynamoDB, buckets Amazon S3 ou um endpoint Amazon API Gateway em um arquivo template.yaml.
- O comando CLI “sam build” constrói a aplicação com base no runtime escolhido e na configuração dentro do template.
- O comando sam build popula a pasta .aws-sam/build com os artefatos construídos (por exemplo, arquivos de classe ou jars).
- O comando sam deploy faz upload do seu template e código de função da pasta .aws-sam/build e inicia uma implantação do AWS CloudFormation.
- Após uma implantação bem-sucedida, você pode encontrar os recursos provisionados em sua conta AWS.
Usando o mecanismo de build Java padrão no AWS SAM CLI
O AWS SAM CLI suporta a construção de funções Java Serverless com Maven ou Gradle. Você deve usar um dos runtimes Java suportados (java8, java8.al2, java11) e a propriedade CodeUri do recurso da sua função deve apontar para uma pasta de origem.
O AWS SAM CLI vem com mecanismos de build padrão fornecidos pelo projeto aws-lambda-builders. Portanto, não é necessário empacotar ou construir sua aplicação antecipadamente e quaisquer etapas de build personalizadas no pom.xml não serão usadas. Por exemplo, por padrão, o AWS SAM Maven Lambda Builder aciona as seguintes etapas:
- mvn clean install para construir a função.
- mvn dependency:copy-dependencies -DincludeScope=runtime -Dmdep.prependGroupId=true para preparar arquivos jar de dependências.
- Arquivos de classe em target/classes e arquivos jar de dependências em target/dependency são copiados para o local final do artefato de build em .aws-sam/build/{ResourceLogicalId}.
Inicie o processo de build executando o seguinte comando do diretório onde o template.yaml reside:
sam build
Isso resulta nas seguintes saídas:
A pasta de build .aws-sam contém as classes e bibliotecas necessárias para executar sua aplicação. O arquivo template.yaml transformado aponta para o diretório de artefatos de build (em vez de apontar para o diretório de origem original).
Execute o seguinte comando para implantar os recursos na AWS:
sam deploy --guided
Isso compacta o diretório HelloWorldFunction em .aws-sam/build e faz upload para o serviço Lambda.
Construindo Uber-Jars com o AWS SAM CLI
Uma maneira popular de construir e empacotar projetos Java, especialmente ao usar frameworks como Micronaut, Quarkus e Spring Boot, é criar um Uber-jar ou Fat-jar. Este é um arquivo jar que contém os arquivos de classe da aplicação com todos os arquivos de classe de dependências dentro de um único arquivo jar. Isso simplifica a implantação e o gerenciamento do artefato da aplicação.
Os frameworks normalmente fornecem uma configuração Maven ou Gradle que produz um Uber-jar por padrão. Por exemplo, usando o plugin Apache Maven Shade para Maven, você pode configurar o empacotamento Uber-jar:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
O maven-shade-plugin modifica a fase de package do build Maven para produzir o arquivo Uber-jar no diretório target.
Para construir e empacotar um Uber-jar com o AWS SAM, você deve personalizar o processo de build do AWS SAM CLI. Você pode fazer isso usando um Makefile para substituir as etapas padrão discutidas anteriormente. Dentro do template.yaml, declare um atributo de recurso Metadata com uma entrada BuildMethod. O processo sam build então procura por um Makefile dentro do diretório CodeUri.
O Makefile é responsável por construir os artefatos necessários pelo AWS SAM para implantar a função Lambda. O AWS SAM executa o target no Makefile. Este é um exemplo de Makefile:
build-HelloWorldFunctionUberJar:
mvn clean package
mkdir -p $(ARTIFACTS_DIR)/lib
cp ./target/HelloWorld*.jar $(ARTIFACTS_DIR)/lib/
O Makefile executa os objetivos clean e package do Maven que constroem o Uber-jar no diretório target através do Apache Maven Plugin. Como o runtime Java do Lambda carrega arquivos jar do diretório lib, você pode copiar o arquivo uber-jar para o diretório $ARTIFACTS_DIR/lib como parte das etapas de build.
Para construir a aplicação, execute:
sam build
Isso aciona a etapa de build personalizada e cria os seguintes recursos de saída:
A etapa de implantação é idêntica ao exemplo anterior.
Executando o processo de build dentro de um contêiner
O AWS SAM fornece um mecanismo para executar o processo de build da aplicação dentro de um contêiner Docker. Isso oferece o benefício de não exigir que suas dependências de build (como Maven e Java) estejam instaladas localmente ou em seu ambiente de CI/CD.
Para executar o processo de build dentro de um contêiner, use as opções de linha de comando –use-container e opcionalmente –build-image. O diagrama a seguir descreve o processo de build modificado com esta opção:
- Semelhante aos exemplos anteriores, o diretório com as fontes da aplicação ou o Makefile é referenciado.
- Para executar o processo de build dentro de um contêiner Docker, forneça a opção de linha de comando:
sam build –-use-container - Por padrão, o AWS SAM usa imagens para builds de contêiner que são mantidas no repositório GitHub aws/aws-sam-build-images. O AWS SAM puxa a imagem do contêiner dependendo do runtime definido. Para este exemplo, ele puxa a imagem public.ecr.aws/sam/build-java11, que tem pré-requisitos como Maven e Java11 pré-instalados para construir a aplicação. Além disso, a pasta de código-fonte é montada no contêiner e o target do Makefile ou mecanismo de build padrão é executado dentro do contêiner.
- Os artefatos finais são entregues ao diretório .aws-sam/build no sistema de arquivos local. Se você estiver usando um Makefile, pode copiar o artefato final para o $ARTIFACTS_DIR.
- O comando sam deploy faz upload do template e código de função do diretório .aws-sam/build e inicia uma implantação do CloudFormation.
- Após uma implantação bem-sucedida, você pode encontrar os recursos provisionados em sua conta AWS.
Para testar o comportamento, execute os exemplos anteriores com a opção –use-container. Nenhuma alteração adicional é necessária.
Usando suas próprias imagens base de build para criar runtimes personalizados
Quando você está tendo como alvo um runtime Lambda não suportado, como uma versão Java não-LTS ou imagens nativas compiladas nativamente com GraalVM, você pode criar sua própria imagem de build com as dependências necessárias instaladas.
Por exemplo, para construir uma imagem nativa com GraalVM, você deve ter o GraalVM e a ferramenta de imagem nativa instalados ao construir sua aplicação.
Para criar uma imagem personalizada:
- Crie um Dockerfile com as dependências necessárias:
#Use the official AWS SAM base image or Amazon Linux 2 as a starting point FROM public.ecr.aws/sam/build-java11:latest-x86_64 #Install GraalVM dependencies ENV GRAAL_VERSION 22.2.0 ENV GRAAL_FOLDERNAME graalvm-ce-java11-${GRAAL_VERSION} ENV GRAAL_FILENAME graalvm-ce-java11-linux-amd64-${GRAAL_VERSION}.tar.gz RUN curl -4 -L https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.2.0/graalvm-ce-java11-linux-amd64-22.2.0.tar.gz | tar -xvz RUN mv $GRAAL_FOLDERNAME /usr/lib/graalvm RUN rm -rf $GRAAL_FOLDERNAME #Install Native Image dependencies RUN /usr/lib/graalvm/bin/gu install native-image RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn #Set GraalVM as default ENV JAVA_HOME /usr/lib/graalvm - Construa sua imagem localmente ou faça upload para um registro de contêiner:
docker build . -t sam/custom-graal-image - Use o AWS SAM build com o argumento de imagem de build para fornecer sua imagem personalizada:
sam build --use-container --build-image sam/custom-graal-image
Você pode encontrar o código-fonte e um exemplo de Dockerfile, Makefile e pom.xml para imagens nativas GraalVM no repositório GitHub.
Quando você usa as imagens de build oficiais do AWS SAM como imagem base, você tem todas as ferramentas necessárias, como Maven, Java11 e os construtores Lambda instalados. Se você quiser usar uma abordagem mais personalizada e usar uma imagem base diferente, deve instalar essas dependências.
Para um exemplo, confira o template cookiecutter GraalVM com Java 17. Além disso, existem vários componentes adicionais envolvidos ao construir runtimes personalizados, que são descritos em “Construa um runtime Java personalizado para AWS Lambda”.
Para evitar fornecer as opções de linha de comando em cada build, inclua-as no arquivo samconfig.toml:
[default.build.parameters]
use_container = true
build_image = ["public.ecr.aws/sam/build-java11:latest-x86_64"]
Para informações adicionais, consulte a documentação oficial do AWS SAM CLI.
Implantando a aplicação sem construir com o AWS SAM
Pode haver cenários em que você não deseja depender do processo de build oferecido pelo AWS SAM. Por exemplo, quando você tem processos de build altamente personalizados ou estabelecidos, ou requisitos avançados de cache de dependências ou visibilidade.
Neste caso, você ainda pode usar os comandos do AWS SAM CLI, como sam local e sam deploy. Mas você deve apontar sua propriedade CodeUri diretamente para o artefato pré-construído (em vez do diretório de código-fonte):
HelloWorldFunctionSkipBuild:
Type: AWS::Serverless::Function
Properties:
CodeUri: HelloWorldFunction/target/HelloWorld-1.0.jar
Handler: helloworld.App::handleRequest
Neste caso, não há necessidade de usar o comando sam build, pois a lógica de build está fora do AWS SAM CLI:
Aqui, o comando sam build falha porque procura uma pasta de origem para construir a aplicação. No entanto, pode haver casos em que você tenha uma configuração mista que inclui algumas funções que apontam para artefatos pré-construídos e outras que são construídas pelo AWS SAM CLI. Neste cenário, você pode marcar essas funções para pular explicitamente o processo de build adicionando a seguinte flag SkipBuild na seção Metadata da definição do seu recurso:
HelloWorldFunctionSkipBuild:
Type: AWS::Serverless::Function
Properties:
CodeUri: HelloWorldFunction/target/HelloWorld-1.0.jar
Handler: helloworld.App::handleRequest
Runtime: java11
Metadata:
SkipBuild: True
Conclusão
Esta publicação de blog mostra como construir aplicações Java com o AWS SAM CLI. Você aprendeu sobre os mecanismos de build padrão e como personalizar o comportamento de build e abstrair o processo de build dentro de um ambiente de contêiner. Visite o repositório GitHub para os templates de código de exemplo referenciados nos exemplos.
Para saber mais, aprofunde-se na documentação do AWS SAM. Para mais recursos de aprendizado Serverless, visite Serverless Land.
Este conteúdo foi traduzido do post original do blog, que pode ser encontrado aqui.
Tradutores
![]() |
Nicolas Tarzia é Senior Technical Account Manager na AWS, com mais de 13 anos de experiência, com ampla experiência em arquitetura cloud, engenharia e design de software. Sua área de interesse são tecnologias serverless.
https://www.linkedin.com/in/nicolastarzia |
![]() |
Daniel Abib é Arquiteto de Soluções Sênior e Especialista em Amazon Bedrock na AWS, com mais de 25 anos trabalhando com gerenciamento de projetos, arquiteturas de soluções escaláveis, desenvolvimento de sistemas e CI/CD, microsserviços, arquitetura Serverless & Containers e especialização em Machine Learning. Ele trabalha apoiando Startups, ajudando-os em sua jornada para a nuvem.
https://www.linkedin.com/in/danielabib/ |








