Help us understand the problem. What is going on with this article?

JavaでAzure Functionsを作る

More than 1 year has passed since last update.

Microsoftのドキュメント「Java と Maven を使用して初めての関数を作成する (プレビュー)」を以下の環境で試しました。

  • Windows 10 Pro 1803(64bit)
  • JDK 8u152
  • Microsoft .NET Core SDK 2.1.402
  • Azure CLI 2.0.45
  • Visual Studio Code 1.27.1
    • Java Extension Pack 0.3.0
    • Language Support for Java(TM) by Red Hat 0.30.0
    • Maven for Java 0.10.0
  • Node.js 8.9.4 (自分の環境ではプリインストール)
  • npm 5.6.0(自分の環境ではプリインストール)

無事に動いたので以下メモ。

Azure Functions Core Toolsのインストール

ドキュメントを参考にAzure Functions Core Toolsをインストールしました。手順通り、まずは.NET Coreをインストールしました。

.NET Coreのダウンロードページで.NET Core SDKをダウンロード
2018-09-16_12h36_38.png

インストールを進めます。
2018-09-16_12h39_37.png

インストール完了です。
2018-09-16_12h45_16.png

npmでAzure Functions Core Toolsをインストールします。自分の環境は既にインストール済だったnpm 5.6.0を利用しました。

npm install -g azure-functions-core-tools@core

azure-functions-archetypeで雛形を作成

Mavenの「azure-functions-archetype」を使って雛形を作成します。

VSCodeで「表示」->「コマンドパレット」から「Maven:Generate from Maven Archetype」を選択して、保存先のフォルダを選択します。
2018-09-17_21h09_55.png

「azure-functions-archetype」を選択します。
2018-09-17_21h11_09.png

すると自動的に以下の処理が開始されます。

PS D:\web\azure\AzureFunctionsJava> cmd /c mvn archetype:generate -DarchetypeArtifactId="azure-functions-archetype" -DarchetypeGroupId="com.microsoft.azure"
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.0.1:generate (default-cli) > generate-sources @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:3.0.1:generate (default-cli) < generate-sources @ standalone-pom <<<
[INFO]
[INFO]
[INFO] --- maven-archetype-plugin:3.0.1:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype [com.microsoft.azure:azure-functions-archetype:1.15] found in catalog remote
Downloading from central: https://repo.maven.apache.org/maven2/com/microsoft/azure/azure-functions-archetype/1.15/azure-functions-archetype-1.15.pom
Downloaded from central: https://repo.maven.apache.org/maven2/com/microsoft/azure/azure-functions-archetype/1.15/azure-functions-archetype-1.15.pom (1.5 kB at 4.3 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/com/microsoft/azure/azure-functions-archetype/1.15/azure-functions-archetype-1.15.jar
Downloaded from central: https://repo.maven.apache.org/maven2/com/microsoft/azure/azure-functions-archetype/1.15/azure-functions-archetype-1.15.jar (15 kB at 44 kB/s)

対話式に設定します。ここではgroupIdとartifactIdだけ指定して、あとはデフォルトで空白のまま進みました。

Define value for property 'groupId' (should match expression '[A-Za-z0-9_\-\.]+'): tech.kikutaro
[INFO] Using property: groupId = tech.kikutaro
Define value for property 'artifactId' (should match expression '[A-Za-z0-9_\-\.]+'): AzureFunctionsJava
[INFO] Using property: artifactId = AzureFunctionsJava
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' tech.kikutaro: :
Define value for property 'appName' azurefunctionsjava-20180917211315850: :
Define value for property 'appRegion' westus: :
Define value for property 'resourceGroup' java-functions-group: :
Confirm properties configuration:
groupId: tech.kikutaro
groupId: tech.kikutaro
artifactId: AzureFunctionsJava
artifactId: AzureFunctionsJava
version: 1.0-SNAPSHOT
package: tech.kikutaro
appName: azurefunctionsjava-20180917211315850
appRegion: westus
resourceGroup: java-functions-group
 Y: : Y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: azure-functions-archetype:1.15
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: tech.kikutaro
[INFO] Parameter: artifactId, Value: AzureFunctionsJava
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: package, Value: tech.kikutaro
[INFO] Parameter: packageInPathFormat, Value: tech/kikutaro
[INFO] Parameter: appName, Value: azurefunctionsjava-20180917211315850
[INFO] Parameter: resourceGroup, Value: java-functions-group
[INFO] Parameter: package, Value: tech.kikutaro
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: groupId, Value: tech.kikutaro
[INFO] Parameter: appRegion, Value: westus
[INFO] Parameter: artifactId, Value: AzureFunctionsJava
[INFO] Project created from Archetype in dir: D:\web\azure\AzureFunctionsJava\AzureFunctionsJava
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:20 min
[INFO] Finished at: 2018-09-17T21:13:37+09:00
[INFO] ------------------------------------------------------------------------

これで雛形の完成です。雛形といいつつ、以下のようなコードが書かれているので、そのまま動かせます。

package tech.kikutaro;

import java.util.*;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;

/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
    /**
     * This function listens at endpoint "/api/HttpTrigger-Java". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/HttpTrigger-Java
     * 2. curl {your host}/api/HttpTrigger-Java?name=HTTP%20Query
     */
    @FunctionName("HttpTrigger-Java")
    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
        String query = request.getQueryParameters().get("name");
        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();
        }
    }
}

ローカルでの動作確認

ビルドします。

mvn clean package

以下、ダウンロード部分は一部省略しています。

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< tech.kikutaro:AzureFunctionsJava >------------------
[INFO] Building Azure Java Functions 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ AzureFunctionsJava ---
[INFO] Deleting D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ AzureFunctionsJava ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\src\main\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ AzureFunctionsJava ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ AzureFunctionsJava ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ AzureFunctionsJava ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\test-classes
[WARNING] /D:/web/azure/AzureFunctionsJava/AzureFunctionsJava/src/test/java/tech/kikutaro/FunctionTest.java: D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\src\test\java\tech\kikutaro\FunctionTest.javaの操作は、未チェックまたは安全ではありません。
[WARNING] /D:/web/azure/AzureFunctionsJava/AzureFunctionsJava/src/test/java/tech/kikutaro/FunctionTest.java: 詳細は、-Xlint:uncheckedオプションを指定して再コン
パイルしてください。
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ AzureFunctionsJava ---
[INFO] Surefire report directory: D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running tech.kikutaro.FunctionTest
9 17, 2018 9:25:20 午後 tech.kikutaro.Function run
情報: Java HTTP trigger processed a request.
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.302 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-dependency-plugin:3.1.1:copy-dependencies (copy-dependencies) @ AzureFunctionsJava ---
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ AzureFunctionsJava ---
[INFO] Building jar: D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\AzureFunctionsJava-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- azure-functions-maven-plugin:1.0.0-beta-6:package (package-functions) @ AzureFunctionsJava ---
Downloading from central: https://repo.maven.apache.org/maven2/com/microsoft/azure/azure-maven-plugin-lib/1.2.0/azure-maven-plugin-lib-1.2.0.pom
AI: INFO 17-09-2018 21:27, 1: Configuration file has been successfully found as resource
AI: INFO 17-09-2018 21:27, 1: Configuration file has been successfully found as resource
[INFO]
[INFO] Step 1 of 7: Searching for Azure Functions entry points
[INFO] 1 Azure Functions entry point(s) found.
[INFO]
[INFO] Step 2 of 7: Generating Azure Functions configurations
[INFO] Generation done.
[INFO]
[INFO] Step 3 of 7: Validating generated configurations
[INFO] Validation done.
[INFO]
[INFO] Step 4 of 7: Saving empty host.json
[INFO] Successfully saved to D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850\host.json
[INFO]
[INFO] Step 5 of 7: Saving configurations to function.json
[INFO] Starting processing function: HttpTrigger-Java
[INFO] Successfully saved to D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850\HttpTrigger-Java\function.json
[INFO]
[INFO] Step 6 of 7: Copying JARs to staging directoryD:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource to D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850
[INFO] Copied successfully.
[INFO]
[INFO] Step 7 of 7: Installing function extensions if needed
  Writing C:\Users\kikuta\AppData\Local\Temp\tmpC1CE.tmp
info : パッケージ 'Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator' の PackageReference をプロジェクト 'D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\extensions.csproj' に追加しています。
log  : D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\extensions.csproj のパッケージを復元しています...
info : パッケージ 'Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator' は、プロジェクト 'D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\extensions.csproj' のすべての指定されたフレームワークとの互換性があります。
info : パッケージ 'Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator' バージョン '1.0.0' の PackageReference がファイル 'D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\extensions.csproj' で更新されました。


.NET Core 向け Microsoft (R) Build Engine バージョン 15.8.166+gd4e8d81a88
Copyright (C) Microsoft Corporation.All rights reserved.

  D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\extensions.csproj のパッケージを復元しています...
  MSBuild ファイル D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\obj\extensions.csproj.nuget.g.props を生成しています。
  MSBuild ファイル D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\obj\extensions.csproj.nuget.g.targets を生成しています。
  D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\extensions.csproj の復元が 971.41 ms で完了しました。
  extensions -> D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850\bin\extensions.dll

ビルドに成功しました。
    0 個の警告
    0 エラー

経過時間 00:00:17.67


[INFO] Function extension installation done.
[INFO] Successfully built Azure Functions.
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:copy-resources (copy-resources) @ AzureFunctionsJava ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 03:07 min
[INFO] Finished at: 2018-09-17T21:28:15+09:00
[INFO] ------------------------------------------------------------------------

実行します。

mvn azure-functions:run
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< tech.kikutaro:AzureFunctionsJava >------------------
[INFO] Building Azure Java Functions 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- azure-functions-maven-plugin:1.0.0-beta-6:run (default-cli) @ AzureFunctionsJava ---
AI: INFO 17-09-2018 22:00, 1: Configuration file has been successfully found as resource
AI: INFO 17-09-2018 22:00, 1: Configuration file has been successfully found as resource
[INFO] Azure Function App's staging directory found at: D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850
[INFO] Azure Functions Core Tools found.

                  %%%%%%
                 %%%%%%
            @   %%%%%%    @
          @@   %%%%%%      @@
       @@@    %%%%%%%%%%%    @@@
     @@      %%%%%%%%%%        @@
       @@         %%%%       @@
         @@      %%%       @@
           @@    %%      @@
                %%
                %

Azure Functions Core Tools (2.0.1-beta.38)
Function Runtime Version: 2.0.12050.0
Skipping 'AzureWebJobsStorage' from local settings as it's already defined in current environment variables.
Skipping 'AzureWebJobsDashboard' from local settings as it's already defined in current environment variables.
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using 'C:\Users\kikuta\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest.
info: Host.Startup[0]
      Reading host configuration file 'D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850\host.json'info: Host.Startup[0]
      Host configuration file read:
      {
        "version": "2.0"
      }
[2018/09/17 13:00:43] Initializing Host.
[2018/09/17 13:00:43] Host initialization: ConsecutiveErrors=0, StartupCount=1
[2018/09/17 13:00:44] Starting JobHost
[2018/09/17 13:00:44] Starting Host (HostId=xxxxxxxxx-xxxxxxxx, InstanceId=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, Version=2.0.12050.0, ProcessId=11372, AppDomainId=1, Debug=False, FunctionsExtensionVersion=)
[2018/09/17 13:00:44] Starting language worker process:C:\Program Files\Java\jdk1.8.0_152\bin\java  -jar "C:\Users\kikuta\AppData\Roaming\npm\node_modules\azure-functions-core-tools\bin\workers\java\azure-functions-java-worker.jar" --host 127.0.0.1 --port 36887 --workerId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --requestId xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --grpcMaxMessageLength 134217728
[2018/09/17 13:00:44] C:\Program Files\Java\jdk1.8.0_152\bin\java process with Id=26080 started
[2018/09/17 13:00:44] Generating 1 job function(s)
[2018/09/17 13:00:44] Found the following functions:
[2018/09/17 13:00:44] Host.Functions.HttpTrigger-Java
[2018/09/17 13:00:44]
[2018/09/17 13:00:44] Host initialized (678ms)
[2018/09/17 13:00:44] Host started (695ms)
[2018/09/17 13:00:44] Job host started
Hosting environment: Production
Content root path: D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850
Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.
Listening on http://0.0.0.0:7071/
Hit CTRL-C to exit...

Http Functions:

        HttpTrigger-Java: http://localhost:7071/api/HttpTrigger-Java

[2018/09/17 13:00:45] Microsoft Azure Functions Java Runtime [build 1.1.0-beta9]
[2018/09/17 13:00:49] [INFO] {MessageHandler.handle}: Message generated by "StartStream.Builder"
[2018/09/17 13:00:49] Host lock lease acquired by instance ID '0000000000000000000000000xxxxxxx'.
[2018/09/17 13:00:57] Worker initialized
[2018/09/17 13:00:57] "HttpTrigger-Java" loaded (ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, Reflection: "D:\web\azure\AzureFunctionsJava\AzureFunctionsJava\target\azure-functions\azurefunctionsjava-20180917211315850\AzureFunctionsJava-1.0-SNAPSHOT.jar"::"tech.kikutaro.Function.run")

http://localhost:7071 」にアクセスすると以下表示されました。
2018-09-16_13h13_14.png

さらに「 http://localhost:7071/api/HttpTrigger-Java?name=kikutaro 」で以下の表示を確認しました。
2018-09-16_13h14_27.png

Microsoft Azureへデプロイ

ローカルで動作確認ができたので、最後にAzureへデプロイします。まずはログインから。

az login

デプロイします。

mvn azure-functions:deploy
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< tech.kikutaro:AzureFunctionsJava >------------------
[INFO] Building Azure Java Functions 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- azure-functions-maven-plugin:1.0.0-beta-6:deploy (default-cli) @ AzureFunctionsJava ---
AI: INFO 17-09-2018 22:07, 1: Configuration file has been successfully found as resource
AI: INFO 17-09-2018 22:07, 1: Configuration file has been successfully found as resource
[INFO] Authenticate with Azure CLI 2.0
[INFO] The specified function app does not exist. Creating a new function app...
[INFO] Successfully created the function app: azurefunctionsjava-20180917211315850
[INFO] Trying to deploy the function app...
[INFO] Successfully deployed the function app at https://azurefunctionsjava-20180917211315850.azurewebsites.net
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:59 min
[INFO] Finished at: 2018-09-17T22:09:03+09:00
[INFO] ------------------------------------------------------------------------

Azure Portalで確認するとMavenで指定した名前のリソースグループが作成されています。
2018-09-17_22h09_57.png

作成されたFunctionをクリックするとURLが確認できます。
2018-09-17_22h08_29.png

ローカルと同じように確認します。まずはトップURL。
2018-09-17_22h14_58.png

ローカルと同じ挙動です。
2018-09-17_22h14_25.png

思ってたより簡単でした。

kikutaro
デビュー当時から堀北真希さんを愛するエンジニアです。堀北さんの結婚を機に乃木坂46を愛するエンジニアに転身しました。Javaを中心としたエンプラ系システムの開発者でしたが、現在はSendGridのサポートエンジニアとして働いています。 http://kikutaro.tech/
http://kikutaro777.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした