Schnellstart: Erstellen einer Java-Funktion über die Befehlszeile in Azure

In diesem Artikel verwenden Sie Befehlszeilentools zum Erstellen einer Java-Funktion, die auf HTTP-Anforderungen reagiert. Der Code wird lokal getestet und anschließend in der serverlosen Umgebung von Azure Functions bereitgestellt.

Sollte Maven nicht Ihr bevorzugtes Entwicklungstool sein, stehen ähnliche Tutorials für Java-Entwickler zur Verfügung:

Im Rahmen dieser Schnellstartanleitung fallen in Ihrem Azure-Konto ggf. geringfügige Kosten im Centbereich an.

Konfigurieren Ihrer lokalen Umgebung

Bevor Sie mit diesem Lernprogramm beginnen können, benötigen Sie Folgendes:

Prüfen der Voraussetzungen

  • Führen Sie in einem Terminal- oder Befehlsfenster func --version aus, um zu überprüfen, ob Version 4.x der Azure Functions Core Tools verwendet wird.

  • Führen Sie az --version aus, um zu überprüfen, ob die Version 2.4 oder höher der Azure CLI verwendet wird.

  • Führen Sie az login aus, um sich bei Azure anzumelden und zu überprüfen, ob ein aktives Abonnement vorhanden ist.

Erstellen eines lokalen Funktionsprojekts

In Azure Functions handelt es sich bei einem Funktionsprojekt um einen Container für eine oder mehrere individuelle Funktionen, die jeweils auf einen bestimmten Trigger reagieren. Für alle Funktionen eines Projekts werden die gleichen lokalen Konfigurationen und Hostkonfigurationen gemeinsam genutzt. In diesem Abschnitt erstellen Sie ein Funktionsprojekt, das nur eine Funktion enthält.

  1. Führen Sie in einem leeren Ordner den folgenden Befehl aus, um das Functions-Projekt über einen Maven-Archetyp zu generieren.

    mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=8
    

    Wichtig

    • Verwenden Sie -DjavaVersion=11, wenn Sie Ihre Funktionen in Java 11 ausführen möchten. Weitere Informationen finden Sie unter Java-Versionen.
    • Damit Sie diesen Artikel durcharbeiten können, muss die Umgebungsvariable JAVA_HOME auf den Installationsspeicherort der richtigen Version des JDK festgelegt sein.
  2. Maven fordert Sie zur Eingabe von Werten auf, die erforderlich sind, um die Generierung des Projekts bei der Bereitstellung abzuschließen.
    Geben Sie die folgenden Werte ein, wenn Sie dazu aufgefordert werden:

    Prompt Wert BESCHREIBUNG
    groupId com.fabrikam Ein Wert, der Ihr Projekt projektübergreifend eindeutig identifiziert. Für den Wert müssen die Paketbenennungsregeln für Java eingehalten werden.
    artifactId fabrikam-functions Der Name des Behälters (ohne Versionsnummer).
    version 1.0-SNAPSHOT Wählen Sie den Standardwert aus.
    package com.fabrikam Das Java-Paket für den generierten Funktionscode. Verwenden Sie den Standardwert.
  3. Geben Sie zur Bestätigung Y ein, oder drücken Sie die EINGABETASTE.

    Maven erstellt die Projektdateien in einem neuen Ordner und benennt ihn mit dem Wert von artifactId (in diesem Beispiel: fabrikam-functions).

  4. Navigieren Sie zum Projektordner:

    cd fabrikam-functions
    

    Dieser Ordner enthält verschiedene Dateien für das Projekt, z. B. die Konfigurationsdateien local.settings.json und host.json. Da local.settings.json aus Azure heruntergeladene Geheimnisse enthalten kann, wird die Datei in der GITIGNORE-Datei standardmäßig aus der Quellcodeverwaltung ausgeschlossen.

(Optional) Untersuchen des Dateiinhalts

Bei Bedarf können Sie Lokales Ausführen der Funktion überspringen und den Dateiinhalt später untersuchen.

Function.java

Function.java enthält eine Methode vom Typ run, die Anforderungsdaten in der Variablen request empfängt. Hierbei handelt es sich um eine HTTP-Anforderungsnachricht (HttpRequestMessage), die mit der Anmerkung HttpTrigger versehen ist, um das Triggerverhalten zu definieren.

/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

package com.functions;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.HttpMethod;
import com.microsoft.azure.functions.HttpRequestMessage;
import com.microsoft.azure.functions.HttpResponseMessage;
import com.microsoft.azure.functions.HttpStatus;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FixedDelayRetry;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;

import java.util.Optional;

/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
    /**
     * This function listens at endpoint "/api/HttpExample". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/HttpExample
     * 2. curl "{your host}/api/HttpExample?name=HTTP%20Query"
     */
    @FunctionName("HttpExample")
    public HttpResponseMessage run(
            @HttpTrigger(
                name = "req",
                methods = {HttpMethod.GET, HttpMethod.POST},
                authLevel = AuthorizationLevel.ANONYMOUS)
                HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        // Parse query parameter
        final String query = request.getQueryParameters().get("name");
        final String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
        } else {
            return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
        }
    }

    public static int count = 1;

    /**
     * This function listens at endpoint "/api/HttpExampleRetry". The function is re-executed in case of errors until the maximum number of retries occur.
     * Retry policies: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-error-pages?tabs=java
     */
    @FunctionName("HttpExampleRetry")
    @FixedDelayRetry(maxRetryCount = 3, delayInterval = "00:00:05")
    public HttpResponseMessage HttpExampleRetry(
        @HttpTrigger(
            name = "req",
            methods = {HttpMethod.GET, HttpMethod.POST},
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
        final ExecutionContext context) throws Exception {
        context.getLogger().info("Java HTTP trigger processed a request.");

        if(count<3) {
            count ++;
            throw new Exception("error");
        }

        // Parse query parameter
        final String query = request.getQueryParameters().get("name");
        final String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body("Please pass a name on the query string or in the request body").build();
        } else {
            return request.createResponseBuilder(HttpStatus.OK).body(name).build();
        }
    }

    /**
     * This function listens at endpoint "/api/HttpTriggerJavaVersion".
     * It can be used to verify the Java home and java version currently in use in your Azure function
     */
    @FunctionName("HttpTriggerJavaVersion")
    public static HttpResponseMessage HttpTriggerJavaVersion(
        @HttpTrigger(
            name = "req",
            methods = {HttpMethod.GET, HttpMethod.POST},
            authLevel = AuthorizationLevel.ANONYMOUS)
            HttpRequestMessage<Optional<String>> request,
        final ExecutionContext context
    ) {
        context.getLogger().info("Java HTTP trigger processed a request.");
        final String javaVersion = getJavaVersion();
        context.getLogger().info("Function - HttpTriggerJavaVersion" + javaVersion);
        return request.createResponseBuilder(HttpStatus.OK).body("HttpTriggerJavaVersion").build();
    }

    public static String getJavaVersion() {
        return String.join(" - ", System.getProperty("java.home"), System.getProperty("java.version"));
    }
}

Die Antwortnachricht wird von der API HttpResponseMessage.Builder generiert.

pom.xml

Einstellungen für die Azure-Ressourcen, die zum Hosten Ihrer App erstellt werden, werden in der generierten Datei „pom.xml“ im Konfigurationselement (configuration) des Plug-Ins mit der Gruppen-ID (groupId) com.microsoft.azure definiert. So wird beispielsweise durch das folgende Konfigurationselement eine Maven-basierte Bereitstellung angewiesen, eine Funktions-App in der Ressourcengruppe java-functions-group in der Region westus zu erstellen. Die Funktions-App selbst wird unter Windows mit Hosting im Tarif java-functions-app-service-plan ausgeführt. Bei dem Tarif handelt es sich standardmäßig um einen serverlosen Verbrauchstarif.

    </configuration>
</plugin>
<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
</plugin>
<plugin>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-functions-maven-plugin</artifactId>
    <version>${azure.functions.maven.plugin.version}</version>
    <configuration>
        <!-- function app name -->
        <appName>${functionAppName}</appName>
        <!-- function app resource group -->
        <resourceGroup>${functionResourceGroup}</resourceGroup>
        <!-- function app service plan name -->
        <appServicePlanName>java-functions-app-service-plan</appServicePlanName>
        <!-- function app region-->
        <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supported-regions for all valid values -->
        <region>${functionAppRegion}</region>
        <!-- function pricingTier, default to be consumption if not specified -->
        <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details#supported-pricing-tiers for all valid values -->
        <!-- <pricingTier></pricingTier> -->

        <!-- Whether to disable application insights, default is false -->
        <!-- refers https://github.com/microsoft/azure-maven-plugins/wiki/Azure-Functions:-Configuration-Details for all valid configurations for application insights-->
        <!-- <disableAppInsights></disableAppInsights> -->
        <runtime>
            <!-- runtime os, could be windows, linux or docker-->
            <os>windows</os>
            <javaVersion>8</javaVersion>
            <!-- for docker function, please set the following parameters -->
            <!-- <image>[hub-user/]repo-name[:tag]</image> -->
            <!-- <serverId></serverId> -->
            <!-- <registryUrl></registryUrl>  -->
        </runtime>
        <appSettings>
            <property>
                <name>FUNCTIONS_EXTENSION_VERSION</name>
                <value>~3</value>
            </property>
        </appSettings>
    </configuration>
    <executions>
        <execution>
            <id>package-functions</id>

Diese Einstellungen ermöglichen die Steuerung der Ressourcenerstellung in Azure. Beispielsweise können Sie runtime.os vor der ersten Bereitstellung von windows in linux ändern. Eine umfassende Liste der Einstellungen, die vom Maven-Plug-In unterstützt werden, finden Sie in den Konfigurationsdetails.

FunctionTest.java

Durch den Archetyp wird auch ein Komponententest für Ihre Funktion generiert. Wenn Sie Ihrer Funktion Bindungen hinzufügen oder dem Projekt neue Funktionen hinzufügen, müssen auch die Tests in der Datei FunctionTest.java geändert werden.

Lokales Ausführen der Funktion

  1. Führen Sie Ihre Funktion aus, indem Sie den lokalen Azure Functions-Runtimehost im Ordner LocalFunctionProj starten:

    mvn clean package
    mvn azure-functions:run
    

    Gegen Ende der Ausgabe sollten die folgenden Zeilen angezeigt werden:

     ...
    
     Now listening on: http://0.0.0.0:7071
     Application started. Press Ctrl+C to shut down.
    
     Http Functions:
    
             HttpExample: [GET,POST] http://localhost:7071/api/HttpExample
     ...
    
     

    Hinweis

    Sollte „HttpExample“ nicht wie oben dargestellt angezeigt werden, haben Sie den Host wahrscheinlich außerhalb des Stammordners des Projekts gestartet. Drücken Sie in diesem Fall STRG+C, um den Host zu beenden. Navigieren Sie anschließend zum Stammordner des Projekts, und führen Sie den vorherigen Befehl erneut aus.

  2. Kopieren Sie die URL Ihrer HttpExample-Funktion aus dieser Ausgabe in einen Browser, und fügen Sie die Abfragezeichenfolge ?name=<YOUR_NAME> an. Die vollständige URL lautet dann wie folgt: http://localhost:7071/api/HttpExample?name=Functions. Im Browser sollte eine Meldung angezeigt werden, die den Wert Ihrer Abfragezeichenkette zurückgibt. Im Terminal, in dem Sie Ihr Projekt gestartet haben, wird beim Senden von Anforderungen auch die Protokollausgabe angezeigt.

  3. Wenn Sie fertig sind, drücken Sie STRG+C, und wählen Sie y aus, um den Funktionshost zu beenden.

Bereitstellen des Funktionsprojekts in Azure

Wenn Sie Ihr Funktionsprojekt erstmals bereitstellen, werden in Azure eine Funktions-App und zugehörige Ressourcen erstellt. Einstellungen für die Azure-Ressourcen, die zum Hosten Ihrer App erstellt werden, werden in der Datei pom.xml definiert. In diesem Artikel werden die Standardeinstellungen übernommen.

Tipp

Wenn Sie eine Funktions-App für Linux anstatt für Windows erstellen möchten, ändern Sie das Element runtime.os in der Datei „pom.xml“ von windows in linux. Das Ausführen von Linux in einem Verbrauchstarif wird in diesen Regionen unterstützt. Unter Linux ausgeführte Apps und unter Windows ausgeführte Apps können nicht in der gleichen Ressourcengruppe enthalten sein.

  1. Damit Sie die Bereitstellung durchführen können, müssen Sie sich entweder über die Azure CLI oder über Azure PowerShell bei Ihrem Azure-Abonnement anmelden.

    az login
    

    Mit dem Befehl az login werden Sie bei Ihrem Azure-Konto angemeldet.

  2. Verwenden Sie den folgenden Befehl, um Ihr Projekt für eine neue Funktions-App bereitzustellen.

    mvn azure-functions:deploy
    

    Dadurch werden in Azure die folgenden Ressourcen erstellt:

    • Ressourcengruppe namens java-functions-group.
    • Speicherkonto – von Functions benötigt. Der Name wird nach dem Zufallsprinzip basierend auf den Anforderungen für den Speicherkontonamen generiert.
    • Hostingplan: Serverloses Hosting für Ihre Funktions-App in der Region westus. Der Name lautet java-functions-app-service-plan.
    • Funktions-App – die Bereitstellungs-und Ausführungseinheit für Ihre Funktionen. Der Name wird auf Grundlage der artifactId zufällig generiert und mit einer zufällig generierten Zahl angefügt.

    Bei der Bereitstellung werden die Projektdateien mithilfe von zip deployment gepackt und für die neue Funktions-App bereitgestellt. Der Code wird über das Bereitstellungspaket in Azure ausgeführt.

Aufrufen der Funktion in Azure

Da für Ihre Funktion ein HTTP-Trigger verwendet wird, führen Sie das Aufrufen durch, indem Sie per Browser eine HTTP-Anforderung an die entsprechende URL senden oder ein Tool wie curl verwenden.

Kopieren Sie die vollständige Aufruf-URL, die in der Ausgabe des Befehls zum Veröffentlichen (publish) angezeigt wird, in eine Browseradressleiste, und fügen Sie den Abfrageparameter ?name=Functions an. Im Browser sollte eine ähnliche Ausgabe wie bei der lokalen Ausführung der Funktion angezeigt werden.

The output of the function run on Azure in a browser

Führen Sie den folgenden Befehl aus, um Streamingprotokolle nahezu in Echtzeit anzuzeigen:

func azure functionapp logstream <APP_NAME> 

In einem separaten Terminalfenster oder im Browser rufen Sie die Remotefunktion erneut auf. Ein ausführliches Protokoll der Funktionsausführung in Azure wird im Terminal angezeigt.

Bereinigen von Ressourcen

Gehen Sie wie folgt vor, falls Sie mit dem nächsten Schritt fortfahren möchten: Fügen Sie eine Ausgabebindung für die Azure Storage-Warteschlange hinzu, und behalten Sie alle Ressourcen bei, weil der nächste Schritt auf der bisherigen Arbeit aufbaut.

Verwenden Sie andernfalls den unten angegebenen Befehl, um die Ressourcengruppe und alle darin enthaltenen Ressourcen zu löschen, damit keine weiteren Kosten anfallen.

az group delete --name java-functions-group

Nächste Schritte