Manipulador de função do AWS Lambda em Java - AWS Lambda

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Manipulador de função do AWS Lambda em Java

O manipulador da função do Lambda é o método no código da função que processa eventos. Quando sua função é invocada, o Lambda executa o método do manipulador. A função é executada até que o manipulador retorne uma resposta, seja encerrado ou atinja o tempo limite.

O GitHub repositório deste guia fornece easy-to-deploy exemplos de aplicativos que demonstram uma variedade de tipos de manipuladores. Para obter detalhes, consulte o final deste tópico.

Exemplo de manipulador: runtimes do Java 17

No exemplo do Java 17 a seguir, uma classe chamada HandlerIntegerJava17 define um método do manipulador chamado handleRequest. O método do manipulador recebe as seguintes entradas:

  • Um IntegerRecord, que é um registro customizado do Java que representa os dados do evento. Neste exemplo, definimos IntegerRecord da seguinte forma:

    record IntegerRecord(int x, int y, String message) { }
  • Um objeto de contexto, que disponibiliza métodos e propriedades que fornecem informações sobre a invocação, a função e o ambiente de execução.

Suponha que desejemos escrever uma função que registre em log a message da entrada IntegerRecord e retorne a soma de x e y. Este é o código da função:

exemplo HandlerIntegerJava17.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; // Handler value: example.HandlerInteger public class HandlerIntegerJava17 implements RequestHandler<IntegerRecord, Integer>{ @Override /* * Takes in an InputRecord, which contains two integers and a String. * Logs the String, then returns the sum of the two Integers. */ public Integer handleRequest(IntegerRecord event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("String found: " + event.message()); return event.x() + event.y(); } } record IntegerRecord(int x, int y, String message) { }

Você especifica qual método deseja que o Lambda invoque ao definir o parâmetro do manipulador na configuração da função. É possível expressar o manipulador nos seguintes formatos:

  • package.Class::method: formato completo. Por exemplo: example.Handler::handleRequest.

  • package.Class: formato abreviado para classes que implantam uma interface de manipulador. Por exemplo: example.Handler.

Quando o Lambda invoca o manipulador, o runtime do Lambda recebe um evento como uma string formatada em JSON e o converte em um objeto. Para o exemplo anterior, uma amostra de evento poderá se assemelhar ao seguinte:

exemplo event.json
{ "x": 1, "y": 20, "message": "Hello World!" }

É possível salvar esse arquivo e testar a função localmente com o seguinte comando da AWS Command Line Interface (CLI):

aws lambda invoke --function-name function_name --payload file://event.json out.json

Exemplo de manipulador: runtimes do Java 11 e versões anteriores

O Lambda é compatível com registros para runtimes do Java 17 e versões posteriores. Em todos os runtimes do Java, é possível usar uma classe para representar os dados do evento. O exemplo a seguir usa uma lista de inteiros e um objeto de contexto como entrada e retorna a soma de todos os inteiros na lista.

exemplo Handler.java

No exemplo a seguir, uma classe chamada Handler define um método do manipulador chamado handleRequest. O método do manipulador usa um evento e um objeto de contexto como entrada e retorna uma string.

exemplo HandlerList.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.List; // Handler value: example.HandlerList public class HandlerList implements RequestHandler<List<Integer>, Integer>{ @Override /* * Takes a list of Integers and returns its sum. */ public Integer handleRequest(List<Integer> event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("EVENT TYPE: " + event.getClass().toString()); return event.stream().mapToInt(Integer::intValue).sum(); } }

Para obter mais exemplos, consulte Código de exemplo do manipulador.

Código de inicialização

O Lambda executa seu código estático e o construtor de classe durante a fase de inicialização antes de invocar a função pela primeira vez. Os recursos criados durante a inicialização permanecem na memória entre as invocações e podem ser reutilizados pelo manipulador milhares de vezes. Dessa forma, é possível adicionar código de inicialização de forma externa ao método do manipulador principal para economizar tempo de computação e reutilizar recursos em diversas invocações.

No exemplo a seguir, o código de inicialização do cliente é externo ao método do manipulador principal. O runtime inicializa o cliente antes que a função veicule o primeiro evento. Os eventos subsequentes são muito mais rápidos porque o Lambda não precisa inicializar o cliente novamente.

exemplo Handler.java
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestHandler; import java.util.Map; import software.amazon.awssdk.services.lambda.LambdaClient; import software.amazon.awssdk.services.lambda.model.GetAccountSettingsResponse; import software.amazon.awssdk.services.lambda.model.LambdaException; // Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String> { private static final LambdaClient lambdaClient = LambdaClient.builder().build(); @Override public String handleRequest(Map<String,String> event, Context context) { LambdaLogger logger = context.getLogger(); logger.log("Handler invoked"); GetAccountSettingsResponse response = null; try { response = lambdaClient.getAccountSettings(); } catch(LambdaException e) { logger.log(e.getMessage()); } return response != null ? "Total code size for your account is " + response.accountLimit().totalCodeSize() + " bytes" : "Error"; } }

Escolher tipos de entrada e saída

Especifique o tipo de objeto para o qual o evento é mapeado na assinatura do método do manipulador. No exemplo anterior, o runtime do Java desserializa o evento em um tipo que implementa a interface Map<String,String>. Os tring-to-string mapas S funcionam para eventos planos como os seguintes:

exemplo Event.json: dados climáticos
{ "temperatureK": 281, "windKmh": -3, "humidityPct": 0.55, "pressureHPa": 1020 }

No entanto, o valor de cada campo deve ser uma string ou um número. Se o evento incluir um campo que tenha um objeto como um valor, o runtime não poderá desserializá-lo e retornará um erro.

Escolha um tipo de entrada que funcione com os dados de evento que sua função processa. É possível usar um tipo básico, um tipo genérico ou um tipo bem definido.

Tipos de entrada
  • Integer, Long, Double etc. – o evento é um número sem formatação adicional, por exemplo, 3.5. O runtime converte o valor em um objeto do tipo especificado.

  • String: o evento é uma string JSON, incluindo aspas, por exemplo, "My string.". O runtime converte o valor (sem aspas) em um objeto String.

  • Type, Map<String,Type> etc. – o evento é um objeto JSON. O runtime o desserializa em um objeto da interface ou tipo especificado.

  • List<Integer>, List<String>, List<Object> etc. – o evento é uma matriz JSON. O runtime o desserializa em um objeto da interface ou tipo especificado.

  • InputStream: o evento é qualquer tipo JSON. O runtime transmite um fluxo de bytes do documento ao manipulador sem modificação. Desserialize a entrada e grave a saída em um fluxo de saída.

  • Tipo de biblioteca — Para eventos enviados por AWS serviços, use os tipos na aws-lambda-java-eventsbiblioteca.

Se você definir seu próprio tipo de entrada, ele deve ser um objeto Java simples e antigo (POJO) desserializável e mutável, com um construtor padrão e propriedades para cada campo no evento. Chaves no evento que não mapeiem para uma propriedade e propriedades que não estejam incluídas no evento são descartadas sem erro.

O tipo de saída pode ser um objeto ou void. O runtime serializa valores de retorno em texto. Se a saída for um objeto com campos, o runtime serializa-o em um documento JSON. Se for um tipo que envolve um valor primitivo, o runtime retornará uma representação de texto desse valor.

Interfaces do manipulador

A biblioteca aws-lambda-java-core define duas interfaces para métodos do manipulador. Use as interfaces fornecidas para simplificar a configuração do manipulador e validar a assinatura do método do manipulador no momento da compilação.

A interface RequestHandler é um tipo genérico que usa dois parâmetros: o tipo de entrada e o tipo de saída. Ambos os tipos devem ser objetos. Quando você usa essa interface, o runtime do Java desserializa o evento em um objeto com o tipo de entrada e serializa a saída em texto. Use essa interface quando a serialização interna funcionar com seus tipos de entrada e saída.

exemplo Handler.java: interface do manipulador
// Handler value: example.Handler public class Handler implements RequestHandler<Map<String,String>, String>{ @Override public String handleRequest(Map<String,String> event, Context context)

Para usar sua própria serialização, implemente a interface RequestStreamHandler. Com essa interface, o Lambda transmite ao seu manipulador uma transmissão de entrada e uma de saída. O manipulador lê bytes do fluxo de entrada, grava no fluxo de saída e retorna um void.

O exemplo a seguir usa tipos de leitor e gravador em buffer para trabalhar com os fluxos de entrada e saída.

exemplo HandlerStream.java
import com.amazonaws.services.lambda.runtime.Context import com.amazonaws.services.lambda.runtime.LambdaLogger import com.amazonaws.services.lambda.runtime.RequestStreamHandler ... // Handler value: example.HandlerStream public class HandlerStream implements RequestStreamHandler { @Override /* * Takes an InputStream and an OutputStream. Reads from the InputStream, * and copies all characters to the OutputStream. */ public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { LambdaLogger logger = context.getLogger(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("US-ASCII"))); PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, Charset.forName("US-ASCII")))); int nextChar; try { while ((nextChar = reader.read()) != -1) { outputStream.write(nextChar); } } catch (IOException e) { e.printStackTrace(); } finally { reader.close(); String finalString = writer.toString(); logger.log("Final string result: " + finalString); writer.close(); } } }

Código de exemplo do manipulador

O GitHub repositório deste guia inclui exemplos de aplicativos que demonstram o uso de vários tipos e interfaces de manipuladores. Cada aplicativo de exemplo inclui scripts para fácil implantação e limpeza, um modelo do AWS SAM e recursos de suporte.

Aplicações de exemplo do Lambda em Java
  • java17-examples: uma função em Java que demonstra como usar um registro Java para representar um objeto de dados de evento de entrada.

  • java-basic: uma coleção de funções Java mínimas com testes de unidade e configuração de registro em log variável.

  • java-events: uma coleção de funções do Java contendo código básico sobre como lidar com eventos de vários serviços, como o Amazon API Gateway, o Amazon SQS e o Amazon Kinesis. Essas funções usam a versão mais recente da aws-lambda-java-eventsbiblioteca (3.0.0 e mais recente). Estes exemplos não exigem oAWS SDK como dependência.

  • s3-java: uma função em Java que processa eventos de notificação do Amazon S3 e usa a Java Class Library (JCL) para criar miniaturas de arquivos de imagem enviados por upload.

  • Use API Gateway to invoke a Lambda function (Usar o API Gateway para invocar uma função do Lambda): uma função Java que verifica uma tabela do Amazon DynamoDB contendo informações de funcionários. Em seguida, usa o Amazon Simple Notification Service para enviar uma mensagem de texto aos funcionários comemorando seus aniversários de empresa. Este exemplo usa o API Gateway para invocar a função.

As aplicações s3-java e java-events usam um evento de serviço da AWS como entrada e retornam uma string. O aplicativo java-basic inclui vários tipos de manipuladores:

Para testar diferentes tipos de manipuladores, basta alterar o valor do manipulador no modelo do AWS SAM. Para obter instruções detalhadas, consulte o arquivo readme do aplicativo de exemplo.