J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM

introduction

Jusqu'à présent, j'ai créé AWS Lambda principalement en Python, et parfois en Node.js, mais pour un changement, j'ai étudié comment développer en Java, je vais donc le résumer.

Cette fois, j'ai créé le code source de la fonction Lambda écrit en Java avec Gradle et l'ai déployé avec AWS SAM. AWS Toolkit for Eclipse (https://docs.aws.amazon.com/ja_jp/toolkit-for-eclipse/v1/user-guide/welcome.html) est également fourni pour le développement dans Eclipse, Je développe généralement avec Vim et déploie avec CLI, donc je vais m'adapter à cela.

Environnement de vérification

Points clés pour développer Lambda avec Java

~~ Runtime est uniquement Java 8 ~~ Runtime est Java 8 et Java 11 (modifié le 19 novembre 2019)

~~ Comme vous pouvez le voir dans la documentation officielle ci-dessous, le seul runtime Java fourni est Java 8 ( JDK 8). Si vous utilisez une autre version, vous devrez attendre qu'elle soit prise en charge ou utiliser un runtime personnalisé. ~~

Java 11 a été ajouté le 19 novembre 2019 et le runtime peut être sélectionné parmi Java 8 (JDK 8) et Java 11 (JDK 11).

Création de fonctions Lambda avec Java-AWS Lambda

Déployer en tant que fichier zip ou jar

Empaquetez et déployez une application écrite en Java dans un fichier zip ou un fichier jar autonome.

La documentation officielle montre comment déployer sur un jar autonome en utilisant Maven et un fichier zip en utilisant Gradle. Cette fois, j'ai essayé la méthode d'empaquetage et de déploiement dans un fichier zip avec Gradle.

Java AWS Lambda Deployment Package-AWS Lambda

Il existe trois façons de recevoir et de renvoyer des demandes de fonction de gestionnaire

Il existe plusieurs méthodes pour recevoir la demande de la fonction de gestionnaire et renvoyer la réponse comme suit.

  1. Type simple Java
  2. Type POJO (Plain Old Java Object)
  3. Type de flux

La manière d'écrire la fonction de gestionnaire est différente pour chacun. En d'autres termes, il existe trois façons d'écrire des fonctions de gestionnaire.

Il semble qu'il soit utilisé correctement du point de vue du type de données envoyées, plutôt que de la manière de décider "Si vous utilisez ce déclencheur d'événement, ce type". Il ne semble pas y avoir de telle chose dans cette situation, il est donc nécessaire de considérer la méthode à utiliser lors du développement de fonctions Lambda en Java.

Cette fois, nous avons adopté le "type POJO".

Type de gestionnaire d'E / S (Java) --AWS Lambda

Ce que j'ai fait cette fois

J'ai créé une application Web simple qui utilise ʻAPI Gateway` comme déclencheur pour les fonctions Lambda. C'est une API simple qui envoie simplement une requête POST et renvoie "Hello".

Exemple de code

Le code que j'ai créé est ici. https://github.com/mmclsntr/awslambda-javagradle

Structure du projet

.
├── build/
│   ├── distributions/
│   │   └── awslambda-javagradle.zip   #Déployer le package généré par build
│   └── ...
├── build.gradle                    #Fichier de configuration de construction Gradle
├── src/main/java/awslambda/javagradle
│   ├── Greeting.java            #La partie centrale de l'application
│   ├── Handler.java             #Stocke les fonctions du gestionnaire Lambda
│   └── Response.java            #Formater la réponse Lambda
└── template.yml                    #Fichier de modèle CloudFormation
└── Autres fichiers Gradle

codage

Classe de gestionnaire

Handler.java


package awslambda.javagradle;

import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class Handler implements RequestHandler<Map<String, Object>, Response> {

	private static final Logger LOG = Logger.getLogger(Handler.class.getName());

	@Override
	public Response handleRequest(Map<String, Object> input, Context context) {
		LOG.info("received: " + input);
        LOG.setLevel(Level.INFO);

        Greeting greetingBody = new Greeting("Hello");

		return Response.builder()
				.setStatusCode(200)
				.setObjectBody(greetingBody)
				.build();
	}
}

Classe de réponse

Response.java


package awslambda.javagradle;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collections;
import java.util.Map;
import org.apache.log4j.Logger;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Response {

	private final int statusCode;
	private final String body;
	private final Map<String, String> headers;
	private final boolean isBase64Encoded;

	public Response(int statusCode, String body, Map<String, String> headers, boolean isBase64Encoded) {
		this.statusCode = statusCode;
		this.body = body;
		this.headers = headers;
		this.isBase64Encoded = isBase64Encoded;
	}
	...

}

Cours d'accueil

Créez une application super simple qui renvoie Hello comme exemple.

Greeting.java


package awslambda.javagradle;

public class Greeting {
    private String greetings;

    public Greeting(String greetings) {
        this.greetings = greetings;
    }
    public String getGreetings() {
        return greetings;
    }

    public void setGreetings(String greetings) {
        this.greetings = greetings;
    }
}

Modèle CloudFormation

template.yml


AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
    AWS Lambda Java with Gradle

Globals:
    Function:
        Timeout: 20

Resources:
  PostGreetingFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: build/distributions/awslambda-javagradle.zip
      Handler: awslambda.javagradle.Handler::handleRequest
      Runtime: java8
      Events:
        GetOrder:
          Type: Api
          Properties:
            Path: /
            Method: post

Outputs:
    ApiEndpoint:
      Description: "API Gateway endpoint URL for Prod stage"
      Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

    PostGreetingFunction:
      Description: "PostGreeting Lambda Function ARN"
      Value: !GetAtt PostGreetingFunction.Arn

Déployer

Créer un fichier de paramètres de construction

build.gradle


apply plugin: 'java'

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile (
        'com.amazonaws:aws-lambda-java-core:1.1.0',
        'com.amazonaws:aws-lambda-java-log4j:1.0.0',
        'com.amazonaws:aws-lambda-java-events:1.1.0',
        'com.fasterxml.jackson.core:jackson-core:2.8.5',
        'com.fasterxml.jackson.core:jackson-databind:2.8.5',
        'com.fasterxml.jackson.core:jackson-annotations:2.8.5'
    )
}

// Task for building the zip file for upload
task buildZip(type: Zip) {
    from compileJava
    from processResources
    into('lib') {
        from configurations.runtime
    }
}

build.dependsOn buildZip

Construire

Construisez avec la commande Gradle.

gradle build

Déployer avec AWS SAM

Créer un compartiment S3 de destination de déploiement

aws s3 mb s3://<Déployer le compartiment S3 de destination> --aws-profile=<Profil AWS>

paquet

Avec sam package, téléchargez le fichier exécutable dans le compartiment S3 créé ci-dessus et générez un fichier modèle pour le déploiement.

sam package \
--s3-bucket <Déployer le nom du compartiment S3 de destination> \
--s3-prefix <Nom du dossier S3 de destination du déploiement(Préfixe)※Tout> \
--output-template-file output.yml \
--profile <Profil AWS>

En sortie, un fichier ʻoutput.yml` est créé.

Déployer

Utilisez sam deploy pour déployer Lambda et API Gateway.

sam deploy \
--template-file output.yml \
--stack-name awslambda-javagradle-greeting \
--capabilities CAPABILITY_IAM \
--profile <Profil AWS>

Vérification

Maintenant que la fonction Lambda et la passerelle API ont été créées sur AWS, lançons une requête POST au point de terminaison.

demande


curl -X POST https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/

réponse


{"greetings":"Hello"}

Impressions

Je n'utilise généralement pas Java, donc ça m'a pris du temps, mais j'ai l'impression que c'était facile à faire. Bien sûr, la quantité de code est plus importante que l'écriture avec un langage de script tel que Python, mais il est intéressant de pouvoir faire un développement rigoureux sans serveur.

Cette fois seulement, je ne pouvais pas saisir pleinement les spécifications spécifiques pour l'écriture en Java, telles que plusieurs types d'écriture de fonctions de gestionnaire. Lorsque je l'utilise réellement, j'aimerais le concevoir en détail tout en tenant compte de cette zone.

De plus, selon la rumeur, le démarrage initial est lent (environ 5 secondes jusqu'à ce qu'il réponde). Référence: https://cero-t.hatenadiary.jp/entry/20160106/1452090214

Résumé

J'ai pu saisir les caractéristiques et le sens du codage du développement de fonctions Lambda à l'aide de Java. Si vous migrez depuis une servlet, je pense que cela nécessitera une rénovation assez importante, mais il semble que cela puisse être utilisé comme substitut.

Je suis un peu inquiet pour le support là-bas, si le runtime est Java 8 tel quel. .. J'ai utilisé API Gateway comme déclencheur, mais j'aimerais également essayer d'autres services.

référence

https://qiita.com/kamata1729/items/8d88ea10dd3bb61fa6cc https://qiita.com/riversun/items/7fcc06617b469aed8f27

Recommended Posts

J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM
Je veux créer une fonction avec kotlin et java!
J'ai écrit un programme de recherche d'itinéraire dans TDD et j'ai essayé de le refactoriser
J'ai écrit un programme de jugement des nombres premiers en Java
Je veux ForEach un tableau avec une expression Lambda en Java
J'ai écrit un programme de factorisation prime en Java
Ecrire une classe en Kotlin et l'appeler en Java
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé de créer une fonction / écran d'administrateur de site commercial avec Java et Spring
Attribuer des expressions lambda Java8 aux variables et les réutiliser
Je veux faire une liste avec kotlin et java!
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3
J'ai créé un PDF avec Java.
J'ai écrit le théorème de Gordobach en java
Un mémo quand j'ai essayé "Parler d'écrire une application Java dans Eclipse et de la publier dans Kubernetes dans un conteneur Liberty (Partie 1)"
Je ne peux pas créer une classe Java avec un nom spécifique dans IntelliJ
J'ai écrit une sorte de livre qui ressemble à Java
Représentez graphiquement les informations du capteur de Raspberry Pi en Java et vérifiez-les avec un navigateur Web
Diviser une chaîne avec ". (Dot)" en Java
Gérez d'énormes JSON avec Java Lambda
Ce que je n'aime pas lors de l'utilisation de l'interface d'une fonction avec des arguments par défaut dans Kotlin depuis Java
J'ai créé un programme de jugement des nombres premiers en Java
J'ai reçu les données du voyage (application agenda) en Java et j'ai essayé de les visualiser # 001
Lire une chaîne dans un fichier PDF avec Java
Créer un CSR avec des informations étendues en Java
Même en Java, je veux sortir true avec un == 1 && a == 2 && a == 3 (deuxième décoction Javassist)
Je voulais que (a == 1 && a == 2 && a == 3) vrai en Java
Comment compresser un fichier JAVA CSV et le gérer dans un tableau d'octets
Préparer un environnement de scraping avec Docker et Java
Faisons une application TODO avec Java 2 Je veux créer un modèle avec Spring Initializr et créer Hello world
Crypter / décrypter avec AES256 en PHP et Java
J'ai essayé de casser le bloc avec java (1)
Même en Java, je veux afficher true avec un == 1 && a == 2 && a == 3 (Black Magic)
[Java] Précautions lors du référencement dans une classe parent et de l'instanciation dans une classe enfant
J'ai créé une fonction pour enregistrer des images avec l'API dans Spring Framework. Partie 1 (édition API)
J'ai fait un jeu de problèmes de calcul simple en Java
Essayé l'API Toot et Streaming de Mastodon en Java
[Ruby] J'ai fait un robot avec de l'anémone et du nokogiri.
J'ai essayé de créer une compétence Clova en Java
Implémentez rapidement singleton avec enum en Java
Résolution du problème lorsque Azure Functions a cessé de fonctionner en Java
Je souhaite définir une fonction dans la console Rails
J'ai essayé OCR de traiter un fichier PDF avec Java
Ce que j'ai appris lors de la création d'un serveur en Java
Sortie true avec if (a == 1 && a == 2 && a == 3) en Java (identifiant invisible)
Comment convertir A en A et A en A en utilisant le produit logique et la somme en Java
J'ai écrit un test avec Spring Boot + JUnit 5 maintenant
[Java] Une technique pour écrire des constructeurs, des getters et des setters d'un seul coup avec IntelliJ IDEA.
Jusqu'à ce que vous construisiez un projet écrit scala avec Maven et que vous l'exécutiez avec la commande scala.
J'ai créé une fonction pour enregistrer des images avec l'API dans Spring Framework. Partie 2 (édition client)
J'ai essayé de créer un programme en Java qui résout le problème du voyageur de commerce avec un algorithme génétique
Stocker dans une carte Java 2D et tourner avec pour instruction
J'ai écrit un test CRUD avec SpringBoot + MyBatis + DBUnit (Partie 1)
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
Implémentez Thread en Java et essayez d'utiliser la classe anonyme Lambda
Mémorandum n ° 4 "Obtenez une chaîne de caractères et décorez-la" [Java]
J'ai essayé de moderniser une application Java EE avec OpenShift.