これまでこのブログで取り上げてきた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に変更している。
<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」クラスに変更している。
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();
}
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」クラスに変更する。





