これまでこのブログで取り上げてきたAzure Functionsのサンプルプログラムでは、spring-cloud-function-dependenciesのバージョンを2.0.1.RELEASEとしてきたが、2021年4月13日現在の最新(2021年3月16日リリース)バージョンである3.1.2に変更することで、1つのAzure Functions内に複数のファンクションを含む場合にSpring Bootが初期化されることの不具合が解消できていることが分かった。
今回は、以前作成したサンプルプログラム内に含まれているspring-cloud-function-dependenciesのバージョンを最新(3.1.2)に変更してみたので、共有する。
なお、1つのAzure Functions内に複数のファンクションを含む場合にSpring Bootが初期化されることの不具合が解消できていることについては、以下のサイトを参照のこと。
https://github.com/spring-cloud/spring-cloud-function/issues/600
前提条件
下記記事の実装が完了していること。
作成したサンプルプログラム(Azure Functions側)の内容
作成したサンプルプログラム(Azure Functions側)の構成は以下の通り。なお、App Services側のソースコードと共通クラス格納用プロジェクトについては、修正していない。
なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。
pom.xmlの変更内容は以下の通りで、spring-cloud-function-dependenciesのバージョンを3.1.2に変更している。
1 2 3 4 5 6 7 8 9 10 11 | <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-function-dependencies</artifactId> <version>3.1.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> |
また、Handlerクラスの内容は以下の通りで、継承するクラスを「AzureSpringBootRequestHandler」クラスから「FunctionInvoker」クラスに変更している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | package com.example; import java.util.Optional; import org.springframework.cloud.function.adapter.azure.FunctionInvoker; import com.example.model.FileUploadParam; import com.example.model.FileUploadResult; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; 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.FunctionName; import com.microsoft.azure.functions.annotation.HttpTrigger; public class FileUploadHandler extends FunctionInvoker<FileUploadParam, FileUploadResult> { /** * HTTP要求に応じて、DemoAzureFunctionクラスのfileUploadメソッドを呼び出し、 * その戻り値をボディに設定したレスポンスを返す. * @param request リクエストオブジェクト * @param context コンテキストオブジェクト * @return レスポンスオブジェクト */ @FunctionName("fileUpload") public HttpResponseMessage execute( @HttpTrigger(name = "request" , methods = HttpMethod.POST, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request, ExecutionContext context) { // リクエストオブジェクトからパラメータ値を取得し、ファイルアップロード用Paramに設定する ObjectMapper mapper = new ObjectMapper(); String jsonParam = request.getBody().get(); jsonParam = jsonParam.replaceAll("\\[", "").replaceAll("\\]", ""); FileUploadParam fileUploadParam = new FileUploadParam(); try { fileUploadParam = mapper.readValue( jsonParam, new TypeReference<FileUploadParam>() { }); } catch (Exception ex) { throw new RuntimeException(ex); } // handleRequestメソッド内でDemoAzureFunctionクラスのfileUploadメソッドを呼び出し、 // その戻り値をボディに設定したレスポンスを、JSON形式で返す return request.createResponseBuilder(HttpStatus.OK) .body(handleRequest(fileUploadParam, context)) .header("Content-Type", "text/json").build(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | package com.example; import java.util.Optional; import org.springframework.cloud.function.adapter.azure.FunctionInvoker; import com.example.model.GetFileListParam; import com.example.model.GetFileListResult; 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.FunctionName; import com.microsoft.azure.functions.annotation.HttpTrigger; public class GetFileListHandler extends FunctionInvoker<GetFileListParam, GetFileListResult> { /** * HTTP要求に応じて、DemoAzureFunctionクラスのfileUploadメソッドを呼び出し、 * その戻り値をボディに設定したレスポンスを返す. * @param request リクエストオブジェクト * @param context コンテキストオブジェクト * @return レスポンスオブジェクト */ @FunctionName("getFileList") public HttpResponseMessage execute( @HttpTrigger(name = "request" , methods = HttpMethod.POST, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request, ExecutionContext context) { // handleRequestメソッド内でDemoAzureFunctionクラスのfileUploadメソッドを // 呼び出し、その戻り値をボディに設定したレスポンスを、JSON形式で返す return request.createResponseBuilder(HttpStatus.OK) .body(handleRequest(new GetFileListParam(), context)) .header("Content-Type", "text/json").build(); } } |
このように変更した背景としては、spring-cloud-function-dependenciesのバージョンを3.1.2に変更すると、以下のように「AzureSpringBootRequestHandler」クラスを使うべきでないという警告が出て、実際に「AzureSpringBootRequestHandler」クラスの警告を確認すると「FunctionInvoker」を使うように書かれているためである。
なお、修正したソースコード全体の内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/azure-function-dependencies-312/
サンプルプログラムの実行
サンプルプログラムの実行結果は、以下の記事の「作成したサンプルプログラムの実行結果」と同じになる。
要点まとめ
- spring-cloud-function-dependenciesのバージョンを3.1.2に変更すると、1つのAzure Functions内に複数のファンクションを含む場合にSpring Bootが初期化されることの不具合が解消できている。
- spring-cloud-function-dependenciesのバージョンを3.1.2に変更した場合は、Handlerクラスで継承するクラスを「AzureSpringBootRequestHandler」クラスから「FunctionInvoker」クラスに変更する。