Azure の Spring Cloud 関数

この記事では、Spring Cloud Function を使用して Java 関数を開発し、それを Azure Functions に発行する手順について説明します。 完了すると、関数コードは Azure の従量課金プランで実行され、HTTP 要求を使用してトリガーできるようになります。

Azure サブスクリプションをお持ちでない場合は、開始する前に無料アカウントを作成してください。

前提条件

Java を使用して関数を開発するには、以下のものがインストールされている必要があります。

重要

  1. このクイック スタートを完了するには、 JAVA_HOME 環境変数を JDK のインストール場所に設定する必要があります。
  2. コア ツールのバージョンが 4.0.5455 以上であることを確認します。

ビルドするもの

ここでは、Azure Functions で実行され、Spring Cloud 関数を使用して構成される従来の "Hello, World" 関数を構築します。

この関数は、ユーザー名を User 含む JSON オブジェクトを受け取り Greeting 、そのユーザーにウェルカム メッセージを含むオブジェクトを返します。

このプロジェクトは、GitHub の azure-function-java-worker リポジトリの Azure サンプルの Spring Cloud 関数で入手できます。 このクイックスタートで説明されている最後の作業を確認する場合は、そのサンプルを直接使用できます。

新しい Maven プロジェクトを作成する

空の Maven プロジェクトを作成し、Spring Cloud Function と Azure Functions を使用してそれを構成します。

空のフォルダーに新しい pom.xml ファイルを作成し、サンプル プロジェクトの pom.xml ファイルの内容をコピーして貼り付けます。

Note

このファイルでは、Spring Boot と Spring Cloud Function 両方の Maven 依存関係を使用し、Spring Boot と Azure Functions の Maven プラグインを構成します。

アプリケーションのいくつかのプロパティをカスタマイズする必要があります。

  • <functionAppName> は、自分の Azure 関数の名前です
  • <functionAppRegion> は、自分の関数がデプロイされる Azure リージョンの名前です
  • <functionResourceGroup> は、使用している Azure リソース グループの名前です

これらのプロパティを pom.xml ファイルの先頭付近に直接、次の例に示すように変更します。

    <properties>
        <java.version>11</java.version>

        <!-- Spring Boot start class. WARNING: correct class must be set -->
        <start-class>com.example.DemoApplication</start-class>

        <!-- customize those properties. WARNING: the functionAppName should be unique across Azure -->
        <azure.functions.maven.plugin.version>1.29.0</azure.functions.maven.plugin.version>
        <functionResourceGroup>my-spring-function-resource-group</functionResourceGroup>
        <functionAppServicePlanName>my-spring-function-service-plan</functionAppServicePlanName>
        <functionAppName>my-spring-function</functionAppName>
        <functionPricingTier>Y1</functionPricingTier>
        <functionAppRegion>eastus</functionAppRegion>
    </properties>

Azure 構成ファイルを作成する

src/メイン/resources フォルダーを作成し、次の Azure Functions 構成ファイルを追加します。

host.json:

{
  "version": "2.0",
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.2.0)"
  },
  "functionTimeout": "00:10:00"
}

local.settings.json:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "java",
    "FUNCTIONS_EXTENSION_VERSION": "~4",
    "AzureWebJobsDashboard": ""
  }
}

ドメイン オブジェクトを作成する

Azure Functions では、JSON 形式のオブジェクトを送受信できます。 ここでは、ドメイン モデルを表す User オブジェクトと Greeting オブジェクトを作成します。 このクイックスタートをカスタマイズして、もっと自分の関心に沿ったものにしたい場合は、さらに多くのプロパティを備えた、より複雑なオブジェクトを作成できます。

src/main/java/com/example/model フォルダーを作成して、次の 2 つのファイルを追加します。

User.java:

package com.example.model;

public class User {

    private String name;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Greeting.java:

package com.example.model;

public class Greeting {

    private String message;

    public Greeting() {
    }

    public Greeting(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Spring Boot アプリケーションを作成する

このアプリケーションは、すべてのビジネス ロジックを管理し、Spring Boot エコシステム全体にアクセスできます。 これができることで、標準の Azure 関数に比べて、2 つの主なメリットがあります。

  • これは Azure Functions API に依存していないため、他のシステムに簡単に移植できます。 たとえば、通常の Spring Boot アプリケーションで再利用することができます。
  • Spring Boot のすべての @Enable 注釈を使用して、新しい機能を追加することができます。

src/main/java/com/example フォルダーで次のファイルを作成します。これは通常の Spring Boot アプリケーションです。

DemoApplication.java:

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(DemoApplication.class, args);
    }
}

次に、src/メイン/java/com/example/hello フォルダーに次のファイルを作成します。 このコードには、実行する関数を表す Spring Boot コンポーネントが含まれています。

Hello.java:

package com.example.hello;

import com.example.model.*;
import org.springframework.stereotype.Component;
import java.util.function.Function;

@Component
public class Hello implements Function<User, Greeting> {

    @Override
    public Greeting apply(User user) {
        return new Greeting("Hello, " + user.getName() + "!\n");
    }
}

Note

Hello は、非常に具体的な関数です。

  • それは java.util.function.Function です。 これにはビジネス ロジックが含まれており、標準の Java API を使用して、あるオブジェクトを別のオブジェクトに変換します。
  • これは @Component 注釈を備えているため、Spring Bean です。既定では、その名前はクラスと同じですが、小文字で始まります (hello)。 アプリケーションで他の関数を作成する場合は、この名前付け規則に従うことが重要です。 名前は、次のセクションで作成する Azure 関数名と一致している必要があります。

Azure 関数を作成する

完全な Azure Functions API を活用するために、前の手順で作成した Spring Cloud 関数にその実行を委任する Azure 関数をコーディングします。

src/メイン/java/com/example/hello フォルダーに、次の Azure 関数クラス ファイルを作成します。

HelloHandler.java:

package com.example.hello;

import com.microsoft.azure.functions.*;
import com.microsoft.azure.functions.annotation.AuthorizationLevel;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.HttpTrigger;
import com.example.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
public class HelloHandler {

    @Autowired
    private Hello hello;

    @FunctionName("hello")
    public HttpResponseMessage execute(
        @HttpTrigger(name = "request", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<User>> request, ExecutionContext context) {
        User user = request.getBody()
                           .filter(u -> u.getName() != null)
                           .orElseGet(() -> new User(request.getQueryParameters().getOrDefault("name", "world")));
        context.getLogger().info("Greeting user name: " + user.getName());
        return request.createResponseBuilder(HttpStatus.OK)
                      .body(hello.apply(user))
                      .header("Content-Type", "application/json")
                      .build();
    }
}

この Java クラスは Azure 関数であり、次のような興味深い機能を備えています。

  • クラスには @Component 注釈があるため、Spring Bean です。
  • @FunctionName("hello") で定義されているように、関数の名前は hello です。
  • このクラスは実際の Azure 関数を実装しているため、ここで完全な Azure Functions API を使用できます。

単体テストを追加する

この手順は省略可能ですが、アプリケーションが正しく動作することを検証するためにお勧めします。

src/test/java/com/example フォルダーを作成し、次の JUnit テストを追加します。

HelloTest.java:

package com.example;

import com.example.hello.Hello;
import com.example.model.Greeting;
import com.example.model.User;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class HelloTest {

    @Test
    public void test() {
        Greeting result = new Hello().apply(new User("foo"));
        assertThat(result.getMessage()).isEqualTo("Hello, foo!\n");
    }
}

ここで、Maven を使用して自分の Azure 関数をテストできます。

mvn clean test

関数をローカルで実行する

自分のアプリケーションを Azure 関数にデプロイする前に、まずはそれをローカルでテストしてみましょう。

最初に、自分のアプリケーションを Jar ファイルにパッケージ化する必要があります。

mvn package

アプリケーションがパッケージ化されたら、azure-functions Maven プラグインを使用してそれを実行できます。

mvn azure-functions:run

Azure 関数は、ポート 7071 を使って自分の localhost で使用できるようになっているはずです。 JSON 形式の User オブジェクトが含まれた POST 要求を送信して、関数をテストできます。 たとえば、cURL を使用した場合:

curl -X POST http://localhost:7071/api/hello -d "{\"name\":\"Azure\"}"

関数は JSON 形式のままで Greeting オブジェクトを返すはずです。

{
  "message": "Hello, Azure!\n"
}

次に示すのは、画面の上部に cURL 要求があり、下部にローカルの Azure 関数があるスクリーンショットです。

Azure Function running locally

関数をローカルでデバッグする

以下のセクションで、関数をデバッグする方法について説明します。

Intellij IDEA を使用したデバッグ

プロジェクトを Intellij IDEA で開き、アタッチするリモート JVM デバッグ実行構成を作成します。 詳細については、「チュートリアル: リモート デバッグ」を参照してください。

Create a Remote JVM Debug run configuration

次のコマンドでアプリケーションを実行します。

mvn azure-functions:run -DenableDebug

アプリケーションが起動すると、次の出力が表示されます。

Worker process started and initialized.
Listening for transport dt_socket at address: 5005

IntelliJ IDEA でプロジェクトのデバッグを開始します。 次の出力が表示されます。

Connected to the target VM, address: 'localhost:5005', transport: 'socket'

デバッグするブレークポイントをマークします。 Intellij IDEA は、要求の送信後にデバッグ モードになります。

Visual Studio Code を使用したデバッグ

プロジェクトを Visual Studio Code で開き、次の launch.json ファイル内容を構成します。

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "java",
            "name": "Attach to Remote Program",
            "request": "attach",
            "hostName": "127.0.0.1",
            "port": 5005
        }
    ]
}

次のコマンドでアプリケーションを実行します。

mvn azure-functions:run -DenableDebug

アプリケーションが起動すると、次の出力が表示されます。

Worker process started and initialized.
Listening for transport dt_socket at address: 5005

Visual Studio Code でプロジェクトのデバッグを開始し、デバッグするブレークポイントをマークします。 Visual Studio Code は、要求の送信後にデバッグ モードになります。 詳細については、「Java の実行とデバッグ」を参照してください。

関数を Azure Functions にデプロイする

次に、Azure 関数を運用環境に発行します。 <functionAppName>pom.xml ファイルで定義した 、<functionAppRegion>、および<functionResourceGroup>プロパティは、関数の構成に使用されます。

Note

Maven プラグインは Azure で認証する必要があります。 Azure CLI がインストールされている場合は、続行する前に az login を使用してください。 認証オプションの詳細については、azure-maven-plugins リポジトリで「認証」を参照してください。

Maven を実行して自分の関数を自動でデプロイします。

mvn azure-functions:deploy

次に Azure portal に移動して、作成された Function App を見つけます。

関数を選択します。

  • 関数の概要で、関数の URL をメモします。
  • 実行中の関数をチェックするには、ナビゲーション メニューの [ログ ストリーミング] を選択します。

ここで、前のセクションで行ったように cURL を使用して、次の例に示すように、実行中の関数にアクセスします。 your-function-name は実際の関数名に置き換えてください。

curl https://your-function-name.azurewebsites.net/api/hello -d "{\"name\":\"Azure\"}"

前のセクションと同様に、関数は JSON 形式のままで Greeting オブジェクトを返すはずです。

{
  "message": "Hello, Azure!\n"
}

おめでとうございます。Azure Functions 上で実行される Spring Cloud 関数ができました。 Spring Cloud 関数の詳細とサンプルについては、次のリソースを参照してください。

次のステップ

Spring および Azure の詳細については、Azure ドキュメント センターで引き続き Spring に関するドキュメントをご確認ください。