web-dev-qa-db-ja.com

JMSのSpring構成(Websphere MQ-SSL、Tomcat、JNDI、非IBM JRE)

背景:メッセージングにWebsphere MQを使用する比較的古いアプリケーションがあります。 WAS(Websphere Application Server)上で実行され、MDB(メッセージ駆動型Bean)を使用します。 Spring Integration-JMS を使用して、すべてのMDBを正常に置き換えることができました。次のステップは、非IBM JREを使用して他のサーブレットコンテナーで実行できるようにWASから移植できるかどうかを確認することです(Apache Tomcatを試しています)。 SSLを使用してチャネルを保護することが要件であることに注意してください。 JNDIの使用を好みます。

終了目標:アプリケーションサーバー(WAS)およびメッセージング(MQ)などの他のインフラストラクチャからアプリケーションを分離する。しかし、これをWASからTomcatに取り込むことが最初のステップです。次は、メッセージングインフラストラクチャをよりスケーラブルなものに更新するタスクです。これにより、アプリを過度に中断することなく、アプリが依存するインフラストラクチャの個々のコンポーネント(アプリサーバー、メッセージングレイヤー、データストア)を1つずつ更新できます。

質問:さて、私の挑戦は、Websphere MQにアクセスできるTomcatでJNDIリソースを定義することです。 context.xmlファイルで次のように定義した非SSLチャネルを使用して、これについていくつかの進歩を遂げました。

<Resource
   name="jms/qcf_sandbox"
   auth="Container"
   type="com.ibm.mq.jms.MQQueueConnectionFactory"
   factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
   description="JMS Queue Connection Factory for sending messages"
   Host="localhost"
   PORT="1414"
   CHAN="CHANNEL_SANDBOX"
   TRAN="1"
   QMGR="QM_SANDBOX"/>
<Resource
   name="jms/SandboxQ"
   auth="Container"
   type="com.ibm.mq.jms.MQQueue"
   factory="com.ibm.mq.jms.MQQueueFactory"
   description="JMS Queue"
   QU="SANDBOX_Q"/>

次のステップは、これをSSLチャネルで動作させることです。キーストアのセットアップ(kdbファイルと証明書の生成と交換)、QMでのSSLチャネルの構成などに関連する部分を理解しています。すべてがすでに機能しています。 Tomcatでキーストア、暗号スイートなどを使用するにはどうすればよいですか?ポインタまたは実例は素晴らしいでしょう!

注:現在、Spring Integration 4.2、Websphere MQ v8、Tomcat v9を使用しています。

最初にJNDIなしですべてを試したことを追加する必要があります。だから、ここにJNDIなしの私の春jms非ssl設定があります、それは動作します:

<bean id="mq-jms-cf-sandbox"
   class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory">
    <ref bean="mqQueueConnectionFactory" />
    </property>
</bean>
<bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
   <property name="hostName" value="localhost" />
   <property name="port" value="1414" />
   <property name="queueManager" value="QM_SANDBOX" />
   <property name="transportType" value="1" />
   <property name="channel" value="CHANNEL_SANDBOX" />
 </bean>
 <bean id="jms-destination-sandbox" class="com.ibm.mq.jms.MQQueue">
   <constructor-arg value="SANDBOX_Q" />
    <property name="baseQueueManagerName">
    <value>QM_SANDBOX</value>
    </property>
    <property name="baseQueueName">
    <value>SANDBOX_Q</value>
    </property>
</bean> 
13
code4kix

私はこれをやめる方法をついに見つけたと思う...ここにステップの簡単な説明がある。詳細が必要な場合はお知らせください。

Pre-reqs:Websphere MQサーバーがインストールされている(少なくともv 8.0.0.2)QM、SSLおよび非SSLチャネルを構成し、Qおよびすべてを作成する必要な良いもの。言うまでもなく、Websphere MQ jarが必要です。ライセンスの制限に注意してください。

ステップ1:SSL、JNDIなしで動作する直接接続を取得します。これらのBeanを使用して、スプリングベースのJMSリスナーやJMSテンプレートなどを設定する必要があります。

<bean id="mq-jms-cf-sandbox"
   class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory">
    <ref bean="mqQueueConnectionFactory" />
    </property>
</bean>
<bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
   <property name="hostName" value="localhost" />
   <property name="port" value="1414" />
   <property name="queueManager" value="QM_SANDBOX" />
   <property name="transportType" value="1" />
   <property name="channel" value="NON_SSL_CHANNEL" />
 </bean>
 <bean id="jms-destination-sandbox" class="com.ibm.mq.jms.MQQueue">
   <constructor-arg value="SANDBOX_Q" />
    <property name="baseQueueManagerName">
    <value>QM_SANDBOX</value>
    </property>
    <property name="baseQueueName">
    <value>SANDBOX_Q</value>
    </property>
</bean>

ステップ2:JNDIなしでSSLで動作する直接接続を取得します。これを設定するのは少し面倒です。

2a。 IBM以外のJREを使用していたため、ここで指定されたマッピングに従って暗号仕様と暗号スイートを構成する必要があることを確認する必要がありました。 http://www-01.ibm.com/support/ docview.wss?uid = swg1IV6684

これは明らかに、少なくともWebsphere MQを8.0.0.2にアップグレードする必要があることを意味します。私の場合、SSLチャネルでECDHE_RSA_AES_256_GCM_SHA384を使用し、アプリケーション内のjms beanがTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384を使用するように構成しました。

<bean id="mq-jms-cf-sandbox"
    class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory">
        <ref bean="mqQueueConnectionFactory" />
    </property>
</bean>
<bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
  <property name="hostName" value="localhost" />
  <property name="port" value="1414" />
  <property name="queueManager" value="QM_SANDBOX" />
  <property name="transportType" value="1" />
  <property name="channel" value="SSL_CHANNEL" />
  <property name="SSLCipherSuite" value="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"/>
</bean>
<bean id="jms-destination-sandbox" class="com.ibm.mq.jms.MQQueue">
<constructor-arg value="SANDBOX_Q" />
    <property name="baseQueueManagerName">
       <value>QM_SANDBOX</value>
    </property>
    <property name="baseQueueName">
       <value>SANDBOX_Q</value>
    </property>
</bean>

2b。証明書、キーストア(kdb)、交換証明書などを作成します。これを行うには多くの方法があります。ただし、パスワードを隠しておく必要があることに注意してください。キューマネージャーのキーラベルは「ibmwebspheremqqmgr」である必要があります。すべて小文字、スペースなし、引用符なし、キーラベルは「ibmwebspheremquserid」のようにする必要があります。すべて小文字でスペースなし(引用符なし)で、useridはTomcatを実行するユーザーIDです。自己署名証明書を使用した正確な方法に関する詳細が必要な場合は、お知らせください。

2c。次に、Tomcatが実行するJVMを取得して、キーストアを読み取る必要があります。多くの方法がありますが、ここに私がそれをした方法があります:Tomcat binフォルダーにsetenv.batファイルを作成し、次の内容で(SSLのデバッグはオプションです)

set Java_OPTS="-Djavax.net.ssl.trustStore=C:\path-to-keystore\key.jks" "-Djavax.net.ssl.trustStorePassword=topsecret" "-Djavax.net.ssl.keyStore=C:\path-to-keystore\key.jks" "-Djavax.net.ssl.keyStorePassword=topsecret" "-Djavax.net.debug=ssl" "-Dcom.ibm.mq.cfg.useIBMCipherMappings=false"

2d。次のコマンドを使用してTomcatを起動します。

catalina.bat run > ..\logs\Tomcat.log 2>&1 

停止するには、ctrl + c(Windows)を押します。どちらの方法でも、起動時にsetenv.batが使用されていることを確認してください。または、Java_OPTSを使用してキーストアプロパティを設定します。

2e。 SSLチャネルの使用が機能することを確認します。

ステップ3:非SSL、JNDIで動作するJNDI接続を取得するTomcatでJNDIをセットアップすることが多くありました。方法は次のとおりです。Webアプリケーション内で、次の内容のファイルMETA-INF/Context.xmlを作成します。

<Resource
   name="jms/qcf_sandbox"
   auth="Container"
   type="com.ibm.mq.jms.MQQueueConnectionFactory"
   factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
   description="JMS Queue Connection Factory for sending messages"
   Host="localhost"
   PORT="1414"
   CHAN="NON_SSL_CHANNEL"
   TRAN="1"
   QMGR="QM_SANDBOX"/>
<Resource
   name="jms/SandboxQ"
   auth="Container"
   type="com.ibm.mq.jms.MQQueue"
   factory="com.ibm.mq.jms.MQQueueFactory"
   description="JMS Queue"
   QU="SANDBOX_Q"/>

これで、直接設定の代わりに、スプリング設定で行う必要があるのは次のとおりです。

<jee:jndi-lookup id="mq-jms-cf-sandbox" jndi-name="Java:/comp/env/jms/qcf_sandbox" resource-ref="false" />
<jee:jndi-lookup id="jms-destination-sandbox" jndi-name="Java:/comp/env/jms/SandboxQ" resource-ref="false" />

簡潔にするために、リソース参照を使用しなかったことに注意してください。その場合、簡単ないくつかの追加手順があります。

ステップ4:最後のステップは、SSLチャネルとJNDIを使用することです。ステップ2を完了したと仮定すると、これは簡単です。次の内容でMETA-INF/Context.xmlを変更します。

<Resource
   name="jms/qcf_sandbox"
   auth="Container"
   type="com.ibm.mq.jms.MQQueueConnectionFactory"
   factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
   description="JMS Queue Connection Factory for sending messages"
   Host="localhost"
   PORT="1414"
   CHAN="SSL_CHANNEL"
   TRAN="1"
   QMGR="QM_SANDBOX"
   SCPHS="TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"/>
<Resource
   name="jms/SandboxQ"
   auth="Container"
   type="com.ibm.mq.jms.MQQueue"
   factory="com.ibm.mq.jms.MQQueueFactory"
   description="JMS Queue"
   QU="SANDBOX_Q"/>

SCPHS = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"の行に注意してください。このような他のパラメーターを設定する必要がある場合は、このリンクの「Short Form」列を参照してください: https://www.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.ref。 dev.doc/q111800_.htm%23jm10910_?lang = en

うまくいけば、これはすべてあなたのために働く。頑張ってください!

この構成が機能すると、メッセージの送信は非常に簡単です。しかし、これはSpring JMSリファレンスを使用してキューでメッセージをリッスンする方法です: https://docs.spring.io/spring/docs/current/spring-framework-reference/html/jms.html

ステップ1:SpringのDefaultMessageListenerContainerを使用して、次のようにxmlファイルでBeanを構成します(spring-beans.xml):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"      
    "http://www.springframework.org/dtd/spring-beans.dtd">

   <!-- this is the Message Driven POJO (MDP) -->
   <bean id="messageListener" class="jmsexample.ExampleListener" />

   <!-- and this is the message listener container -->
   <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
       <property name="connectionFactory" ref="mq-jms-cf-sandbox"/>
       <property name="destination" ref="jms-destination-sandbox"/>
       <property name="messageListener" ref="messageListener" />
   </bean>

</beans>

ステップ2:これをweb.xmlに追加します

<context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>/WEB-INF/context/spring-beans.xml</param-value>
 </context-param>

<listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

ステップ3:メッセージリスナクラスを次のように記述します。

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class ExampleListener implements MessageListener {

    public void onMessage(Message message) {
        if (message instanceof TextMessage) {
            try {
                System.out.println(((TextMessage) message).getText());
            }
            catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
        }
        else {
            throw new IllegalArgumentException("Message must be of type TextMessage");
        }
    }
}

また、ステップ3の代わりに、スプリング統合を使用している場合は、次のようなことができます。

<int:channel id="jms-inbound"/>
    <int-jms:message-driven-channel-adapter
        id="jms-inbound-adapter" container="jmsContainer" channel="jms-inbound" 
        extract-payload="true" acknowledge="transacted" 
        message-converter="messagingMessageConverter" />

<beans:bean id="messagingMessageConverter" class="org.springframework.jms.support.converter.MessagingMessageConverter">
    </beans:bean>
12
code4kix