当前位置: 首页 > 知识库问答 >
问题:

Mule-embedded:使用容器自己的jndiInitialFactory

和魁
2023-03-14

考虑以下骡子配置,并将骡子嵌入到Web(Java EE)应用程序中:

<jms:connector
        name="jmsConnector"
        connectionFactory-ref="jmsConnectionFactory"> <!-- From spring -->
        <!-- JNDI Name Resover here? -->
</jms:connector>
<flow name="mainTestFlow">
    <jms:inbound-endpoint connector-ref="jmsConnector" 
        queue="jms/MessageQueue" />
    <logger level="INFO" category="mule.message.logging" message="Message arrived." />
</flow>

jmsConnectionFactory是指Spring中定义的JMS连接工厂,来自:

<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jms/QueueConnectionFactory" />
</bean>

队列连接工厂已经过测试,并且正在工作。

jms/MessageQueue队列名称引用web应用程序web.xml文件中定义的resource-ref。这个JNDI引用在容器级别绑定到由应用服务器管理的javax.jms.Queue,并连接到适当的消息服务器(在本例中是ActiveMQ)。

然而,Mule并不将queue=“”属性视为JNDI目的地,而是视为队列名称本身。因此,当上述代码初始化时,它实际上在ActiveMQ中创建了一个名为“jms/MessageQueue”的新队列。我真正想要的是它从Web应用程序描述符中的JNDI引用中正确检索队列。

好吧,你可以说,我所要做的就是在JMS连接器上配置一个JNDI名称解析器,并向其添加jndiDestinations="true "和forceJndiDestinations="true "属性。

这是可以接受的:

<jms:default-jndi-name-resolver 
    jndiProviderUrl="tcp://localhost:1099"
    jndiInitialFactory="???"/>

真正的问题是,我不想将真正的初始上下文工厂类名放在 jndiInitialFactory 中,因为它会落入特定于容器的定义中。但是,我的应用程序有时部署到 JBoss 4.2.3 中,有时部署到 WebSphere 7 中。由于我们的开发过程,拥有2个配置和2个EAR包不是一种选择。

无论如何,是否有可能告诉Mule-ESB将当前容器(因为它处于嵌入式模式)假设为用于查找的默认JNDI初始工厂,或者提供一个“通用”JNDI初始工厂来识别容器的JNDI环境?这应该不是问题,因为Web应用程序可以引用它的容器JNDI环境而无需额外(甚至可见)配置。

如果不可能,我可以让我的jms: inbing-endpoint引用Spring中定义的javax.jms.Queue吗,就像jms:连接器引用JMS连接工厂一样?这实际上相当优雅和干净,因为Mule对Spring友好。

提前谢谢大家了!

解决办法

经过深思熟虑,我终于通过创建一个连接到Spring JNDI设施(例如JndiTemboard)的自定义JndiNameResolver来解决我的问题。这远非最佳解决方案,但我发现这是最不会干扰和篡改Mule和Spring内部复杂性的解决方案。

这就是说,这里有一个类:package com.filcobra.mule;

import javax.naming.NamingException;

import org.mule.transport.jms.jndi.AbstractJndiNameResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jndi.JndiObjectLocator;
import org.springframework.jndi.JndiTemplate;

public class SpringJndiNameResolver extends AbstractJndiNameResolver implements InitializingBean {
    private static Logger logger = LoggerFactory.getLogger(SpringJndiNameResolver.class);
    private JndiTemplate jndiTemplate;

    @Override
    public void afterPropertiesSet() throws Exception {
        if (jndiTemplate == null) {
            jndiTemplate = new JndiTemplate();
        }
    }

    @Override
    public Object lookup(String name) throws NamingException {
        Object object = null;
        if (name != null) {
            logger.debug("Looking up name "+name);
            object = jndiTemplate.lookup(name);
            logger.debug("Object "+object+" found for name "+name);
        }
        return object;
    }

    public JndiTemplate getJndiTemplate() {
        return jndiTemplate;
    }

    public void setJndiTemplate(JndiTemplate jndiTemplate) {
        this.jndiTemplate = jndiTemplate;
    }
}

这样,配置就回到了通常的状态:

<spring:bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate" />

<jms:connector
        name="jmsConnector"
        connectionFactoryJndiName="java:comp/env/jms/MyConnectionFactory" <!-- from Resource-Ref -->
        jndiDestinations="true"
        forceJndiDestinations="true"
        specification="1.1" >

    <jms:custom-jndi-name-resolver class="com.filcobra.mule.SpringJndiNameResolver">
        <spring:property name="jndiTemplate" ref="jndiTemplate"/>
    </jms:custom-jndi-name-resolver>    
</jms:connector>

有了它,我终于能够不让我的Mule ESB安装绑定到特定的JMS供应商/实现。事实上,JMS(队列和工厂)配置都由应用服务器负责。

然而,有一件事仍然很奇怪。我希望JMSendpoint也使用我的Jndi名称解析程序,以便从资源引用或其Jndi名中查找队列,与连接工厂的查找方式相同。那根本不管用。我最终通过放置队列名称本身解决了这个问题,正如在JMS服务器中创建的那样:

<flow name="mainTestFlow">
    <jms:inbound-endpoint connector-ref="jmsConnector" queue="queue/myQueue"/> <!-- Queue Name, not JNDI Name -->

成功了。因此,我假设JMS连接器不尝试查找队列,而是简单地使用连接工厂(无论是否查找)直接访问JMS服务器。

问候!

共有1个答案

韩善
2023-03-14

我在源代码中看到了问题:基本上如果你提供一个外部创建的连接工厂,< code>jndiDestinations和< code > forceJndiDestinations 被强制设置为< code>false。

我最近对JNDI的研究还不够深入,无法为您的问题提供一个通用的解决方案,这确实是最好的解决方案。

我会尝试的是子类 org.mule.transport.jms.Jms11Support,在其中注入我的 Spring 查找队列,在内部重新连接以使用这些队列,最后,将其注入 Mule JMS 连接器本身。

 类似资料:
  • 一步一步从无到有写一个 servlet 容器。一开始不会涉及复杂的部分,中间会进行多次重构,直到完成复杂的功能。

  • 我正在尝试使用Janalyiler分析部署在mule容器(CE v3.4)上的Mule ESB应用程序,但迄今为止没有成功。我的Mule服务器在linux 64位服务器上远程运行,而janalyiler在我的本地Windows机器上运行。我正在尝试将本地Windows机器上运行的janalyiler远程连接到在linux服务器上远程运行的Mule服务器,但到目前为止,我未能将本地运行的janaly

  • 问题内容: 当我从公共Elasticsearch存储库中提取图像时,生成带有该提取图像的容器对我来说工作正常,没有权限问题。 但是当我使用Dockerfile生成一个容器时,公共仓库中就可以使用它,这给了我权限问题。我的目录结构与公共仓库相同。 命令:-1)使用Dockerfile构建映像 2)从生成的图像中生成容器 但是,当我尝试从上述自定义构建映像中派生任何容器时,每次都会出现以下错误。 问题

  • 我如何像这样使用我的电子邮件example@domain.ph在phpmailer中。因为我总是有一个错误,即使我有一个正确的凭据。 2020-05-14 09:21:24服务器- 这是我的配置:

  • 我有一个python应用程序要测试。此应用程序正在导入许多包,例如: 其中mypackage是我自己的包。 当我开始应用程序时,一切正常。然而,一旦我试图运行毒物测试它,我就会得到以下错误: 我知道tox无法安装mypackage依赖项,因为它不在pip中。您知道如何在此类应用程序上运行tox,或者如何使用tox安装自己的软件包吗? 我的tox.ini文件内容:

  • 问题内容: 具有运行后自动删除容器的标志。我想知道是否有与docker- compose.yml对应的特定服务配置,因为我在yml中获得的其中一项服务是一个脱离构建的过程,该过程应该只输出编译文件并自行消失。 问题答案: 我没有找到任何选项来帮助您在文件中定义此行为,我认为解释如下: 构建,(重新)创建,启动并附加到服务的容器。 由于您的服务器已构建并且服务已经启动,因此您可以使用和启动/停止服务