考虑下面的mule配置,并将mule嵌入到Web (Java )应用程序中:
<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中定义的jmsConnectionFactory,它来自:
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jms/QueueConnectionFactory" />
</bean>队列连接工厂已经过测试并正在工作。
jms/MessageQueue队列名引用了在web应用程序web.xml文件中定义的资源-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:inbound-endpoint引用在Spring中定义的javax.jms.Queue,就像jms:connector对所做的那样?这实际上是相当优雅和干净的,因为Mule是春天友好的。
提前谢谢大家!
溶液
经过深思熟虑,我终于通过创建一个连接到spring设施的定制JndiNameResolver (例如JndiTemplate)来解决我的问题。这远非最好的解决方案,但我发现,这将是对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 (队列和工厂)配置都由应用服务器负责。
然而,有一件事仍然很奇怪。我希望JMS端点也使用我的Jndi Name Resolver来从资源引用(或其JNDI名称)中查找队列,就像对Connection一样。不管怎么说都没用。最后,我将队列名称放在JMS服务器中创建的队列名称中,从而解决了这一问题:
<flow name="mainTestFlow">
<jms:inbound-endpoint connector-ref="jmsConnector" queue="queue/myQueue"/> <!-- Queue Name, not JNDI Name -->起作用了。因此,我假设JMS连接器没有尝试查找队列,而是简单地使用连接工厂(查找或不查找)直接访问JMS服务器。
致以问候!
发布于 2012-09-17 20:22:48
我在源代码中看到了问题:基本上,如果您提供外部创建的连接工厂,jndiDestinations和forceJndiDestinations将强制设置为false。
最近我还没有为您的问题提供一个通用的解决方案,这确实是最好的解决方案。
我将尝试的是子类org.mule.transport.jms.Jms11Support,在其中注入我的Spring查找队列,在内部重新连接它以使用这些队列,最后将它注入Mule JMS连接器本身。
https://stackoverflow.com/questions/12461714
复制相似问题