Definir o manipulador da função do 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 repositório do GitHub para este guia fornece aplicativos de exemplo fáceis de implantar que demonstram uma variedade de tipos de manipuladores. Para obter detalhes, consulte o final deste tópico.
Seções
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 registrocustomizado 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:
-
: formato completo. Por exemplo:package
.Class
::method
example.Handler::handleRequest
. -
: formato abreviado para classes que implantam uma interface de manipulador. Por exemplo:package
.Class
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
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>
. Mapas de string a string funcionam para eventos simples como o seguinte:
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 objetoString
. -
,Type
Map<String,
etc. – o evento é um objeto JSON. O runtime o desserializa em um objeto da interface ou tipo especificado.Type
> -
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 pelos serviços da AWS, use os tipos na biblioteca aws-lambda-java-events.
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
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 repositório do GitHub para este guia inclui aplicativos de exemplo 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 biblioteca aws-lambda-java-events (3.0.0 e versões mais recentes). 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:
-
Handler.java
: recebe Map<String,String>
como entrada. -
HandlerInteger.java
: recebe Integer
como entrada. -
HandlerList.java
: recebe List<Integer>
como entrada. -
HandlerStream.java
: recebe InputStream
eOutputStream
como entrada. -
HandlerString.java
: recebe uma String
como entrada. -
HandlerWeatherData.java
: recebe um tipo personalizado como entrada.
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.