javax.jms.JMSSecurityException: MQJMS2008: 未能打开 MQ 队列

Posted

技术标签:

【中文标题】javax.jms.JMSSecurityException: MQJMS2008: 未能打开 MQ 队列【英文标题】:javax.jms.JMSSecurityException: MQJMS2008: failed to open MQ queue 【发布时间】:2011-08-05 00:03:18 【问题描述】:

我有一个基于 JMS 的应用程序,我在 Websphere 6.0 上运行,并且正在迁移到 Websphere 7。两个 Websphere 服务器都支持 Websphere MQ 6.0 服务器。尝试将测试 servlet 部署到 Websphere 7 服务器时收到以下异常:

javax.jms.JMSSecurityException: MQJMS2008: failed to open MQ queue

Websphere 6.0:RHEL 5.3

Websphere 7.0.0.15:RHEL 5.3

Websphere MQ 6.0:Windows Server 2003

Servlet 测试代码:

public class JMSTestServlet extends HttpServlet 
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
        String MQConnectionFactory, MQQueue; 

    public JMSTestServlet() 
        super();
        // TODO Auto-generated constructor stub
        System.out.println("JMSTestServlet: loading");

        URL urlProps = getClass().getClassLoader().getResource("META-INF/startup.properties");
        Properties props = new Properties();
        try
                
          System.out.println("JMSTestServlet: loading properties");
          props.load( urlProps.openStream() );

                    MQConnectionFactory = props.getProperty("MQConnectionFactory"); 
                    MQQueue = props.getProperty("MQQueue"); 

          System.out.println("JMSTestServlet: loading properties ... done!");

          sendMessage("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
                 catch (IOException e)
                
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                
    

    protected void sendMessage(String messageString)  
        QueueConnectionFactory fact;
        QueueConnection qConn = null;
        try  
            System.out.println("JMSTestServlet: creating context");
            Context ctx = new InitialContext();
            fact = (QueueConnectionFactory)ctx.lookup(MQConnectionFactory);
            Destination destination = (Destination)ctx.lookup(MQQueue);

            System.out.println("JMSTestServlet: creating QueueConnection");
            qConn = fact.createQueueConnection(); 
            QueueSession    qSess = qConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageProducer prod = qSess.createProducer(destination); 


            System.out.println("JMSTestServlet: sending Message");
            TextMessage message = qSess.createTextMessage();
            message.setText(messageString);
            prod.send(message); 

            System.out.println("JMSTestServlet: done sendMessage()");
         catch ( JMSException ex ) 
            ex.toString(); 
            ex.printStackTrace();
            ex.getLinkedException().toString();
            ex.getLinkedException().printStackTrace();
         catch ( NamingException ex ) 
            System.out.println("JMSTestServlet: naming exception " + ex.toString());
            ex.printStackTrace();
         catch ( Exception ex ) 
          System.out.println("JNDI API lookup failed: " +         ex.toString());
            ex.printStackTrace();           
         finally 
            System.out.println("JMSTestServlet: cleaning up sendMessage()");

            try
            
                if ( qConn != null ) qConn.close();
             catch (JMSException e)
            
                // TODO Auto-generated catch block
                e.printStackTrace();
            
        
    

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
        try  
            String messageString = request.getParameter("message"); 
            sendMessage(messageString);
         finally 
        
    

属性文件是:

MQConnectionFactory=jms/QUEUECONNFACTORY
MQQueue=jms/QUEUE 

部署到 Websphere 6 时,我在远程队列中收到消息。当我部署到 Websphere 7 时,我得到:

[4/13/11 14:53:55:622 EDT] 0000005c ConnectionEve A   J2CA0056I: The Connection Manager received a fatal connection error from the Resource Adapter for resource JMS$QUEUECONNFACTORY$JMSManagedConnection@15. The exception is: javax.jms.JMSSecurityException: MQJMS2008: failed to open MQ queue 'QUEUE'.
[4/13/11 14:53:55:622 EDT] 0000005c ConnectionEve W   J2CA0206W: A connection error occurred.  To help determine the problem, enable the Diagnose Connection Usage option on the Connection Factory or Data Source.
[4/13/11 14:53:55:623 EDT] 0000005c ConnectionEve A   J2CA0056I: The Connection Manager received a fatal connection error from the Resource Adapter for resource jms/QUEUECONNFACTORY. The exception is: javax.jms.JMSSecurityException: MQJMS2008: failed to open MQ queue 'QUEUE'.
[4/13/11 14:53:55:625 EDT] 0000005c SystemErr     R   javax.jms.JMSSecurityException: MQJMS2008: failed to open MQ queue 'QUEUE'.

我很确定我已将两个 Websphere 服务器上的队列和连接工厂配置为相同。我不知道如何解决这个问题,谷歌也没有帮助。

2011-04-15 更新:

我从日志中提取了以下错误:

com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2035'

我已经在几个地方阅读过它,但我真的看不出 WAS 6 和 WAS 7 之间的差异在哪里导致了这个问题。

我在两台 Linux 主机上都以 root 身份运行 Websphere。我在 Windows 机器上创建了一个具有 MQ 安装完全权限的 root 帐户:

setmqaut -t qmgr -m QM_webspheremq -p root +all

【问题讨论】:

SecurityException 建议您需要提供连接凭据。 你会这么认为,但我似乎不需要它们。我没有为 Websphere 6.0(工作)配置任何内容,拥有/不拥有它们似乎对 Websphere 7 没有任何影响(!工作)。 嗨,克里斯,您是否介意查看我迟交的答案,如果看起来不错,请接受它或其他用户的回答,以防止这一次“被社区用户撞到”(可能是因为我提供了新的答案)它在仅仅 1 个月后就遇到了问题。 【参考方案1】:

我也遇到了同样的错误。检查您的端口、队列管理器和队列详细信息。对我来说,这是不正确的通道。

对于其他用户: 当您拥有 MQJMS2008 时,您无权操作该队列,您必须获得一个嵌套的异常,它为您提供有关您的错误的更多信息,它告诉您一个 MQRC 原因代码和终止代码。

有关原因代码的更多信息,请打开 CMD 并键入 mqrc

分析您的错误,看起来您被允许访问该队列,我有一些问题:

您是否使用 JNDI 进行连接?如果您正在连接一个使 PTP 连接的类(我的意思是不使用 JNDI),您必须向 MQQueueConnectionFactory 提供通道、队列管理器、队列名称和服务器的主机名,如果您想了解更多关于 PTP 连接的信息,这里是:http://hursleyonwmq.wordpress.com/2007/05/29/simplest-sample-applications-using-websphere-mq-jms/。

如果您对远程队列执行此操作,并且您在 Windows 上使用的是 MQSeries 而不是 WMQ,则您必须授予公共所有权限。 使用 WRKMQMQ。

如果你能给出嵌套异常,我会帮你的。

【讨论】:

【参考方案2】:

自 2019 年 1 月以来,每四个月“社区用户浏览”一次,我将尝试回答这个旧帖子。


先介绍一下背景:

是 6.0

包含来自 Websphere MQ v5.3 的 MQ jar 文件 根据 WAS 6.0 的特定版本,jar 将来自 Websphere MQ v5.3 CSD08 到 CSD14

是 7.0.0.15

应该包括 WebSphere MQ JCA 资源适配器版本 7.0.1.3(这里的默认行为是 MQ v5.3 jar 的行为),但是由于一个错误,如果您从 WAS 7.0.0.0 升级到 WAS 7.0.0.15,WAS 7.0.0.0 附带的 WebSphere MQ JCA 资源适配器版本 7.0.0.0 将保持不变。

区别:

对于 MQ v5.3 jar 文件,当您调用 fact.createQueueConnection(); 时,将向队列管理器发送一个空白用户 ID。如果您连接到的SVRCONN 通道具有空白MCAUSER 属性,则连接将在Windows MQ 队列管理器运行的用户帐户的权限下运行。换句话说,您将获得队列管理器和所有队列的完全权限(完全 MQ 管理权限)。

使用 MQ v7.0.0.0 资源适配器,当您调用 fact.createQueueConnection(); 时,JVM 进程 ID 将被发送到队列管理器。如果您连接的SVRCONN 通道具有空白MCAUSER 属性,则Windows MQ 队列管理器将尝试在JVM 进程ID 的权限下运行连接。根据您问题中的信息,这将是用户root


总结:

它在 Websphere 6.0 下工作,因为连接以完全 MQ 管理员权限运行。

它在 Websphere 7.0.0.15 下失败,因为连接以 root 用户权限运行,在这种情况下,您仅向队列管理器 (qmgr) 本身提供了具有 all 权限的 root 用户,但是没有QUEUE的权限。

Websphere 必须首先连接并查询队列管理器对象,然后才能打开任何队列。你得到的错误是javax.jms.JMSSecurityException: MQJMS2008: failed to open MQ queue 'QUEUE'.。这意味着您确实成功连接到队列管理器,但随后无法连接到队列。

这可以通过将QUEUE 的权限提供给root 用户来解决:

setmqaut -t q -m QM_webspheremq -n QUEUE -p root +put +get +browse +inq +dsp


请注意,问题中列出的所有软件版本现在(8.5 年后)都不再得到 IBM 的支持。也不建议使用带有空白MCAUSERSVRCONN 通道,除非您使用其他方法(例如安全出口)将 MCAUSER 设置为非 MQ Admin id。在当前的 IBM MQ 版本中,您可以使用 TLS 和在队列管理器上映射到非 MQ Admin id 的客户端证书,或使用没有证书 + 连接身份验证的 TLS 来验证客户端在队列管理器上发送的用户 id 和密码。

【讨论】:

接受。它是一个彻底的答案。但不完全确定它的有效性。我不再有能力进行测试,但如果有人仍然有这个问题,人们有其他人可以联系,或者可以查看的地方。感谢您的精彩文章。

以上是关于javax.jms.JMSSecurityException: MQJMS2008: 未能打开 MQ 队列的主要内容,如果未能解决你的问题,请参考以下文章