Opções de implementação do Java
Tem duas opções para implementar uma função Java:
- Fonte. Para uma discussão geral sobre este tópico, consulte o artigo Implemente uma função do Cloud.
- A partir de um ficheiro JAR pré-criado.
Implemente a partir da origem
O código-fonte da sua função tem de estar no local habitual para projetos Maven
(src/main/java). As funções de exemplo neste documento estão diretamente em
src/main/java, sem declaração de pacote no ficheiro de origem .java. Para código não trivial, é provável que introduza um pacote. Se esse pacote for
com.example, a hierarquia teria o seguinte aspeto:
myfunction/
├─ pom.xml
├─ src
├─main
├─ java
├─ com
├─ example
├─ MyFunction.java
Use o seguinte comando para implementar uma função HTTP:
gcloud functions deploy $name --trigger-http --no-gen2 \
--entry-point $function_class --runtime java17
Onde:
$nameé um nome descritivo arbitrário que será o nome da função após a implementação.$namesó pode conter letras, números, sublinhados e hífenes.$function_classé o nome totalmente qualificado da sua classe (por exemplo,com.example.MyFunctionou apenasMyFunctionse não usar um pacote).
Use o seguinte comando para implementar uma função orientada por eventos:
gcloud functions deploy $name --no-gen2 --entry-point $function_class \
--trigger-resource $resource_name \
--trigger-event $event_name \
--runtime java17
Onde:
$nameé um nome descritivo arbitrário que será o nome da função após a implementação.$function_classé o nome totalmente qualificado da sua classe (por exemplo,com.example.MyFunctionou apenasMyFunctionse não usar um pacote).$resource_namee$event_namesão específicos dos eventos que acionam a sua função. Alguns exemplos de recursos e eventos suportados são o Google Cloud Pub/Sub e o Google Cloud Storage.
Quando implementa uma função a partir da origem, a CLI gcloud carrega o diretório de origem (e tudo o que contém) para o Google Cloud para compilar. Para evitar o envio de ficheiros desnecessários, pode usar o ficheiro .gcloudignore. Edite o ficheiro .gcloudignore para ignorar diretórios comuns, como .git e target/. Por exemplo, um ficheiro
.gcloudignore pode conter o seguinte:
.git
target
build
.idea
Implemente a partir de um JAR
Pode implementar um JAR pré-criado que contenha a função. Isto é útil, especialmente, se precisar de implementar uma função que use dependências de um repositório de artefactos privado que não pode ser acedido a partir do pipeline de compilação do Google Cloud quando compila a partir da origem. O JAR pode ser um JAR abrangente que
contém a classe de função e todas as respetivas classes de dependência, ou um JAR simples
que tem entradas Class-Path para JARs de dependência no ficheiro META-INF/MANIFEST.MF.
Crie e implemente um JAR Uber
Um JAR uber é um ficheiro JAR que contém as classes de funções, bem como todas as respetivas dependências. Pode criar um JAR completo com o Maven e o Gradle. Para implementar um Uber JAR, tem de ser o único ficheiro JAR no respetivo diretório, por exemplo:
my-function-deployment/ ├─ my-function-with-all-dependencies.jar
Pode copiar o ficheiro para esta estrutura de diretórios ou usar os plug-ins Maven e Gradle para gerar o diretório de implementação correto.
Maven
Use o plug-in Maven Shade para criar um JAR uber. Configure o seu
pom.xml com o 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>
Crie o JAR Uber:
mvn package
Em seguida, implemente com o seguinte comando:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=target/deployment
Gradle
Use o plugin Shadow para o Gradle. Configure o plugin no ficheiro
build.gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
...
classpath "com.github.jengelman.gradle.plugins:shadow:5.2.0"
}
}
plugins {
id 'java'
...
}
sourceCompatibility = '17.0'
targetCompatibility = '17.0'
apply plugin: 'com.github.johnrengelman.shadow'
shadowJar {
mergeServiceFiles()
}
...
Agora, pode executar o Gradle com o comando shadowJar:
gradle shadowJar
Em seguida, implemente com o seguinte comando:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=build/libs
Crie e implemente um JAR simples com dependências externas
Pode criar e implementar um ficheiro JAR simples em vez de um uber JAR. Um JAR simples é um ficheiro JAR que contém apenas as classes de funções sem as dependências incorporadas no mesmo ficheiro JAR. Uma vez que as dependências ainda são necessárias para a implementação, tem de configurar as coisas da seguinte forma:
- As dependências têm de estar numa subdiretoria relativa ao JAR a implementar.
- O JAR tem de ter um ficheiro
META-INF/MANIFEST.MFque inclua um atributoClass-Pathcujo valor liste os caminhos de dependência necessários.
Por exemplo, o seu ficheiro JAR my-function.jar tem um ficheiro META-INF/MANIFEST.MF com 2 dependências no diretório libs/ (uma lista de caminhos relativos separados por espaços):
Manifest-Version: 1.0
Class-Path: libs/dep1.jar libs/dep2.jar
O diretório de implementação deve conter o ficheiro JAR da função principal, bem como um subdiretório com as duas dependências das quais a função depende:
function-deployment/
├─ my-function.jar
├─ libs
├─ dep1.jar
├─ dep2.jar
Pode criar um JAR simples com o Maven e o Gradle:
Maven
Use o plug-in JAR do Maven para configurar automaticamente MANIFEST.MF com os caminhos para as dependências e, de seguida, use o plug-in de dependência do Maven para copiar as dependências.
<?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>
Crie o JAR simples:
mvn package
Em seguida, implemente com o seguinte comando:
gcloud functions deploy jar-example \
--entry-point=Example \
--no-gen2 \
--runtime=java17 \
--trigger-http \
--source=target/deployment
Gradle
Atualize o ficheiro do projeto build.gradle para adicionar uma nova tarefa para obter as dependências:
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
}
}