Linguaggi JVM

È possibile scrivere la funzione utilizzando linguaggi JVM diversi (come Kotlin, Groovy o Scala) purché siano conformi alle seguenti regole:

  • La funzione è una classe pubblica che implementa una delle interfacce di funzione (HttpFunction, BackgroundFunction o RawBackgroundFunction) e ha un dominio pubblico costruttore senza argomento.

  • Se esegui il deployment dall'origine:

    • Può essere creato da Maven.
    • Il file di build contiene tutti i plug-in per la generazione delle classi compilate.
  • Se esegui il deployment da un JAR predefinito:

    • Per produrre questo JAR, puoi utilizzare qualsiasi strumento di creazione.
    • Il JAR predefinito deve essere un JAR Fat con tutte le sue classi di dipendenze oppure il suo manifest deve contenere Class-Path voce con le posizioni relative dei jar contenenti quelle dipendenze .

Esempi di funzioni HTTP

Puoi utilizzare le funzioni HTTP per richiamare della funzione tramite una richiesta HTTP(S). Gli esempi seguenti mostrano il messaggio "Hello World!"

Kotlin

import com.google.cloud.functions.HttpFunction
import com.google.cloud.functions.HttpRequest
import com.google.cloud.functions.HttpResponse
import java.io.IOException
import java.util.logging.Logger

class HelloWorld : HttpFunction {
    // Simple function to return "Hello World"
    @Throws(IOException::class)
    override fun service(request: HttpRequest, response: HttpResponse) {
        response.writer.write("Hello World!")
    }
}

Alla moda

import com.google.cloud.functions.HttpFunction
import com.google.cloud.functions.HttpRequest
import com.google.cloud.functions.HttpResponse

class GroovyHelloWorld implements HttpFunction {
    @Override
    void service(HttpRequest request, HttpResponse response) {
        response.writer.write("Hello World!")
    }
}

Scala

class ScalaHelloWorld extends HttpFunction {
  override def service(httpRequest: HttpRequest, httpResponse: HttpResponse): Unit = {
    httpResponse.getWriter.write("Hello World!")
  }
}

File pom.xml per esempi HTTP

Ecco i file pom.xml per gli esempi precedenti:

Kotlin

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-kotlin-hello-world</artifactId>


  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <kotlin.version>1.9.22</kotlin.version>
  </properties>

  <dependencies>
    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib-jdk8</artifactId>
      <version>${kotlin.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-test</artifactId>
      <version>${kotlin.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.HelloWorld</functionTarget>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-maven-plugin</artifactId>
        <version>${kotlin.version}</version>
        <executions>
          <execution>
            <id>compile</id>
            <phase>compile</phase>
            <goals>
              <goal>compile</goal>
            </goals>
            <configuration>
              <sourceDirs>
                <source>src/main/kotlin</source>
              </sourceDirs>
            </configuration>
          </execution>
          <execution>
            <id>test-compile</id>
            <phase>test-compile</phase>
            <goals>
              <goal>test-compile</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <jvmTarget>1.8</jvmTarget>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Alla moda

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-groovy-hello-world</artifactId>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <groovy.version>3.0.20</groovy.version>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <artifactId>libraries-bom</artifactId>
        <groupId>com.google.cloud</groupId>
        <scope>import</scope>
        <type>pom</type>
        <version>26.32.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>

    <!-- Required for groovy samples -->
    <dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>${groovy.version}</version>
      <type>pom</type>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.GroovyHelloWorld</functionTarget>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>3.0.2</version>
        <executions>
          <execution>
            <id>groovy-compile</id>
            <phase>process-resources</phase>
            <goals>
              <goal>addSources</goal>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <!-- any version of Groovy \>= 1.5.0 should work here -->
            <version>${groovy.version}</version>
            <scope>runtime</scope>
            <type>pom</type>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</project>

Scala

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example.functions</groupId>
  <artifactId>functions-scala-hello-world</artifactId>

  <properties>
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <artifactId>libraries-bom</artifactId>
        <groupId>com.google.cloud</groupId>
        <scope>import</scope>
        <type>pom</type>
        <version>26.32.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <!-- Required for scala samples -->
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-library</artifactId>
      <version>2.13.5</version>
    </dependency>

    <!-- Required for Function primitives -->
    <dependency>
      <groupId>com.google.cloud.functions</groupId>
      <artifactId>functions-framework-api</artifactId>
      <version>1.1.0</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <!--
          Google Cloud Functions Framework Maven plugin

          This plugin allows you to run Cloud Functions Java code
          locally. Use the following terminal command to run a
          given function locally:

          mvn function:run -Drun.functionTarget=your.package.yourFunction
        -->
        <groupId>com.google.cloud.functions</groupId>
        <artifactId>function-maven-plugin</artifactId>
        <version>0.11.0</version>
        <configuration>
          <functionTarget>functions.ScalaHelloWorld</functionTarget>
        </configuration>
      </plugin>
      <plugin>
        <groupId>net.alchim31.maven</groupId>
        <artifactId>scala-maven-plugin</artifactId>
        <version>4.4.1</version>
        <executions>
          <execution>
            <id>scala-compile</id>
            <phase>process-resources</phase>
            <goals>
              <goal>add-source</goal>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Deployment delle funzioni HTTP

Kotlin

gcloud functions deploy kotlin-helloworld --entry-point functions.KotlinHelloWorld --runtime java17 --trigger-http --allow-unauthenticated --memory 512MB

Alla moda

gcloud functions deploy groovy-helloworld --entry-point functions.GroovyHelloWorld --runtime java17 --trigger-http --allow-unauthenticated --memory 512MB

Scala

gcloud functions deploy scala-helloworld --entry-point functions.ScalaHelloWorld --runtime java17 --trigger-http --allow-unauthenticated --memory 512MB

Esempi di funzioni basate su eventi

Puoi usare le funzioni basate su eventi per richiamare la tua Cloud Function indirettamente in risposta a un evento asincrono, come un messaggio su una un argomento Pub/Sub, una modifica in un bucket Cloud Storage o un evento Firebase.

Esistono due tipi di funzioni basate su eventi: in background e CloudEvent. Le lingue JVM supportano solo funzioni in background.

Kotlin

import com.google.cloud.functions.BackgroundFunction
import com.google.cloud.functions.Context
import functions.eventpojos.PubsubMessage
import java.nio.charset.StandardCharsets
import java.util.Base64
import java.util.logging.Logger


class KotlinHelloPubSub : BackgroundFunction<PubsubMessage> {
    override fun accept(message: PubsubMessage, context: Context) {
        // name's default value is "world"
        var name = "world"
        if (message?.data != null) {
            name = String(
                    Base64.getDecoder().decode(message.data!!.toByteArray(StandardCharsets.UTF_8)),
                    StandardCharsets.UTF_8)
        }
        LOGGER.info(String.format("Hello %s!", name))
        return;
    }

    companion object {
        private val LOGGER = Logger.getLogger(KotlinHelloPubSub::class.java.name)
    }
}

Durante lo sviluppo delle funzioni in background, definisci le classi per gli eventi attivare le tue funzioni. Tuttavia, il marshalling di GSON potrebbe non funzionare riquadro per Kotlin, se la classe dell'evento non segue alcune linee guida.

Nella classe di evento Kotlin, le proprietà devono essere conformi alle seguenti linee guida:

  • Possono essere impostate su null.
  • Non gli è stato assegnato un valore predefinito.
  • Non sono proprietà delegati.

Un altro approccio consiste nel creare le classi di eventi in Java e utilizzarle la classe della funzione Kotlin.

Alla moda

import com.google.cloud.functions.BackgroundFunction
import com.google.cloud.functions.Context
import functions.eventpojos.PubsubMessage
import java.nio.charset.StandardCharsets
import java.util.logging.Logger

class GroovyHelloPubSub implements BackgroundFunction<PubsubMessage> {
    private static final Logger LOGGER = Logger.getLogger(GroovyHelloPubSub.class.name)

    @Override
    void accept(PubsubMessage message, Context context) {
        // name's default value is "world"
        String name = "world"

        if (message?.data) {
             name = new String(Base64.decoder.decode(message.data), StandardCharsets.UTF_8)
        }

        LOGGER.info("Hello ${name}!")
        return
    }
}

Scala

import java.nio.charset.StandardCharsets
import java.util.Base64
import java.util.logging.Logger

import com.google.cloud.functions.{BackgroundFunction, Context}
import functions.eventpojos.PubsubMessage

class ScalaHelloPubSub extends BackgroundFunction[PubsubMessage] {

  val LOGGER = Logger.getLogger(this.getClass.getName)

  override def accept(message: PubsubMessage, context: Context): Unit = {
    // name's default value is "world"
    var name = "world"
    if (message != null && message.getData != null) {
      name = new String(Base64.getDecoder.decode(
        message.getData.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8)
    }
    LOGGER.info(String.format("Hello %s!", name))
  }
}

Deployment delle funzioni in background

Kotlin

gcloud functions deploy kotlin-hello-pubsub --entry-point functions.KotlinHelloPubSub --runtime java17 --trigger-topic my-topic --allow-unauthenticated --memory 512MB

Alla moda

gcloud functions deploy groovy-hello-pubsub --entry-point functions.GroovyHelloPubSub --runtime java17 --trigger-topic my-topic --allow-unauthenticated --memory 512MB

Scala

gcloud functions deploy scala-hello-pubsub --entry-point functions.ScalaHelloPubSub --runtime java17 --trigger-topic my-topic --allow-unauthenticated --memory 512MB

Testa gli esempi di sfondo

Puoi testare gli esempi in background nel seguente modo:

  1. Pubblica un messaggio nell'argomento Pub/Sub per attivare la funzione:

    gcloud pubsub topics publish my-topic --message Flurry
  2. Esamina i log:

    gcloud functions logs read --limit 10

Dovresti vedere una schermata simile a questa, con un messaggio che include il nome pubblicate nell'argomento Pub/Sub:

D      my-function  ...  Function execution started
I      my-function  ...  Hello Flurry!
D      my-function  ...  Function execution took 39 ms, finished with status: 'ok'