JMS でメッセージング

このガイドでは、JMS ブローカーを使用してメッセージをパブリッシュおよびサブスクライブするプロセスを順を追って説明します。

構築するもの

Spring の JmsTemplate を使用して単一のメッセージを投稿し、マネージド Bean の @JmsListener アノテーション付きメソッドでそのメッセージをサブスクライブするアプリケーションを構築します。

必要なもの

本ガイドの完成までの流れ

ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。

最初から始めるには、Spring Initializr から開始に進みます。

基本をスキップするには、次の手順を実行します。

完了したときは、gs-messaging-jms/complete のコードに対して結果を確認できます。

Spring Initializr から開始

IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。

プロジェクトを手動で初期化するには:

  1. IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。

  2. Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。

  3. 依存関係をクリックして、Spring は Apache ActiveMQ アルテミスを選択します。

  4. 生成をクリックします。

  5. 結果として得られる ZIP ファイルをダウンロードします。これは、選択した内容で構成されたアプリケーションのアーカイブです。

Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。
プロジェクトを Github からフォークして、IDE または他のエディターで開くこともできます。

メッセージレシーバーを作成する

Spring は、任意の POJO(Plain Old Java Object)にメッセージを公開する手段を提供します。

このガイドでは、JMS メッセージブローカーを介してメッセージを送信する方法について説明します。まず、メールメッセージの詳細を具体化した単純な POJO を作成します。メールメッセージは送信しておりませんのでご注意ください。メッセージで何を送信するかについて、ある場所から別の場所に詳細を送信します。

src/main/java/hello/Email.java

package hello;

public class Email {

  private String to;
  private String body;

  public Email() {
  }

  public Email(String to, String body) {
    this.to = to;
    this.body = body;
  }

  public String getTo() {
    return to;
  }

  public void setTo(String to) {
    this.to = to;
  }

  public String getBody() {
    return body;
  }

  public void setBody(String body) {
    this.body = body;
  }

  @Override
  public String toString() {
    return String.format("Email{to=%s, body=%s}", getTo(), getBody());
  }

}

この POJO は非常に単純で、2 つのフィールド(to と body)と、推定される getter および setter のセットが含まれています。

ここから、メッセージレシーバーを定義できます。

src/main/java/hello/Receiver.java

package hello;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class Receiver {

  @JmsListener(destination = "mailbox", containerFactory = "myFactory")
  public void receiveMessage(Email email) {
    System.out.println("Received <" + email + ">");
  }

}

Receiver は、メッセージ駆動型 POJO とも呼ばれます。コードが示すように、特定のインターフェースを実装したり、メソッドに特定の名前を付けたりする必要はありません。その上、メソッドは柔軟な署名を持っているかもしれません。特に、このクラスには JMSAPI のインポートがないことに注意してください。

JmsListener アノテーションは、このメソッドがリッスンする必要がある Destination の名前と、基になるメッセージリスナーコンテナーを作成するために使用する JmsListenerContainerFactory への参照を定義します。厳密に言えば、Spring Boot は必要に応じてデフォルトのファクトリを登録するため、コンテナーの構築方法をカスタマイズする必要がない限り、この最後の属性は必要ありません。

リファレンスドキュメントでは、これについて詳しく説明しています。

Spring を使用した JMS メッセージの送受信

次に、送信者と受信者を接続します。

src/main/java/hello/Application.java

package hello;

import jakarta.jms.ConnectionFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
import org.springframework.jms.support.converter.MessageConverter;
import org.springframework.jms.support.converter.MessageType;

@SpringBootApplication
@EnableJms
public class Application {

  @Bean
  public JmsListenerContainerFactory<?> myFactory(ConnectionFactory connectionFactory,
                          DefaultJmsListenerContainerFactoryConfigurer configurer) {
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    // This provides all auto-configured defaults to this factory, including the message converter
    configurer.configure(factory, connectionFactory);
    // You could still override some settings if necessary.
    return factory;
  }

  @Bean // Serialize message content to json using TextMessage
  public MessageConverter jacksonJmsMessageConverter() {
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("_type");
    return converter;
  }

  public static void main(String[] args) {
    // Launch the application
    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

    JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);

    // Send a message with a POJO - the template reuse the message converter
    System.out.println("Sending an email message.");
    jmsTemplate.convertAndSend("mailbox", new Email("[email protected] (英語)  ", "Hello"));
  }

}

@SpringBootApplication は、次のすべてを追加する便利なアノテーションです。

  • @Configuration: アプリケーションコンテキストの Bean 定義のソースとしてクラスにタグを付けます。

  • @EnableAutoConfiguration: クラスパス設定、他の Bean、さまざまなプロパティ設定に基づいて Bean の追加を開始するよう Spring Boot に指示します。例: spring-webmvc がクラスパスにある場合、このアノテーションはアプリケーションに Web アプリケーションとしてフラグを立て、DispatcherServlet のセットアップなどの主要な動作をアクティブにします。

  • @ComponentScan: Spring に、hello パッケージ内の他のコンポーネント、構成、サービスを探して、コントローラーを検出させるように指示します。

main() メソッドは、Spring Boot の SpringApplication.run() メソッドを使用してアプリケーションを起動します。XML が 1 行もないことに気付きましたか? web.xml ファイルもありません。この Web アプリケーションは 100% 純粋な Java であり、接続機能やインフラストラクチャの構成に対処する必要はありませんでした。

明確にするために、受信者の JmsListener アノテーションで参照される myFactory Bean も定義しました。Spring Boot によって提供される DefaultJmsListenerContainerFactoryConfigurer インフラストラクチャを使用するため、その JmsMessageListenerContainer は Spring Boot がデフォルトで作成するものと同一です。

デフォルトの MessageConverter は基本型 ( String、Map、Serializable など) のみを変換でき、Email は意図的に Serializable ではありません。Jackson を使用して、コンテンツをテキスト形式で JSON に直列化します (つまり、TextMessage として)。Spring Boot は MessageConverter の存在を検出し、それをデフォルトの JmsTemplate と DefaultJmsListenerContainerFactoryConfigurer によって作成された JmsListenerContainerFactory の両方に関連付けます。JSON コンバーターには、次の依存関係が必要です: org.springframework.boot:spring-boot-starter-json。

JmsTemplate を使用すると、JMS 宛先にメッセージを簡単に送信できます。main ランナー方式では、起動後、jmsTemplate を使用して Email POJO を送信できます。カスタム MessageConverter は自動的に関連付けられているため、JSON ドキュメントは TextMessage でのみ生成されます。

定義されていない 2 つの Bean は、JmsTemplate と ConnectionFactory です。これらは、Spring Boot によって自動的に作成されます。Spring Boot は、JMS インフラストラクチャが使用可能な場合、つまり @EnableJms を追加する必要がない場合、@JmsListener アノテーション付きメソッドも自動的に検出します。

デフォルトでは、Spring Boot はローカルマシン上で実行されている artemis ブローカーへの接続を試行します。次の構成プロパティを追加してブローカーを埋め込むこともできます。

spring.artemis.mode=embedded

org.apache.activemq:artemis-jakarta-server への依存関係も追加する必要があります。

デフォルトでは、Spring Boot は、pubSubDomain を false に設定することでキューに送信するように構成された JmsTemplate を作成します。JmsMessageListenerContainer も同じ方法で構成されます。オーバーライドするには、Spring Boot のプロパティ設定 (application.properties 内または環境変数の設定) を通じて spring.jms.pub-sub-domain=true を設定します。次に、受信コンテナーが同じ設定になっていることを確認します。

Spring の JmsTemplate は、receive メソッドを介して直接メッセージを受信できますが、同期的にのみ機能するため、ブロックされます。そのため、キャッシュベースの接続ファクトリで DefaultMessageListenerContainer などのリスナーコンテナーを使用することをお勧めします。これにより、メッセージを非同期で最大の接続効率で消費できます。

実行可能 JAR を構築する

コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。

Gradle を使用する場合、./gradlew bootRun を使用してアプリケーションを実行できます。または、次のように、./gradlew build を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。

java -jar build/libs/gs-messaging-jms-0.0.1-SNAPSHOT.jar

Maven を使用する場合、./mvnw spring-boot:run を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package で JAR ファイルをビルドしてから、JAR ファイルを実行できます。

java -jar target/gs-messaging-jms-0.0.1-SNAPSHOT.jar

実行すると、すべてのログに埋もれて、次のメッセージが表示されます。

Sending an email message.
Received <Email{[email protected] (英語)  , body=Hello}>

要約

おめでとう! JMS ベースのメッセージの発行者とコンシューマーを開発しました。

新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語) 。

すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の帰属表示、NoDerivatives クリエイティブコモンズライセンス (英語) でリリースされています。

コードを入手する