aws-serveless-lamba-steps

Función Lambda con Java

Para poder mostrar el funcionamiento de los Lambda de AWS haciendo uso del servicio Step Function de AWS se ha implementado un pequeño programa desarrollado en Java. Este código de ejemplo utiliza la clase Hello, esta clase hace uso de la interfaz proporcionada por AWS, RequestHandler.

El método RequesHandler sobrescrito  toma como entrada un objeto JSON, el cual pasaremos como entrada al llamar la función, ya sea bien a través de la llamada de la función Lambda o a través de Steps de AWS.

Como tipos de entrada la interface RequestHandler permite que se le pasen como inputs los diferentes tipos de datos como: Integer, Long, Double, List<Integer>, Type, Map<String, Type>, etc

Los tipos de entrada se pueden encontrar en el siguiente enlace:

https://docs.aws.amazon.com/es_es/lambda/latest/dg/java-handler.html

En nuestro caso hemos utilizado como entrada el tipo Object, pero podríamos haber usado también el tipo String,  ya que lo que vamos a hacer simplemente es devolver la entrada a la salida para que dependiendo de el valor en el siguiente paso o Step realicemos una acción u otra.

Para facilitar la compresión del ejemplo, la clase implementada unicamente va a devolver la entrada en formato String, el motivo es que cuando añadamos la siguiente tarea en AWS Step Functions podamos utilzar la salida de la función como variable.

Como veremos más adelante el siguiente paso simplemente es un choice que elige entre dos funciones Lambda a ejecutar.

El siguiente código muestra la función lambda principal

package org.example;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class Hello implements RequestHandler<Object, String> {

    @Override
    public String handleRequest(Object input, Context context) {
        context.getLogger().log("Input: " + input);

        String output = "" + input + "";
        // TODO: implement your handler
        return output;
    }

}

Y a continuación una de las funciones lambda secundarias

package org.example;

public class Hello1Lambda {
    public String HandleRequest(){
        AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();

        return "Hello, AWS Lambda 1";
    }
}

 

Una vez comprobado el funcionamiento de las lambdas lo siguiente es crear el flujo de trabajo del sistema, podemos crear de una manera visual utilizando la herramienta que nos ofrece AWS de WorkFlow Studio como aparece en la siguiente figura.

 

 

Es importante, y se puede hacer de una manera visual, el configurar las variables de entrada y salida de cada paso, para ello pasamos el valor de la salida de la función $.Payload a la variable choice.$.

Como parametro de entrada le estamos pasando el string "1", la varible Payload por consiguiente toma este valor.

"Payload.$": "$"

También podríamos haber dejado como valor

"Payload.$": "$.data"

y en lugar de entrar la string "1", podríamos haberle pasdo un JSON con el campo dato que valiera 1

{

"data"="1"

}

Configurado el primer paso lo siguiente es recoger la variable en el choice y articular para que dependiendo de un valor u otro ejecute la primera o segunda lambda.

En la figura se muestra la manera visual, a traves de Workflow Studio de programar el proceso.

 

 

Una vez realizado ya podemos ejecutar la acción:

 

 

 

A continuación se expone el archivo obtenido del workflow

 

{
  "Comment": "A description of my state machine",
  "StartAt": "Lambda Invoke",
  "States": {
    "Lambda Invoke": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "Parameters": {
        "Payload.$": "$",
        "FunctionName": "arn:aws:lambda:us-east-1:056178724386:function:HeloLambdaIJ:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "Next": "Choice",
      "ResultSelector": {
        "choice.$": "$.Payload"
      }
    },
    "Choice": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.choice",
          "StringEquals": "1",
          "Next": "Lambda Invoke (1)"
        }
      ],
      "Default": "Lambda Invoke (2)"
    },
    "Lambda Invoke (1)": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "OutputPath": "$.Payload",
      "Parameters": {
        "FunctionName": "arn:aws:lambda:us-east-1:056178724386:function:LambdaFunction1:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "End": true
    },
    "Lambda Invoke (2)": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke",
      "OutputPath": "$.Payload",
      "Parameters": {
        "FunctionName": "arn:aws:lambda:us-east-1:056178724386:function:LambdaFunction2:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "IntervalSeconds": 2,
          "MaxAttempts": 6,
          "BackoffRate": 2
        }
      ],
      "End": true
    }
  }
}

 

 

 

 

 

 

Json que permite invocar a una función Lambda

{  
  "StartAt":"CallLambda",
  "States":{  
     "CallLambda":{  
        "Type":"Task",
        "Resource":"arn:aws:states:::lambda:invoke",
        "OutputPath": "$.Payload",
        "Parameters":{  
           "Payload.$": "$",
           "FunctionName":"HeloLambdaIJ"
        },
        "End":true
     }
  }
}

 

 

 

https://www.youtube.com/playlist?list=PL9nWRykSBSFgQrO66TmO1vHFP6yuPF5G-

 

JSON método que permite elegir entre dos funciones lambda dependiendo de la entrada:

{
  "TransactionType": "REFUND"
}
{
  "Comment": "A simple AWS Step Functions state machine that automates a call center support session.",
  "StartAt": "ProcessTransaction",
  "States": {
    "ProcessTransaction": {
        "Type" : "Choice",
        "Choices": [
          {
            "Variable": "$.TransactionType",
            "StringEquals": "PURCHASE",
            "Next": "ProcessPurchase"
          },
          {
            "Variable": "$.TransactionType",
            "StringEquals": "REFUND",
            "Next": "ProcessRefund"
          }
      ]
    },
     "ProcessRefund": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:056178724386:function:LambdaJavaFunction",
      "End": true
    },
    "ProcessPurchase": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:056178724386:function:LambdaJavaFunction",
      "End": true
    }
  }
}