8.5. サーバーへの接続
クライアントをサーバーに接続する場合は、適切なコネクターが必要です。これには 2 つの方法があります。サーバーに設定され、JNDI ルックアップから取得できる ConnectionFactory を使用することができます。または、ActiveMQ Artemis コア API を使用して、クライアント側で ConnectionFactory 全体を設定することもできます。
8.5.1. JMS 接続ファクトリー リンクのコピーリンクがクリップボードにコピーされました!
クライアントでは JNDI を使用して、サーバーへの接続を提供する ConnectionFactory オブジェクトをルックアップできます。接続ファクトリーでは、それぞれ以下の 3 つのタイプのコネクターを公開することができます。
remote-connector を参照する connection-factory は、リモートクライアントがサーバーからメッセージを送受信するために使用できます (connection-factory に適切なエクスポートエントリーがあることを前提とします)。remote-connector は、connection-factory の使用して接続先をクライアントに指示する socket-binding と関連付けられます。
in-vm-connector を参照する connection-factory は、ローカルクライアントよるローカルサーバーとのメッセージの送受信にに適しています。in-vm-connector は、複数のメッセージングサーバーを 1 つの JVM で実行できるため、connection-factory を使用して接続先をクライアントに指示する server-id と関連付けられます。
http-connector を参照する connection-factory は、HTTP ポートに接続してサーバーからメッセージを送受信してからメッセージングプロトコルにアップグレードするにあたり、リモートクライアントで使用するのに適しています。http-connector は、デフォルトで http という名前の HTTP ソケットを表す socket-binding に関連付けられています。
JMS 2.0 以降、デフォルトの JMS 接続ファクトリーは、JNDI 名 java:comp/DefaultJMSConnectionFactory で Java EE アプリケーションを利用できます。messaging-activemq サブシステムでは、このデフォルトの接続ファクトリーを提供するために使用される pooled-connection-factory を定義します。
以下は、JBoss EAP の full 設定プロファイルに含まれるデフォルトのコネクターおよび接続ファクトリーです。
<subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">
<server name="default">
[...]
<http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor" />
<http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput">
<param name="batch-delay" value="50"/>
</http-connector>
<in-vm-connector name="in-vm" server-id="0"/>
[...]
<connection-factory name="InVmConnectionFactory" connectors="in-vm" entries="java:/ConnectionFactory" />
<pooled-connection-factory name="activemq-ra" transaction="xa" connectors="in-vm" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory"/>
[...]
</server>
</subsystem>
ファクトリーの entries 属性では、ファクトリーが公開される JNDI 名を指定します。リモートクライアントに利用できるのは、java:jboss/exported 名前空間にバインドされた JNDI 名のみです。connection-factory が java:jboss/exported 名前空間にバインドされたエントリーを持っている場合、リモートクライアントは java:jboss/exported の後のテキストを使用して connection-factory をルックアップします。たとえば、RemoteConnectionFactory はデフォルトで java:jboss/exported/jms/RemoteConnectionFactory にバインドされています。これは、リモートクライアントが jms/RemoteConnectionFactory を使用してこの connection-factory をルックアップすることを意味します。pooled-connection-factory はリモートクライアントに適していないため、pooled-connection-factory では java:jboss/exported 名前空間内にエントリーがバインドされないようにする必要があります。
8.5.2. JNDI を使用したサーバーへの接続 リンクのコピーリンクがクリップボードにコピーされました!
クライアントがサーバーと同じ JVM 内に存在する場合は、InVmConnectionFactory が提供する in-vm コネクターを使用できます。以下は、standalone-full.xml などでみられる InvmConnectionFactory の典型的な設定方法です。
<connection-factory
name="InVmConnectionFactory"
entries="java:/ConnectionFactory"
connectors="in-vm" />
entries 属性の値に注意してください。InVmConnectionFactory を使用するクライアントは、以下の例のように、ルックアップ時に先頭の java:/ を省略します。
InitialContext ctx = new InitialContext();
ConnectionFactory cf = (ConnectionFactory)ctx.lookup("ConnectionFactory");
Connection connection = cf.createConnection();
リモートクライアントでは RemoteConnectionFactory を使用しますが、これは通常以下のような設定になります。
<connection-factory
name="RemoteConnectionFactory"
scheduled-thread-pool-max-size="10"
entries="java:jboss/exported/jms/RemoteConnectionFactory"
connectors="http-connector"/>
リモートクライアントでは entries の値の先頭の java:jboss/exported/ を無視し、以下のコードスニペットの例に従います。
final Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.wildfly.naming.client.WildFlyInitialContextFactory");
env.put(Context.PROVIDER_URL, "http-remoting://remotehost:8080");
InitialContext remotingCtx = new InitialContext(env);
ConnectionFactory cf = (ConnectionFactory) remotingCtx.lookup("jms/RemoteConnectionFactory");
PROVIDER_URL プロパティーの値と、クライアントの JBoss EAP http-remoting プロトコルの使用方法に注意してください。クライアントの org.wildfly.naming.client.WildFlyInitialContextFactory の使用方法にも注意してください。これはクライアントがこのクラスを持ち、クラスパスのどこかにクライアント JAR を包含するということを意味します。Maven プロジェクトでは、以下の依存関係を含めることで実現できます。
<dependencies>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-jms-client-bom</artifactId>
<type>pom</type>
</dependency>
</dependencies>
8.5.3. コア API を使用したサーバーへの接続 リンクのコピーリンクがクリップボードにコピーされました!
Core API を使用すると、JNDI ルックアップを使用せずにクライアント接続を行うことができます。Core API を使用するクライアントでは、JNDI ベースのクライアントと同様、クラスパスでクライアント JAR が必要になります。
ServerLocator
クライアントは ServerLocator インスタンスを使用して ClientSessionFactory インスタンスを作成します。名前が示すように、ServerLocator インスタンスはサーバーを検索し、そのサーバーへの接続を作成するために使用されます。
JMS では、JMS Connection Factory と同様に ServerLocator を考えてみましょう。
ServerLocator インスタンスは、ActiveMQClient ファクトリークラスを使用して作成されます。
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(InVMConnectorFactory.class.getName()));
ClientSessionFactory
クライアントは ClientSessionFactory を使用して ClientSession インスタンスを作成します。これは基本的にサーバーへの接続です。JMS 関係ではこれを JMS 接続と考えます。
ClientSessionFactory インスタンスは ServerLocator クラスを使用して作成されます。
ClientSessionFactory factory = locator.createClientSessionFactory();
ClientSession
クライアントは ClientSession を使用してメッセージの消費と生成を行い、トランザクションでメッセージをグループ化します。ClientSession インスタンスは、トランザクションセマンティクスと非トランザクションセマンティクスの両方をサポートし、JTA トランザクションの一部として、メッセージング操作を実行できるように XAResource インターフェイスも提供できます。
ClientSession インスタンスは ClientConsumers と ClientProducers をグループ化します。
ClientSession session = factory.createSession();
今説明したことを簡単な例で以下に示します。
ServerLocator locator = ActiveMQClient.createServerLocatorWithoutHA(
new TransportConfiguration( InVMConnectorFactory.class.getName()));
// In this simple example, we just use one session for both
// producing and consuming
ClientSessionFactory factory = locator.createClientSessionFactory();
ClientSession session = factory.createSession();
// A producer is associated with an address ...
ClientProducer producer = session.createProducer("example");
ClientMessage message = session.createMessage(true);
message.getBodyBuffer().writeString("Hello");
// We need a queue attached to the address ...
session.createQueue("example", "example", true);
// And a consumer attached to the queue ...
ClientConsumer consumer = session.createConsumer("example");
// Once we have a queue, we can send the message ...
producer.send(message);
// We need to start the session before we can -receive- messages ...
session.start();
ClientMessage msgReceived = consumer.receive();
System.out.println("message = " + msgReceived.getBodyBuffer().readString());
session.close();