1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Java Quarkus Webサービスで Hello World する

Last updated at Posted at 2023-07-31

Java Quarkus Webサービスで Hello World する

こんにちは、@studio_meowtoon です。今回は、WSL の Ubuntu 22.04 で Java Quarkus Web アプリケーションを作成して Hello World を出力する方法を紹介します。
quarkus_on_ubuntu.png

目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

実現すること

ローカル環境の Ubuntu で、Java Quarkus Web サービスの JAR ファイル形式、また、ネイティブイメージ形式のアプリを起動します。

① JAR ファイル形式のアプリを起動

要素 概要
terminal ターミナル
Ubuntu OS
JVM Java 実行環境
app-runner.jar Java アプリケーション
netty Web サーバー

② ネイティブイメージ形式のアプリを起動

要素 概要
terminal ターミナル
Ubuntu OS
app-runner ネイティブイメージ アプリケーション
netty Web サーバー

技術トピック

Quarkus とは?

こちらを展開してご覧いただけます。

Quarkus (クォーカス)

Quarkus は、Java アプリケーションを高速で軽量なマイクロサービスやクラウドネイティブアプリケーションとして実行するためのフレームワークです。

キーワード 内容
オープンソース Quarkus はオープンソースであり、活発なコミュニティによってサポートされています。
クラウドネイティブ Kubernetes などのコンテナ環境との統合が簡単であり、クラウドネイティブアプリケーションの開発を容易にします。
マイクロサービス 小規模で疎結合なマイクロサービスアーキテクチャの開発に適しています。
軽量で高速 Quarkus は GraalVM によるネイティブイメージ生成をサポートし、高速で起動時間が短いアプリケーションを実現します。
低メモリ使用量 小さなコンテナサイズや省エネルギーな環境に適しています。

Java におけるネイティブイメージビルドとは?

こちらを展開してご覧いただけます。
キーワード 内容
ネイティブイメージビルド Java コードをネイティブマシンコードにコンパイルすることです。通常、Java コードは Java バイトコードと呼ばれる中間言語にコンパイルされ、Java 仮想マシン (JVM) で実行されます。しかし、ネイティブイメージビルドは、Java コードを JVM を介さずに直接実行可能なネイティブマシンコードに変換することで、より高速な実行速度より低いメモリ使用量を実現することができます。

ネイティブイメージビルドは、以下のようなニーズから求められています。

キーワード 内容
パフォーマンスの向上 Java は一般的に高水準のプログラミング言語であり、JVM によって実行されるため、実行速度が遅いとされることがあります。ネイティブイメージビルドにより、高速な実行速度を実現することができます。
メモリの最適化 JVM による Java コードの実行には、多くのメモリが必要となることがあります。ネイティブイメージビルドにより、より少ないメモリ使用量でプログラムを実行できるようになります。
ネイティブプログラムの統合 Java は、C言語や C++ などの他のプログラミング言語で書かれたネイティブプログラムと統合することができます。しかし、統合するためには、ネイティブコードが必要になります。ネイティブイメージビルドにより、これらのネイティブプログラムと Java コードをシームレスに統合することができます。

開発環境

  • Windows 11 Home 22H2 を使用しています。

WSL の Ubuntu を操作していきますので macOS の方も参考にして頂けます。

WSL (Microsoft Store アプリ版) ※ こちらの関連記事からインストール方法をご確認いただけます

> wsl --version
WSL バージョン: 1.0.3.0
カーネル バージョン: 5.15.79.1
WSLg バージョン: 1.0.47

Ubuntu ※ こちらの関連記事からインストール方法をご確認いただけます

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.1 LTS
Release:        22.04

Java JDK ※ こちらの関連記事からインストール方法をご確認いただけます

$ java -version
openjdk version "11.0.18" 2023-01-17
OpenJDK Runtime Environment (build 11.0.18+10-post-Ubuntu-0ubuntu122.04)
OpenJDK 64-Bit Server VM (build 11.0.18+10-post-Ubuntu-0ubuntu122.04, mixed mode, sharing)

Maven ※ こちらの関連記事からインストール方法をご確認いただけます

$ mvn -version
Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.18, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64

この記事では基本的に Ubuntu のターミナルで操作を行います。Vim を使用してコピペする方法を初めて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。

作成する Web アプリケーションの仕様

No エンドポイント HTTPメソッド MIME タイプ
1 /api/data GET application/json
説明を開きます。

/api/data というエンドポイントに対して HTTP GET リクエストを送信すると、JSON データがレスポンスされるシンプルな Web サービスを実装します。

Hello World を表示する手順

プロジェクトの作成

プロジェクトフォルダを作成します。
※ ~/tmp/hello-quarkus をプロジェクトフォルダとします。

$ mkdir -p ~/tmp/hello-quarkus
$ cd ~/tmp/hello-quarkus

リソースクラスの作成

リソースクラスを作成します。

$ mkdir -p src/main/java/com/example/quarkus
$ vim src/main/java/com/example/quarkus/HelloResource.java

ファイルの内容

HelloResource.java
package com.example.quarkus;

import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/api")
public class HelloResource {

    @GET
    @Path("/data")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> getData() {
        Map<String, String> map = Map.of("message", "Hello World!");
        return map;
    }
}

pom.xml の作成

pom.xml ファイルを作成します。

$ vim pom.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>hello-quarkus</artifactId>
    <version>1.0</version>
    <name>hello-quarkus</name>

    <properties>
        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
        <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
        <quarkus.platform.version>2.16.8.Final</quarkus.platform.version>
        <compiler-plugin.version>3.8.1</compiler-plugin.version>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>${quarkus.platform.artifact-id}</artifactId>
                <version>${quarkus.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>app</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>quarkus-maven-plugin</artifactId>
                <version>${quarkus.platform.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

ディレクトリ・ファイル構成

プロジェクトのファイル構成を表示してみます。

$ tree
.
├── pom.xml
└── src
    └── main
        └── java
            └── com
                └── example
                    └── quarkus
                        └── HelloResource.java

開発モードでアプリを起動

開発モードでアプリを起動します。
※ アプリを停止するときは ctrl + C を押します。

$ mvn quarkus:dev

出力

Listening for transport dt_socket at address: 5005
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2023-07-31 15:35:11,682 INFO  [io.quarkus] (Quarkus Main Thread) hello-quarkus 1.0 on JVM (powered by Quarkus 2.16.8.Final) started in 1.451s. Listening on: http://0.0.0.0:8080

2023-07-31 15:35:11,687 INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
2023-07-31 15:35:11,688 INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, resteasy-reactive, resteasy-reactive-jackson, smallrye-context-propagation, vertx]

--
Tests paused
Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>

ここまでの手順で、Quarkus アプリを開発モードで起動することができました。

アプリの動作確認

別ターミナルから curl コマンドで確認します。

$ curl -v http://localhost:8080/api/data -w '\n'

出力

*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /api/data HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-length: 22
< Content-Type: application/json;charset=UTF-8
<
* Connection #0 to host localhost left intact
{message=Hello World!}

ここまでの手順で、ターミナルに {"message":"Hello World!"} と表示され、JSON データを取得することが出来ました。

jar ファイルのビルド

アプリのビルド

Java アプリをビルドします。
※ target/app-runner.jar が作成されます。

$ mvn clean package \
    -Dquarkus.package.type=uber-jar

実行します。

$ java -jar target/app-runner.jar

ここまでの手順で、Quarkus アプリの JAR ファイルをビルド・起動することができました。

ネイティブイメージをビルド

pom.xml の修正

pom.xml ファイルを修正します。

$ vim pom.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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>hello-quarkus</artifactId>
    <version>1.0</version>
    <name>hello-quarkus</name>

    <properties>
        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
        <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
        <quarkus.platform.version>2.16.8.Final</quarkus.platform.version>
        <compiler-plugin.version>3.8.1</compiler-plugin.version>
        <surefire-plugin.version>3.0.0-M7</surefire-plugin.version>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-resteasy-reactive-jackson</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>${quarkus.platform.artifact-id}</artifactId>
                <version>${quarkus.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>app</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>quarkus-maven-plugin</artifactId>
                <version>${quarkus.platform.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>build</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>native</id>
            <activation>
                <property>
                    <name>native</name>
                </property>
            </activation>
            <properties>
                <quarkus.package.type>native</quarkus.package.type>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>${surefire-plugin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                                <configuration>
                                    <systemPropertyVariables>
                                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                                        <maven.home>${maven.home}</maven.home>
                                    </systemPropertyVariables>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

ファイルの内容 ※一部抜粋

pom.xml ※一部抜粋
</project>
    <!--省略-->
    <properties>
        <!--省略-->
        <surefire-plugin.version>3.0.0-M7</surefire-plugin.version>
        <!--省略-->
    </properties>
    <!--省略-->
    <profiles>
        <profile>
            <id>native</id>
            <activation>
                <property>
                    <name>native</name>
                </property>
            </activation>
            <properties>
                <quarkus.package.type>native</quarkus.package.type>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-failsafe-plugin</artifactId>
                        <version>${surefire-plugin.version}</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>integration-test</goal>
                                    <goal>verify</goal>
                                </goals>
                                <configuration>
                                    <systemPropertyVariables>
                                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                                        <maven.home>${maven.home}</maven.home>
                                    </systemPropertyVariables>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

Docker デーモンを起動します。

$ sudo service docker start
 * Starting Docker: docker    [ OK ]

Docker 環境をお持ちでない場合は、以下の関連記事から Docker Engine のインストール手順をご確認いただけます。

GraalVM はビルド時に Docker コンテナとして提供されます。

ネイティブイメージをビルドします。
※ target/app-runner ネイティブイメージが作成されます。

$ mvn clean package -Pnative

実行します。

$ ./target/app-runner

ここまでの手順で、Quarkus アプリの ネイティブイメージをビルド・起動することができました。

アプリ起動時間の比較

ファイル形式 実行ファイル 起動時間(秒)
JAR ファイル形式 app-runner.jar 0.642秒
ネイティブイメージ形式 app-runner 0.017秒

JVM で動作する Quarkus アプリの起動時間も十分速いですが、ネイティブイメージだと起動時間が非常に速いとわかりました。

まとめ

Ubuntu に構築したシンプルな Java 開発環境で、Java Quarkus Web サービスを実行することができました。

実際の業務での Quarkus の使用ケースでは、構成ファイルなどが追加されるため、ここで示したようなシンプルな構成とは異なる場合があります。しかしながら、最小構成の例を学ぶことで、Quarkus がどのような構成が必要なのかを理解することができます。

どうでしたか? WSL Ubuntu で、Java Quarkus Web アプリケーション開発環境を手軽に構築することができます。ぜひお試しください。今後も Java の開発環境などを紹介していきますので、ぜひお楽しみにしてください。

推奨コンテンツ

関連記事

Java JAX-RS

Java Spring Boot

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?