Helidon Messaging with JMS

原文はこちら。
The original article was written by Daniek Kec (Java Developer, Oracle).
https://medium.com/helidon/helidon-messaging-with-jms-bca19fd99413

Reactive messaging with JMS connector

メッセージングシステムとの統合において、JMS APIは最も人気のあるソリューションの一つです。Helidon 2.2.0では、リアクティブメッセージングをJMSに接続するための直接のサポートが提供されているのも不思議ではありません。

HelidonとApache ActiveMQをJMS経由で接続してみましょう。設定は超簡単で、コネクタ自体に集中できます。

Apache ActiveMQ
http://activemq.apache.org/

まず、dockerでActiveMQを起動します。

docker run --name='activemq' -p 61616:61616 -p 8161:8161 rmohr/activemq

JMSサーバーの準備ができたら、Helidonで遊びましょう。

JMS Messaging with Helidon MP

Helidon MPを接続するには、MicroProfile Reactive Messagingの実装、HelidonのJMSメッセージコネクタ、そしてActiveMQクライアントライブラリが必要です。

MicroProfile Reactive Messaging Specification
https://download.eclipse.org/microprofile/microprofile-reactive-messaging-1.0/microprofile-reactive-messaging-spec.html

<dependency>
<groupId>io.helidon.microprofile.messaging</groupId>
<artifactId>helidon-microprofile-messaging</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.messaging.jms</groupId>
<artifactId>helidon-messaging-jms</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</dependency>
view raw mp-jms-pom.xml hosted with ❤ by GitHub

Dependencies needed for connecting ActiveMQ over JMS

Injecting ConnectionFactory

JMS接続の準備が最も簡単なのは、名前付き、アプリケーションスコープのbeanとしてConnectionFactoryを手作業で作成することです。

@Produces
@ApplicationScoped
@Named("active-mq-factory")
public ConnectionFactory connectionFactory() {
return new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
}

Creating connection factory as named bean

JMSコネクタの構成は、named-factoryプロパティを使って名前付きbeanを参照できます。

mp:
messaging:
connector:
helidon-jms:
named-factory: active-mq-factory
outgoing.to-jms:
connector: helidon-jms
destination: messaging-test-queue-1
type: queue
incoming.from-jms:
connector: helidon-jms
destination: messaging-test-queue-1
type: queue

Referencing connection factory injected as bean

構成が済んだら、メッセージの送受信ができます。

Consume:

@Incoming("from-jms")
@Acknowledgment(Acknowledgment.Strategy.MANUAL)
public CompletionStage<?> consumeJms(JmsMessage<String> msg) {
System.out.println("JMS says: " + msg.getPayload());
return msg.ack();
}

Publish:

@Outgoing("to-jms")
public PublisherBuilder<String> produceToJms() {
return ReactiveStreams.of("test1", "test2")
.map(s -> JmsMessage.builder(s)
.correlationId(UUID.randomUUID().toString())
.property("stringProp", "cool property")
.property("byteProp", 4)
.property("intProp", 5)
.onAck(() -> System.out.println("Acked!"))
.build());
}

Configuration with JNDI

JNDIを使ってConnectionFactoryをルックアップするようにすれば、構成だけでJMS接続をセットアップできます。JNDIの構成に必要なのは、jndi.jms-factoryキーを持つ接続ファクトリの名前と、初期ファクトリーのプロパティをenv-propertiesに指定するだけです。java.naming.factory.initialやjava.naming.provider.urlのような感じです。

mp.messaging:
connector:
helidon-jms:
jndi:
# Connection factory jndi
jms-factory: ConnectionFactory
# Initial context properties
env-properties:
java.naming:
factory.initial: org.apache.activemq.jndi.ActiveMQInitialContextFactory
provider.url: tcp://localhost:61616
incoming.from-jms:
connector: helidon-jms
destination: messaging-test-queue-1
type: queue
outgoing.to-jms:
connector: helidon-jms
destination: messaging-test-queue-1
type: queue
view raw jndi-conf.yaml hosted with ❤ by GitHub

Configuration with JNDI

その結果、自身で作成したbeanとしての接続ファクトリを注入した場合と同じになります。このソリューションの詳細は、Helidonリポジトリのexampleプロジェクトをお試しください。

Helidon Messaging with JMS Example
https://github.com/oracle/helidon/tree/master/examples/messaging/jms-websocket-mp

JMS Messaging with Helidon SE

Helidon SE MessagingはJMSコネクタを依存関係に持つので、必要なのはコネクタ自体の依存関係と、そして今回のサンプル用に、JMS ConnectionFactoryの実装を含むActiveMQクライアントの依存関係だけです。

<dependency>
<groupId>io.helidon.messaging.jms</groupId>
<artifactId>helidon-messaging-jms</artifactId>
</dependency>
<!-- JMS client implenting JMS api of your choice-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</dependency>

Dependencies needed for connecting ActiveMQ with Helidon SE

Helidon SE環境においては、基本的に接続ファクトリの管理方法には2種類(自身で作成した接続ファクトリを供給するか、JNDIを利用する)あります。

Custom ConnectionFactory

自身で作成した接続ファクトリを供給するのが、最も汎用性の高いアプローチです。複数の接続ファクトリを1個のコネクタで利用できるので、チャネル構成から接続ファクトリを参照するため、カスタム識別子を提供する必要があります。

// Manually define JMS connection factory
ActiveMQConnectionFactory connectionFactory =
new ActiveMQConnectionFactory("tcp://192.168.0.123:61616");
// Setup connector
JmsConnector seConn = JmsConnector.builder()
.connectionFactory("jms-con-1", connectionFactory)
.build();
// Prepare channels
Channel<String> toJms = Channel.<String>builder()
.name("to-jms")
.subscriberConfig(JmsConnector.configBuilder()
.queue("example_queue_1")
.namedFactory("jms-con-1")
.build())
.build();
Channel<String> fromJms = Channel.<String>builder()
.name("from-jms")
.publisherConfig(JmsConnector.configBuilder()
.queue("example_queue_1")
.namedFactory("jms-con-1")
.build())
.build();
// Prepare emitter for interaction with non-reactive code
Emitter<String> emitter = Emitter.create(toAq);
// Connect everything together
Messaging.builder()
.connector(seConn)
.emitter(emitter)
.listener(fromAq, s -> {
System.out.println("Message received: " + s);
})
.build()
.start();
// Manually send some messages
emitter.send("Hello");
emitter.send("world");
emitter.send("from");
emitter.send("Active");
emitter.send("MQ!");
// Don't forget to wait for messages to arrive asynchronously!

Complete example of sending and receiving JMS messages

1つのスニペットに全てが詰まっているのです。アブラカダブラ!✨魔法じゃないですよ。

ご覧のように、この例は全て自己完結型なので、タネも仕掛けもなく、Helidonの他の部分は必要ありません。実際には、この例をmainメソッドに置くだけで、そのまま動作します。

Configuration with JNDI

JNDIを使って接続ファクトリをルックアップすることもできます。

// Setup connector
JmsConnector seConn = JmsConnector.create();
// Prepare channels
Channel<String> toJms = Channel.<String>builder()
.name("to-jms")
.subscriberConfig(JmsConnector.configBuilder()
.queue("example_queue_1")
.jndiInitialFactory(ActiveMQInitialContextFactory.class)
.jndiProviderUrl("tcp://192.168.0.123:61616")
.build())
.build();

Looking up connection factory with JNDI

これは構成を直接供給して初めてより実用的に見えることでしょう。上のMPの例からJNDIルックアップを使ったyamlの設定を見てみましょう。configがyamlを理解できるようにするために、もう一つ依存関係が必要です。

<dependency>
    <groupId>io.helidon.config</groupId>
    <artifactId>helidon-config-yaml</artifactId>
</dependency>

MPの例で使った構成と全く同じことがわかります。

mp.messaging:
connector:
helidon-jms:
jndi:
# Connection factory jndi
jms-factory: ConnectionFactory
# Initial context properties
env-properties:
java.naming:
factory.initial: org.apache.activemq.jndi.ActiveMQInitialContextFactory
provider.url: tcp://localhost:61616
incoming.from-jms:
connector: helidon-jms
destination: messaging-test-queue-1
type: queue
outgoing.to-jms:
connector: helidon-jms
destination: messaging-test-queue-1
type: queue
view raw jndi-conf.yaml hosted with ❤ by GitHub

Same config as in the MP example above

ではSEのメッセージングで使ってみましょう。これは全く問題ありません。というのも、JMSコネクタがMPメッセージングの構成記法を両方のフレーバーで理解しているためです。

// Setup connector
JmsConnector seConn = JmsConnector.create();
// Prepare channels
Channel<String> toJms = Channel.create("to-jms");
Channel<String> fromJms = Channel.create("from-jms");
// Prepare emitter for interaction with non-reactive code
Emitter<String> emitter = Emitter.create(toJms);
// Connect everything together
Messaging.builder()
.config(Config.builder()
.sources(() -> FileConfigSource.builder()
.path(Paths.get("src/main/resources/application.yaml"))
.build()
)
.build()
)
.connector(seConn)
.emitter(emitter)
.listener(fromJms, s -> {
System.out.println("Message received: " + s);
})
.build()
.start();
// Manually send some messages
emitter.send("Hello");
emitter.send("world");
emitter.send("from");
emitter.send("Active");
emitter.send("MQ!");
// Don't forget to wait for messages to arrive asynchronously!

SE JMS connector with MP messaging config notation

Helidon SEにおけるJMSコネクタに関する詳細は、Helidonリポジトリのサンプルプロジェクトをお試しください。

Helidon Messaging with JMS Example
https://github.com/oracle/helidon/tree/master/examples/messaging/jms-websocket-se

HelidonのJMSコネクタが、リアクティブメッセージングを使った他のサービスへの統合の新たな扉を開きます。これらのサービスの中でも、Weblogic JMSとOracle AQは非常に興味深いものです。これらのサービスについては、次回の記事で詳しく紹介します。

HelidonのReactive Messagingについては以下のリソースをどうぞ。

Reactive JMS Connector (MP)
https://helidon.io/docs/v2/#/mp/reactivemessaging/05_jms
Reactive JMS Connector (SE)
https://helidon.io/docs/v2/#/se/reactivemessaging/05_jms
Helidon Messaging Examples
https://github.com/oracle/helidon/tree/master/examples/messaging

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中