MENU
Azure基本

Azure App ServiceやAzure Functionsで使うSpring Bootのバージョンを2.7.xに変更してみた

Spring Bootの各バージョン毎のサポート期間は、以下のサイトで確認できる。
https://spring.pleiades.io/projects/spring-boot/#support

SpringBootサポート期間

これまでこのブログで、Azure App ServiceやAzure Functionsで動作する、Spring Bootを利用したJavaアプリケーションをいくつか取り上げて来ているが、使用しているSpring Bootのバージョンが、既に有償サポートも終了した状態になっている。

今回は、Azure App ServiceやAzure Functionsで動作するSpring Bootのバージョンを、2025/8/24まで有償サポートが受けられるバージョン「2.7.x」に変更してみたので、そのサンプルプログラムを共有する。

前提条件

下記記事のサンプルプログラムをいずれも作成済であること。

(メインドメインが同一の)サブドメインをもつ複数のAzure App Service間でデータ共有してみた下記記事で、セッションデータをAzure Cache for Redisに格納するJavaアプリケーションを、複数のAzure App ...
Azure Function上でCSVファイルのデータをDBに書き込む処理をカスタマイズしてみたこれまでこのブログで、Spring BatchのChunkモデルを用いて、Blob上のCSVファイルをDBのテーブルに書き込む処理を作成...

作成したサンプルプログラムの内容(Azure App Service)

作成したサンプルプログラム(呼び出し元のApp Service)の構成は、以下の通り。なお、下記の赤枠は、前提条件のプログラムから変更したプログラムである。
サンプルプログラムの構成_appservice_1

また、作成したサンプルプログラム(呼び出し先のApp Service)の構成は、以下の通り。なお、下記の赤枠は、前提条件のプログラムから変更したプログラムである。
サンプルプログラムの構成_appservice_2

呼出元・呼出先のいずれも、pom.xmlの変更内容は以下の通りで、Spring Bootのバージョンを2.7.18に変更している。

<parent> 
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-parent</artifactId>  
    <version>2.7.18</version>  <!-- Spring Bootのバージョンを変更 --> 
    <relativePath/>  
    <!-- lookup parent from repository --> 
</parent>

その他のソースコードについては、前提条件のプログラムから特に変更していない。その内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/azure-spring-boot-27/demoAzureApp1/

https://github.com/purin-it/azure/tree/master/azure-spring-boot-27/demoAzureApp2/

サンプルプログラムの実行結果(Azure App Service)

サンプルプログラムの実行結果は、以下の記事の「サンプルプログラムの実行結果(ローカル環境)」「サンプルプログラムの実行結果(Azure環境)」と同じ内容となる。

(メインドメインが同一の)サブドメインをもつ複数のAzure App Service間でデータ共有してみた下記記事で、セッションデータをAzure Cache for Redisに格納するJavaアプリケーションを、複数のAzure App ...



作成したサンプルプログラムの内容(Azure Functions)

作成したサンプルプログラム(Azure Functions)の構成は、以下の通り。なお、下記の赤枠は、前提条件のプログラムから変更したプログラムである。
サンプルプログラムの構成_AzureFunctions

pom.xmlの内容は以下の通りで、Spring Bootのバージョンに加え、mybatis-spring-boot-starter・spring-cloud-function-dependencies・spring-boot-maven-pluginのバージョンも変更している。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>demoAzureFunc</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>Hello Spring Function on Azure</name>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.18</version>  <!-- Spring Bootのバージョンを変更 -->
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <azure.functions.maven.plugin.version>1.9.0</azure.functions.maven.plugin.version>

    <!-- customize those properties. The functionAppName should be unique across Azure -->
    <functionResourceGroup>azureAppDemo</functionResourceGroup>
    <functionAppName>azureFuncDemoApp</functionAppName>
    <functionAppServicePlan>ASP-azureAppDemo-8679</functionAppServicePlan>
    <functionPricingTier>B1</functionPricingTier>

    <functionAppRegion>japaneast</functionAppRegion>
    <stagingDirectory>${project.build.directory}/azure-functions/${functionAppName}</stagingDirectory>
    <start-class>com.example.DemoAzureFunction</start-class>
    <!-- Spring Bootのバージョン変更により下記バージョンを変更 -->
    <spring.boot.wrapper.version>1.0.31.RELEASE</spring.boot.wrapper.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-function-adapter-azure</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-function-web</artifactId>
      <scope>provided</scope>
    </dependency>
    <!-- lombokを利用するための設定 -->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>
    <!-- Spring Batchを利用するための設定 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>
    <!-- Azure Storageの設定 -->
    <dependency>
      <groupId>com.microsoft.azure</groupId>
      <artifactId>azure-storage</artifactId>
      <version>8.3.0</version>
    </dependency>
    <!-- Azure StorageでSASトークンを利用するための設定 -->
    <dependency>
      <groupId>com.azure</groupId>
      <artifactId>azure-storage-blob</artifactId>
      <version>12.10.0</version>
    </dependency>
    <!-- SQL Serverを利用するための設定 -->
    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
    </dependency>
    <!-- MyBatisを利用するための設定 -->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>2.3.2</version>  <!-- Spring Bootのバージョン変更によりバージョンを変更 -->
    </dependency>
    <!-- @ConfigurationPropertiesアノテーションを利用するための設定 -->
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-configuration-processor</artifactId>
    	<optional>true</optional>
    </dependency>
    <!-- Test -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-function-dependencies</artifactId>
        <version>3.2.12</version>  <!-- Spring Bootのバージョン変更によりバージョンを変更 -->
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>com.microsoft.azure</groupId>
          <artifactId>azure-functions-maven-plugin</artifactId>
          <version>${azure.functions.maven.plugin.version}</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-dependency-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
      </plugins>
    </pluginManagement>

    <plugins>
      <plugin>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-functions-maven-plugin</artifactId>
        <configuration>
          <resourceGroup>${functionResourceGroup}</resourceGroup>
          <appName>${functionAppName}</appName>
          <appServicePlanName>${functionAppServicePlan}</appServicePlanName>
          <region>${functionAppRegion}</region>
          <pricingTier>${functionPricingTier}</pricingTier>
          <runtime>
          	<os>Linux</os>
          	<javaVersion>8</javaVersion>
          </runtime>
          <appSettings>
            <!-- Run Azure Function from package file by default -->
            <property>
              <name>WEBSITE_RUN_FROM_PACKAGE</name>
              <value>1</value>
            </property>
            <property>
              <name>FUNCTIONS_EXTENSION_VERSION</name>
              <value>~3</value>
            </property>
            <property>
              <name>FUNCTIONS_WORKER_RUNTIME</name>
              <value>java</value>
            </property>
          </appSettings>
        </configuration>
        <executions>
          <execution>
            <id>package-functions</id>
            <goals>
              <goal>package</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>package</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <overwrite>true</overwrite>
              <outputDirectory>
                ${project.build.directory}/azure-functions/${functionAppName}
              </outputDirectory>
              <resources>
                <resource>
                  <directory>${project.basedir}/src/main/azure
                  </directory>
                  <includes>
                    <include>**</include>
                  </includes>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>copy-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${stagingDirectory}/lib</outputDirectory>
              <overWriteReleases>false</overWriteReleases>
              <overWriteSnapshots>false</overWriteSnapshots>
              <overWriteIfNewer>true</overWriteIfNewer>
              <includeScope>runtime</includeScope>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <!--Remove obj folder generated by .NET SDK in maven clean-->
      <plugin>
        <artifactId>maven-clean-plugin</artifactId>
        <configuration>
          <filesets>
            <fileset>
              <directory>obj</directory>
            </fileset>
          </filesets>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <dependencies>
          <dependency>
            <groupId>org.springframework.boot.experimental</groupId>
            <artifactId>spring-boot-thin-layout</artifactId>
            <version>${spring.boot.wrapper.version}</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <repository>
      <id>spring-snapshots</id>
      <name>Spring Snapshots</name>
      <url>https://repo.spring.io/plugins-snapshot</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <releases>
        <enabled>false</enabled>
      </releases>
    </repository>
    <repository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/plugins-milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
  <pluginRepositories>
    <pluginRepository>
      <id>spring-snapshots</id>
      <name>Spring Snapshots</name>
      <url>https://repo.spring.io/plugins-snapshot</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
      <releases>
        <enabled>false</enabled>
      </releases>
    </pluginRepository>
    <pluginRepository>
      <id>spring-milestones</id>
      <name>Spring Milestones</name>
      <url>https://repo.spring.io/plugins-milestone</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </pluginRepository>
  </pluginRepositories>
</project>

また、local.settings.jsonの内容は以下の通りで、FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBSの設定を追加している。

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=azureblobpurinit;AccountKey=(Azure Blob Storageのアクセスキー)",
    "FUNCTIONS_WORKER_RUNTIME": "java",
    "MAIN_CLASS":"com.example.DemoAzureFunction",
    "AzureWebJobsDashboard": "",
    "JAVA_HOME": "C:\\Program Files\\Java\\jdk1.8.0_271",
    "FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS": "true"
  }
}

同様に、Azure Functionsのアプリケーション設定にも、FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBSの設定を追加している。
AzureFunctions設定

なお、FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBSの設定を追加した理由は、以下のサイトを参照のこと。
https://github.com/Azure/azure-sdk-for-java/issues/22242

また、Azure Functions (Java 8 を実行するもののみ) の内部依存関係のバージョンは、ユーザー指定のバージョンよりも優先されるため、特に、Jackson・Netty・Reactorとのバージョンの競合が発生する。その問題を解決するには、FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS環境変数をtrueまたは1に変更する必要がある旨が、以下のサイトに記載されている。
https://learn.microsoft.com/ja-jp/azure/developer/java/sdk/troubleshooting-dependency-version-conflict

その他のソースコードについては、前提条件のプログラムから特に変更していない。その内容は、以下のサイトを参照のこと。
https://github.com/purin-it/azure/tree/master/azure-spring-boot-27/demoAzureFunc/

サンプルプログラムの実行結果(Azure Functions)

サンプルプログラムの実行結果は、以下の記事の「サンプルプログラムの実行結果」と同じ内容となる。

Azure Function上でCSVファイルのデータをDBに取り込むプログラムで楽観ロックを使ってみたこれまでこのブログで、Spring BatchのChunkモデルを用いて、Blob上のCSVファイルをDBのテーブルに書き込む処理を作成...
Azure Function上でバッチモードとそれ以外のデータソースを混在させてみたAzure Function上で楽観ロックを実装する場合、DB接続する際のSqlSessionを生成する際に、Spring Batchの...

要点まとめ

  • Azure Functionsで動作するJavaアプリケーションにおいて、Spring Bootのバージョンを上げる際は、mybatis-spring-boot-starter・spring-cloud-function-dependencies・spring-boot-maven-pluginのバージョンも変更が必要になる。
  • Azure FunctionsでJava8で動作させ、Jackson・Netty・Reactor等でバージョンの競合によりエラーが発生した場合は、FUNCTIONS_WORKER_JAVA_LOAD_APP_LIBS環境変数をtrueまたは1に変更する必要がある。