バージョンレスフィーチャーを使ってOpen Libertyのフィーチャーを簡単に指定する

# What's？

Open Libertyを使う時は、使用するフィーチャーを以下のように指定します。

```xml
    <featureManager>
        <feature>restfulWS-3.1</feature>
        <feature>jsonb-3.0</feature>
        <feature>mpOpenAPI-3.1</feature>
    </featureManager>
```

これはこれで必要なフィーチャーだけ絞り込んでランタイムを構成できるので便利なのですが、使用するAPI（Jakarta EE 10、MicroProfile 6.0など）で使用するフィーチャーのバージョンを調べて設定しないといけないのでやや面倒だったりします。

なのですが、`featureManager`に`platform`（バージョンレスフィーチャー）を使うことでこのあたりを簡単に設定できるようになっていたみたいなので、試してみました。

https://openliberty.io/blog/2024/08/13/24.0.0.8.html

# バージョンレスフィーチャー

このブログ記事に書かれている内容がすべてなのですが、

https://openliberty.io/blog/2024/08/13/24.0.0.8.html

以下のようにバージョンレスフィーチャー（`platform`）を指定することで使用する個々のフィーチャーのバージョンを書かなくてよくなります。

Java EE 8の場合。

```xml
    <!-- Enable features -->
    <featureManager>
        <platform>javaee-8.0</platform>
        <feature>servlet</feature>
        <feature>jpa</feature>
        <feature>jaxrs</feature>
    </featureManager>
```

MicroProfile 5.0の場合。

```xml
    <!-- Enable features -->
    <featureManager>
        <platform>microProfile-5.0</platform>
        <feature>mpHealth</feature>
        <feature>mpMetrics</feature>
    </featureManager>
```

バージョンレスフィーチャーのリファレンスはこちら。

https://openliberty.io/docs/25.0.0.3/reference/feature/versionless-features.html

バージョンレスフィーチャーは全部で3つあり、最大2つを指定できます。

- https://openliberty.io/docs/25.0.0.3/reference/platform/JavaEE.html
- https://openliberty.io/docs/25.0.0.3/reference/platform/JakartaEE.html
- https://openliberty.io/docs/25.0.0.3/reference/platform/MicroProfile.html

3つというのはJava EE、Jakarta EE、MicroProfileです。

この中から、Java EEとJakarta EEのどちらかひとつ、そしてMicroProfileを指定できます。これで最大2つです。

簡単に確認してみます。

# 環境

今回の環境はこちらです。

```powershell
PS > java --version
openjdk 21.0.6 2025-01-21 LTS
OpenJDK Runtime Environment Temurin-21.0.6+7 (build 21.0.6+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.6+7 (build 21.0.6+7-LTS, mixed mode, sharing)
PS > mvn --version
Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)
Maven home: C:\Users\user\AppData\Local\mise\installs\maven\3.9.9
Java version: 21.0.6, vendor: Eclipse Adoptium, runtime: C:\Users\user\AppData\Local\mise\installs\java\temurin-21.0.6+7.0.LTS
Default locale: ja_JP, platform encoding: UTF-8
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
```

# 確認してみる

Jakarta RESTful Web ServicesとMicroProfile Configを使った簡単なアプリケーションを作成してみます。

この時、`server.xml`にバージョンレスフィーチャーを使います。

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8" ?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo</groupId>
    <artifactId>platform-version-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>10.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.eclipse.microprofile</groupId>
            <artifactId>microprofile</artifactId>
            <version>7.0</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>ROOT</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.3.2</version>
                </plugin>
                <plugin>
                    <groupId>io.openliberty.tools</groupId>
                    <artifactId>liberty-maven-plugin</artifactId>
                    <version>3.11.3</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>io.openliberty.tools</groupId>
                <artifactId>liberty-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
```

```java:src\main\java\com\demo\rest\MessageResource.java
package com.demo.rest;

import java.util.Map;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@Path("/message")
public class MessageResource {
    @ConfigProperty(name = "app.message")
    @Inject
    private String message;

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> get() {
        return Map.of("message", message);
    }
}
```

```xml:src\main\liberty\config\server.xml
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <platform>jakartaee-10.0</platform>
        <platform>microProfile-7.0</platform>
        <feature>restfulWS</feature>
        <feature>jsonb</feature>
        <feature>mpConfig</feature>
    </featureManager>

    <!-- This template enables security. To get the full use of all the capabilities, a keystore and user registry are required. -->

    <!-- For the keystore, default keys are generated and stored in a keystore. To provide the keystore password, generate an
        encoded password using bin/securityUtility encode and add it below in the password attribute of the keyStore element.
        Then uncomment the keyStore element. -->
    <!--
    <keyStore password=""/>
    -->

    <!--For a user registry configuration, configure your user registry. For example, configure a basic user registry using the
        basicRegistry element. Specify your own user name below in the name attribute of the user element. For the password,
        generate an encoded password using bin/securityUtility encode and add it in the password attribute of the user element.
        Then uncomment the user element. -->
    <basicRegistry id="basic" realm="BasicRealm">
        <!--
        <user name="yourUserName" password="" />
        -->
    </basicRegistry>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443" />

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

    <!-- Configures the application on a specified context root -->
    <webApplication contextRoot="/" location="ROOT.war" />

    <!-- Default SSL configuration enables trust for default certificates from the Java runtime -->
    <ssl id="defaultSSLConfig" trustDefaultCerts="true" />
</server>
```

今回のポイントはここですね。

```xml
    <!-- Enable features -->
    <featureManager>
        <platform>jakartaee-10.0</platform>
        <platform>microProfile-7.0</platform>
        <feature>restfulWS</feature>
        <feature>jsonb</feature>
        <feature>mpConfig</feature>
    </featureManager>
```

バージョンレスフィーチャーとしてJakarta EE 10、MicroProfile 7.0を指定しています。

使用する他のフィーチャーはバージョンを指定しません。

動作確認してみます。

起動。

```powershell
PS > mvn liberty:dev
```

Open Libertyに組み込まれるフィーチャーの表示はこんな感じになります。

```powershell
[INFO] Resolving features: [jsonb, restfulws, mpconfig] using platforms: [microprofile-7.0, jakartaee-10.0]
```

確認。

```powershell
PS > (curl http://localhost:9080/message).Content
{"message":"Hello World"}
```

よさそうですね。

バージョン指定を省略できるのは便利なので、使っていこうと思います。