次のミュール構成と、ミュールが 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>
Queue Connection Factory はテスト済みで、動作しています。
jms/MessageQueueキュー名は、Web アプリケーションの web.xml ファイルで定義されたresource - refを参照します。この JNDI 参照は、コンテナー レベルで、アプリケーション サーバーによって管理され、適切なメッセージング サーバー (この場合は ActiveMQ) に接続されているjavax.jms.Queueにバインドされます。
ただし、Mule はqueue=""属性を JNDI 宛先としてではなく、キュー名自体として扱います。したがって、上記のコードが初期化されると、実際には ActiveMQ に「jms/MessageQueue」という名前の新しいキューが作成されます。私が本当に望んでいたのは、Web アプリケーション記述子の JNDI 参照からキューを正しく取得することでした。
わかりました。JMSコネクタで JNDI Name Resolver を構成し、それに jndiDestinations="true"およびforceJndiDestinations="true"属性を追加するだけで済みました。
これは許容されます:
<jms:default-jndi-name-resolver
jndiProviderUrl="tcp://localhost:1099"
jndiInitialFactory="???"/>
本当の問題は、コンテナー固有の定義に該当するため、実際の Initial Context Factory クラス名をjndiInitialFactoryに配置したくないことです。ただし、私のアプリケーションは JBoss 4.2.3 にデプロイされることもあれば、WebSphere 7 にデプロイされることもあります。開発プロセスにより、2 つの構成と 2 つの EAR パッケージを持つことはできません。
とにかく、Mule-ESB に現在のコンテナ (埋め込みモードの場合) をルックアップ用のデフォルトの JNDI 初期ファクトリとして想定させるか、コンテナの JNDI 環境を認識する「一般的な」JNDI 初期ファクトリを提供することは可能ですか? Web アプリケーションは、追加の (または目に見える) 構成なしでコンテナー JNDI 環境を参照できるため、これは問題になりません。
不可能な場合、 jms:connectorが JMS 接続ファクトリーで行うように、 jms:inbound-endpointに Spring で定義されたjavax.jms.Queueを参照させることはできますか? Mule は Spring に対応しているため、実際にはかなりエレガントでクリーンです。
よろしくお願いします!
解決
よく考えて検討した結果、Spring JNDI 機能 (JndiTemplate など) に接続されたカスタム 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 (キューとファクトリ) の構成はすべて、アプリケーション サーバーの責任の下に残されています。
それにもかかわらず、1つのことが奇妙でした。JMS エンドポイントも Jndi Name Resolver を使用して、リソース参照またはその JNDI 名からキューをルックアップすることを期待していました。これは、コネクション ファクトリの場合と同じ方法です。それはまったくうまくいきません。JMSサーバーで作成されたキュー名自体を配置することで、最終的にこれを回避しました。
<flow name="mainTestFlow">
<jms:inbound-endpoint connector-ref="jmsConnector" queue="queue/myQueue"/> <!-- Queue Name, not JNDI Name -->
それはうまくいきました。したがって、JMS コネクタはキューを検索しようとせず、(検索したかどうかに関係なく) 接続ファクトリを使用して JMS サーバーに直接アクセスすると想定しています。
よろしく!