JMS的Spring配置(WebSphereMQ-SSL、Tomcat、JNDI、非IBMJRE)

JMS的Spring配置(WebSphereMQ-SSL、Tomcat、JNDI、非IBMJRE),spring,tomcat,jms,jndi,ibm-mq,Spring,Tomcat,Jms,Jndi,Ibm Mq,背景: 我有一个相对较旧的应用程序,它使用WebSphereMQ进行消息传递。它运行在WAS(WebSphereApplicationServer)上,并使用MDB(消息驱动bean)。我成功地使用替换了所有MDB。我的下一步是尝试看看是否可以将它从WAS中移植出来,以便它可以在任何其他具有非IBMJRE的servlet容器上运行(我正在尝试:ApacheTomcat)。请注意,使用SSL保护通道是一项要求。我更喜欢使用JNDI 最终目标: 将我的应用程序与应用程序服务器(WAS)和其他基础结构

背景: 我有一个相对较旧的应用程序,它使用WebSphereMQ进行消息传递。它运行在WAS(WebSphereApplicationServer)上,并使用MDB(消息驱动bean)。我成功地使用替换了所有MDB。我的下一步是尝试看看是否可以将它从WAS中移植出来,以便它可以在任何其他具有非IBMJRE的servlet容器上运行(我正在尝试:ApacheTomcat)。请注意,使用SSL保护通道是一项要求。我更喜欢使用JNDI

最终目标: 将我的应用程序与应用程序服务器(WAS)和其他基础结构(如消息传递(MQ))分离。但是把这个从WAS中带到tomcat上是第一步。接下来的任务是用更具可伸缩性的东西更新我的消息传递基础结构。这使我能够一次更新应用程序所依赖的基础设施的各个组件(应用程序服务器、消息传递层、数据存储),而不会在运行过程中过度中断应用程序

问题: 现在,我的挑战是在tomcat上定义可以访问WebSphereMQ的JNDI资源。我使用在context.xml文件中定义的非SSL通道在这方面取得了一些进展,如下所示:


我的下一步是让它与SSL通道一起工作。我理解涉及设置密钥库(kdb文件和证书生成和交换)、配置QM上的SSL通道等的部分。我已经完成了所有这些工作。如何让tomcat使用我的密钥库、密码套件等?指针或工作示例将是伟大的

注意:我目前正在使用SpringIntegration4.2、WebSphereMQV8和TomcatV9

我必须补充一点,没有JNDI我什么都试过了。下面是我的spring jms非ssl配置,没有JNDI,它可以工作:


QM_沙箱
沙箱

我想我终于找到了解决办法。。。以下是这些步骤的简要说明。如果你需要更多的细节,请告诉我

预需求: 已安装Websphere MQ服务器(至少版本8.0.0.2) 配置QM、SSL和非SSL通道,创建Qs和所有您需要的好东西。 不用说,您需要WebSphereMQJAR。请注意任何许可限制

步骤1:让直接连接在没有SSL、没有JNDI的情况下工作。您将需要使用这些bean来配置基于spring的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>
2d。使用以下命令启动tomcat:

catalina.bat run > ..\logs\tomcat.log 2>&1 
要停止,只需按ctrl+c(在windows上)。无论采用哪种方式,请确保在启动期间使用setenv.bat。或者使用JAVA_选项设置密钥库属性

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"/>
<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"/>
或者,如果您使用的是spring集成,则可以执行如下操作,而不是步骤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>


详细说明+1.您在哪里配置步骤1?文件名,在spring-beans.xml或其他文件中,以及如何读取它。它是配置spring-beans的xml文件(也可以分解为多个文件)。只需确保在web.xml中提到@code4kix(如果根据命名约定,默认情况下无法获取它),就可以获取它。我只是尝试从WAS7迁移到WAS8.5,并删除所有EJB和MDB。我已经成功地完成了EJB到Spring4的注入和ComponentContext,现在我只能在代码中使用一个MDB。我使用ActiveSpec阅读was。你能帮助我如何在was 8.5中迁移它吗?我的建议是完全删除MDB和active spec。在服务器上,你所需要的只是qm连接工厂和q连接工厂。在应用程序上,只使用消息驱动的POJO(而不是MDB)。我相信如果你搜索,肯定会有一些例子。如果你真的找不到,可以在stackoverflow中再问一个问题。如果没有其他人能做到的话,我会尽力做到的。
<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" />
<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"/>
<?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>
<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>
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");
        }
    }
}
<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>