JMSの使用
このガイドでは、QuarkusアプリケーションがApache Qpid JMS AMQPクライアント、またはApache ActiveMQ Artemis JMSクライアントを介してJMSメッセージングを使用する方法を説明します。
この技術は、previewと考えられています。 preview では、下位互換性やエコシステムでの存在は保証されていません。具体的な改善には設定や API の変更が必要になるかもしれませんが、 stable になるための計画は現在進行中です。フィードバックは メーリングリスト や GitHub の課題管理 で受け付けています。 とりうるステータスの完全なリストについては、 FAQの項目 を参照してください。 |
前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
-
実行中のArtemisサーバー、またはDockerでの起動
アーキテクチャ
このガイドでは、1つのコンポーネントで(ランダムな)価格を生成することにしています。これらの価格は、JMSクライアントを使用してキュー( prices
)に書き込まれます。別のコンポーネントは prices
のキューから読み出し、最新の価格を保存します。データは、Jakarta RESTリソースからフェッチボタンを使ってブラウザから取得することができます。
このガイドでは、以下のようにApache Qpid JMS AMQPクライアントを使用することもできます。 あるいは、Apache ActiveMQ Artemis JMSクライアントを使用して、後述のように いくつかの異なる設定を行うこともできます。
Qpid JMS - AMQP
以下の詳細な手順では、 Quarkus Qpid JMSエクステンション を使用して Apache Qpid JMS クライアントを使用します。Qpid JMSは、ワイヤプロトコルとしてAMQP 1.0 ISO標準を使用しているため、ActiveMQ Artemis、ActiveMQ 5、Qpid Broker-J、Qpid Dispatchルーター、Azure Service Busなど、さまざまなAMQP 1.0サーバーやサービスで使用することができます。
ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。ただし、完成した例にそのまま進んでも構いません。
Git リポジトリをクローンします。 git clone https://github.com/amqphub/quarkus-qpid-jms-quickstart.git
または アーカイブ をダウンロードします。
Mavenプロジェクトの作成
まず、新しいプロジェクトが必要です。以下のコマンドで新規プロジェクトを作成します:
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=jms-quickstart"
このコマンドは、quarkus-qpid-jmsエクステンションをインポートした新しいプロジェクトを生成します:
<dependency>
<groupId>org.amqphub.quarkus</groupId>
<artifactId>quarkus-qpid-jms</artifactId>
</dependency>
implementation("org.amqphub.quarkus:quarkus-qpid-jms")
ブローカーの開始
次に、AMQPブローカーが必要です。この場合はActiveMQ Artemisサーバーを使用します。 Apache ArtemisのWebサイト の手順に従うか、 ArtemisCloud コンテナイメージを使用し、docker経由でブローカーを起動します:
docker run -it --rm -p 8161:8161 -p 61616:61616 -p 5672:5672 -e AMQ_USER=quarkus -e AMQ_PASSWORD=quarkus quay.io/artemiscloud/activemq-artemis-broker:1.0.25
価格のプロデューサー
以下の内容の src/main/java/org/acme/jms/PriceProducer.java
ファイルを作成します:
package org.acme.jms;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSContext;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
/**
* A bean producing random prices every 5 seconds and sending them to the prices JMS queue.
*/
@ApplicationScoped
public class PriceProducer implements Runnable {
@Inject
ConnectionFactory connectionFactory;
private final Random random = new Random();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
void onStart(@Observes StartupEvent ev) {
scheduler.scheduleWithFixedDelay(this, 0L, 5L, TimeUnit.SECONDS);
}
void onStop(@Observes ShutdownEvent ev) {
scheduler.shutdown();
}
@Override
public void run() {
try (JMSContext context = connectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)) {
context.createProducer().send(context.createQueue("prices"), Integer.toString(random.nextInt(100)));
}
}
}
価格のコンシューマー
価格のコンシューマーはJMSから価格を読み取り、最後の1つを保存します。以下の内容で src/main/java/org/acme/jms/PriceConsumer.java
ファイルを作成します。
package org.acme.jms;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.inject.Inject;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSConsumer;
import jakarta.jms.JMSContext;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
/**
* A bean consuming prices from the JMS queue.
*/
@ApplicationScoped
public class PriceConsumer implements Runnable {
@Inject
ConnectionFactory connectionFactory;
private final ExecutorService scheduler = Executors.newSingleThreadExecutor();
private volatile String lastPrice;
public String getLastPrice() {
return lastPrice;
}
void onStart(@Observes StartupEvent ev) {
scheduler.submit(this);
}
void onStop(@Observes ShutdownEvent ev) {
scheduler.shutdown();
}
@Override
public void run() {
try (JMSContext context = connectionFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)) {
JMSConsumer consumer = context.createConsumer(context.createQueue("prices"));
while (true) {
Message message = consumer.receive();
if (message == null) return;
lastPrice = message.getBody(String.class);
}
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
}
価格のリソース
最後に、最後の価格を表示するための簡単なJakarta RESTリソースを作成しましょう。以下の内容で src/main/java/org/acme/jms/PriceResource.java
ファイルを作成します:
package org.acme.jms;
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;
/**
* A simple resource showing the last price.
*/
@Path("/prices")
public class PriceResource {
@Inject
PriceConsumer consumer;
@GET
@Path("last")
@Produces(MediaType.TEXT_PLAIN)
public String last() {
return consumer.getLastPrice();
}
}
HTMLページ
最後に、変換された価格をSSEを使って読み込むHTMLページです。
以下の内容の src/main/resources/META-INF/resources/prices.html
ファイルを作成します :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Prices</title>
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly.min.css">
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly-additions.min.css">
</head>
<body>
<div class="container">
<h2>Last price</h2>
<div class="row">
<p class="col-md-12"><button id="fetch">Fetch</button>The last price is <strong><span id="content">N/A</span> €</strong>.</p>
</div>
</div>
</body>
<script>
document.getElementById("fetch").addEventListener("click", function() {
fetch("/prices/last").then(function (response) {
response.text().then(function (text) {
document.getElementById("content").textContent = text;
})
})
})
</script>
</html>
特筆すべきものは何もありません。フェッチするたびにページが更新されます。
Qpid JMSのプロパティーの設定
ConnectionFactoryを注入する際にエクステンションで使用するQpid JMSプロパティーを設定する必要があります。
これは、 src/main/resources/application.properties
ファイルで行います。
# Configures the Qpid JMS properties.
quarkus.qpid-jms.url=amqp://localhost:5672
quarkus.qpid-jms.username=quarkus
quarkus.qpid-jms.password=quarkus
設定の詳細については、 Quarkus Qpid JMS のドキュメントを参照してください。
実行
手順に従うことで、Artemis サーバーを起動できます。あとは、アプリケーションを使用して実行するだけです。
quarkus dev
./mvnw quarkus:dev
./gradlew --console=plain quarkusDev
ブラウザーで http://localhost:8080/prices.html
を開いてください。
ネイティブ実行
以下でネイティブ実行可能ファイルをビルドすることができます:
quarkus build --native
./mvnw install -Dnative
./gradlew build -Dquarkus.native.enabled=true
あるいは、GraalVMをインストールしていない場合は、代わりにDockerを使ってネイティブ実行可能ファイルをビルドすることもできます:
quarkus build --native --no-tests -Dquarkus.native.container-build=true
# The --no-tests flag is required only on Windows and macOS.
./mvnw install -Dnative -DskipTests -Dquarkus.native.container-build=true
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.native.container-build=true
次に、以下を実行してください:
./target/jms-quickstart-1.0.0-SNAPSHOT-runner
ブラウザーで http://localhost:8080/prices.html
を開いてください。
Artemis JMS
上記の手順ではQpid JMS AMQPクライアントを使用した場合について説明しましたが、このガイドはArtemis JMSクライアントでも使用できます。個々のステップの多くは、 上記Qpid JMSの詳細 と全く同じです。 個々のコンポーネントコードも同じです。 唯一の違いは、初期プロジェクト作成の依存関係と、使用する設定プロパティです。 これらの変更点の詳細を以下に示しますので、上記のシーケンス中の同等のステップに置き換えてください。
ソリューション
完成した例に進むことができます。
Gitレポジトリをクローンする: git clone https://github.com/quarkusio/quarkus-quickstarts.git
か、 アーカイブ をダウンロードします。
Artemis JMS ソリューションは jms-quickstart
ディレクトリ にあります。
Mavenプロジェクトの作成
以下のコマンドで新規プロジェクトを作成します:
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\
を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-D
パラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=jms-quickstart"
これにより quarkus-artemis-jmsエクステンションをインポートした新しいプロジェクトが作成されます:
<dependency>
<groupId>io.quarkiverse.artemis</groupId>
<artifactId>quarkus-artemis-jms</artifactId>
</dependency>
implementation("io.quarkiverse.artemis:quarkus-artemis-jms")
プロジェクトが作成されたら、上記の詳細手順の ブローカーの開始 から再開し、application.properties
ファイルの設定まで進め、代わりに以下のArtemisの設定を使用します。
Artemisのプロパティーの設定
Artemis の接続プロパティーを設定する必要があります。これは src/main/resources/application.properties
ファイルで行います。
# Configures the Artemis properties.
quarkus.artemis.url=tcp://localhost:61616
quarkus.artemis.username=quarkus
quarkus.artemis.password=quarkus
Artemisのプロパティーを設定した状態で、 実行 から上記の手順を再開することができます。
設定リファレンス
To know more about how to configure the Artemis JMS client, have a look at the documentation of the extension.