Options de déploiement Java

Deux possibilités s'offrent à vous pour déployer une fonction Java 11 :

Déployer une fonction à partir d'une source

Le code source de votre fonction doit se trouver à l'emplacement habituel des projets Maven (src/main/java). Les exemples de fonctions décrits dans ce document se trouvent directement dans src/main/java, sans déclaration de package dans le fichier source .java. Il convient d'utiliser un package si le code est complexe. Si ce package est com.example, votre hiérarchie se présente comme suit :

myfunction/
├─ pom.xml
├─ src
    ├─main
        ├─ java
            ├─ com
                ├─ example
                    ├─ MyFunction.java

Exécutez la commande suivante pour déployer une fonction HTTP :

gcloud functions deploy $name --trigger-http \
    --entry-point $function_class --runtime java11

Où :

  • $name est un nom descriptif arbitraire correspondant au nom de la fonction déployée. L'argument $name ne peut contenir que des lettres, des chiffres, des traits de soulignement et des tirets.
  • $function_class est le nom complet de votre classe (par exemple, com.example.MyFunction ou simplement MyFunction si vous n'utilisez pas de package).

Exécutez la commande suivante pour déployer une fonction d'arrière-plan :

gcloud functions deploy $name --entry-point $function_class \
    --trigger-resource $resource_name \
    --trigger-event $event_name \
    --runtime java11

Où :

  • $name est un nom descriptif arbitraire correspondant au nom de la fonction déployée.
  • $function_class est le nom complet de votre classe (par exemple, com.example.MyFunction ou simplement MyFunction si vous n'utilisez pas de package).
  • $resource_name et $event_name sont spécifiques aux événements qui déclenchent votre fonction d'arrière-plan. Google Cloud Pub/Sub et Google Cloud Storage sont des exemples de ressources et d'événements acceptés.

Lorsque vous déployez une fonction à partir d'une source, l'outil de ligne de commande gcloud importe le répertoire source (et tous les éléments qu'il contient) dans Google Cloud pour la compilation. Pour éviter d'envoyer des fichiers inutiles, vous pouvez utiliser le fichier .gcloudignore. Modifiez le fichier .gcloudignore pour ignorer les répertoires courants, tels que .git et target/. Par exemple, un fichier .gcloudignore peut contenir les éléments suivants :

.git
target
build
.idea

Déployer une fonction à partir d'un fichier JAR

Vous pouvez déployer un fichier JAR prédéfini qui contient la fonction. Cela est particulièrement utile si vous devez déployer une fonction qui utilise les dépendances d'un dépôt d'artefacts privé non accessible à partir du pipeline de compilation de Google Cloud lors de la compilation à partir de la source. Le fichier JAR peut être un fichier Uber JAR contenant la classe de la fonction et toutes les classes de ses dépendances, ou un fichier JAR fin contenant des entrées Class-Path pour les fichiers JAR des dépendances dans le fichier META-INF/MANIFEST.MF.

Créer et déployer un fichier Uber JAR

Un fichier Uber JAR est un fichier JAR qui contient les classes de la fonction ainsi que toutes ses dépendances. Vous pouvez créer un fichier Uber JAR avec Maven et Gradle. Pour déployer un fichier Uber JAR, il doit s'agir du seul fichier JAR dans son propre répertoire. Exemple :

my-function-deployment/
 ├─ my-function-with-all-dependencies.jar

Vous pouvez copier le fichier dans cette structure de répertoires, ou générer le répertoire de déploiement approprié à l'aide des plug-ins Maven et Gradle.

Maven

Le plug-in Maven Shade permet de créer un fichier Uber JAR. Configurez votre fichier pom.xml avec le plug-in Shade :

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals><goal>shade</goal></goals>
            <configuration>
              <outputFile>${project.build.directory}/deployment/${build.finalName}.jar</outputFile>
              <transformers>
                <!-- This may be needed if you need to shade a signed JAR -->
                <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                  <resource>.SF</resource>
                  <resource>.DSA</resource>
                  <resource>.RSA</resource>
                </transformer>
                <!-- This is needed if you have dependencies that use Service Loader. Most Google Cloud client libraries does. -->
                <transformer implementation=
       "org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Créez le fichier Uber JAR :

mvn package

Déployez ensuite la fonction à l'aide de la commande suivante :

gcloud functions deploy jar-example \
    --entry-point=Example \
    --runtime=java11 \
    --trigger-http \
    --source=target/deployment

Gradle

Utilisez le plug-in Shadow pour Gradle. Configurez le plug-in dans votre fichier build.gradle :

buildscript {
   repositories {
       jcenter()
   }
   dependencies {
       ...
       classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0"
   }
}

plugins {
   id 'java'
   ...
}
sourceCompatibility = '11.0'
targetCompatibility = '11.0'
apply plugin: 'com.github.johnrengelman.shadow'

shadowJar {
   mergeServiceFiles()
}
...

Vous pouvez maintenant exécuter Gradle avec la commande shadowJar :

gradle shadowJar

Déployez ensuite la fonction à l'aide de la commande suivante :

gcloud functions deploy jar-example \
   --entry-point=Example \
   --runtime=java11 \
   --trigger-http \
   --source=build/libs

Créer et déployer un fichier JAR fin avec des dépendances externes

Vous pouvez créer et déployer un fichier JAR fin au lieu d'un fichier Uber JAR. Un fichier JAR fin est un fichier JAR qui ne contient que les classes de la fonction sans inclure les dépendances. Étant donné que les dépendances sont toujours nécessaires au déploiement, vous devez configurer les éléments comme suit :

  • Les dépendances doivent se trouver dans un sous-répertoire associé au fichier JAR à déployer.
  • Le fichier JAR doit comporter un fichier META-INF/MANIFEST.MF incluant un attribut Class-Path dont la valeur répertorie les chemins d'accès aux dépendances requises.

Par exemple, votre fichier JAR my-function.jar contient un fichier META-INF/MANIFEST.MF qui comporte deux dépendances dans le répertoire libs/ (liste de chemins relatifs séparés par des espaces) :

Manifest-Version: 1.0
Class-Path: libs/dep1.jar libs/dep2.jar

Votre répertoire de déploiement doit alors contenir le fichier JAR de votre fonction principale, ainsi qu'un sous-répertoire contenant les deux dépendances de votre fonction :

function-deployment/
├─ my-function.jar
├─ libs
       ├─ dep1.jar
       ├─ dep2.jar

Vous pouvez créer un fichier JAR fin à l'aide de Maven et de Gradle :

Maven

Utilisez le plug-in Maven JAR pour configurer automatiquement MANIFEST.MF avec les chemins d'accès aux dépendances. Utilisez ensuite le plug-in Maven Dependency pour copier les dépendances.

<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
              <classpathPrefix>libs/</classpathPrefix>
            </manifest>
          </archive>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <overWriteReleases>false</overWriteReleases>
              <includeScope>runtime</includeScope>
              <outputDirectory>${project.build.directory}/libs</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>package</phase>
            <goals><goal>copy-resources</goal></goals>
            <configuration>
              <outputDirectory>${project.build.directory}/deployment</outputDirectory>
              <resources>
                <resource>
                  <directory>${project.build.directory}</directory>
                  <includes>
                    <include>${build.finalName}.jar</include>
                    <include>libs/**</include>
                  </includes>
                  <filtering>false</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Créez le fichier JAR fin :

mvn package

Déployez ensuite la fonction à l'aide de la commande suivante :

gcloud functions deploy jar-example \
    --entry-point=Example \
    --runtime=java11 \
    --trigger-http \
    --source=target/deployment

Gradle

Mettez à jour le fichier de projet build.gradle pour ajouter une tâche permettant de récupérer les dépendances :

dependencies {
   // API available at compilation only, but provided at runtime
   compileOnly 'com.google.cloud.functions:functions-framework-api:1.0.1'
   // dependencies needed by the function
   // ...
}

jar {
 manifest {
   attributes(
     "Class-Path": provider {
         configurations.runtimeClasspath
           .collect { "libs/${it.name}" }.join(' ')
     }
   )
 }
}

task prepareDeployment(type: Copy) {
 into("${buildDir}/deployment")
 into('.') {
   from jar
 }
 into('libs') {
   from configurations.runtimeClasspath
 }
}