3

構成に Akka、Akka-Camel、Spring を使用してアプリケーションを作成しています。アプリケーションは、さまざまなアプリケーション サーバーに対してスタンドアロンの JMS クライアントとして機能する必要があります。そのためには、JNDI を使用して JMS 接続ファクトリを設定する必要があります。これをjBossでテストしています。私は jBoss 5 と 6 で同じ問題を抱えています (これは jBoss とは関係なく、クライアント側の Spring の問題のようです)。

この xml を使用して Spring Bean を構成しています。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
         http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
         http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
         ">

    <camelContext id="camel" trace="false" xmlns="http://camel.apache.org/schema/spring">
        <jmxAgent id="agent" disabled="true"/>
    </camelContext>

    <jee:jndi-lookup id="jmsConnectionFactory" jndi-name="ConnectionFactory">
        <jee:environment>
            java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
            java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
            java.naming.provider.url=jnp://192.168.0.109:1099
        </jee:environment>
    </jee:jndi-lookup>

    <bean name="jms" class="org.apache.camel.component.jms.JmsComponent">
        <property name="connectionFactory" ref="jmsConnectionFactory" />
    </bean>

</beans>

ご覧のとおり、次のように設定しています。

  • jmsConnectionFactory と呼ばれる、JNDI を介して初期化された ConnectionFactory
  • connectionFactory プロパティが前の Bean に設定された JmsComponent

この構成では、私のアプリは起動時に次のように失敗します。

java.lang.IllegalArgumentException: connectionFactory must be specified
    at org.apache.camel.util.ObjectHelper.notNull(ObjectHelper.java:294) ~[camel-core.jar:2.10.4]
    at org.apache.camel.component.jms.JmsConfiguration.createConnectionFactory(JmsConfiguration.java:1053) ~[camel-jms.jar:2.10.4]
    at org.apache.camel.component.jms.JmsConfiguration.getConnectionFactory(JmsConfiguration.java:416) ~[camel-jms.jar:2.10.4]
    at org.apache.camel.component.jms.JmsConfiguration.createListenerConnectionFactory(JmsConfiguration.java:1062) ~[camel-jms.jar:2.10.4]
    at org.apache.camel.component.jms.JmsConfiguration.getListenerConnectionFactory(JmsConfiguration.java:435) ~[camel-jms.jar:2.10.4]
    at org.apache.camel.component.jms.JmsConfiguration.configureMessageListenerContainer(JmsConfiguration.java:889) ~[camel-jms.jar:2.10.4]
    at org.apache.camel.component.jms.JmsConfiguration.createMessageListenerContainer(JmsConfiguration.java:379) ~[camel-jms.jar:2.10.4]

これは、JmsConfiguration.java の次のコードに由来します。

protected ConnectionFactory createConnectionFactory() {
    ObjectHelper.notNull(connectionFactory, "connectionFactory");
    return null;
}

したがって、Spring Bean の初期化が、ここで指示されているように Bean の関連付け/配線に失敗しているようです (以前に貼り付けた完全な XML Spring 構成から抽出)。

    <bean name="jms" class="org.apache.camel.component.jms.JmsComponent">
        <property name="connectionFactory" ref="jmsConnectionFactory" />
    </bean>

また、connectionFactory プロパティを直接設定する代わりに、中間 JmsConfiguration Bean を作成し、JmsComponent の構成プロパティを設定しようとしましたが、両方のセットアップで同じ結果が得られます。

ちなみに、ビーンはコードで配線できます。私はこれを意味します:

val connFactory = springContext.getBean[javax.jms.ConnectionFactory]("jmsConnectionFactory", classOf[javax.jms.ConnectionFactory])
camelContext.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connFactory))

完全に正常に動作します。したがって、JNDI から ConnectionFactory を取得していることはわかっていますが、XML で配線するための適切な Spring 構成をヒットできないだけです。

私はこのアプリケーションを再コンパイルせずに非常に構成可能にする必要があるため、XML を機能させることは私にとって必須です。

明確でない場合の質問は次のとおりです。JNDI が取得したファクトリに設定された connectionFactory を使用して、Spring に JmsComponent Bean を設定するにはどうすればよいですか?

編集:キャメルを使用するポイントは、このコンポーネントを別のタイプの別のコンポーネントと交換できるようにすることです。今日は JMS を使っていますが、明日は TCP を使うかもしれません。これが、すべてを XML で定義できることが重要な理由です。

4

2 に答える 2

1

問題は、Akka が Spring 構成で定義されたものではなく、独自の CamelContext を使用していることだと思います。Akka の以前のバージョンでは、 Akka が使用するコンテキストを設定できるように見えましたが、最新バージョンではそれができなくなっているようです。

私は同じ問題に遭遇しました.Java(Scalaではなく)で注釈ベースの構成を使用し、このコードを使用して問題を回避しました:

@Bean
public ActorSystem getCamelActorSystem(ConnectionFactory factory) {

    ActorSystem system = ActorSystem.create("some-system");

    Camel camel = CamelExtension.get(system);
    CamelContext camelContext = camel.context();
    camelContext.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(factory));

    return system;
}

これは、別の場所で定義された ConnectionFactory 依存関係を注入し、これを使用して、Akka が使用する camelContext に jms コンポーネントを追加します。

別の解決策として、CamelExtension コードを何らかの方法で拡張して、以前は可能であったように、camelContext 依存関係を注入できるようにすることもできます。ただし、変更には十分な理由があったと思いますので、そのままにしておきます。アクター システムが常に同じ Camel コンテキストを使用するように、コンテキストを変更できないようにするためだと思います。これは、以下に基づいています。

1 つの CamelExtension は 1 つの ActorSystem ごとに 1 回だけロードされるため、コード内の任意の時点で CamelExtension を呼び出して、関連付けられた Apache Camel オブジェクトにアクセスすることが安全になります。CamelExtension を使用する ActorSystem ごとに 1 つの CamelContext と 1 つの ProducerTemplate があります。

http://doc.akka.io/docs/akka/current/scala/camel.html#CamelExtension

于 2013-10-02T09:03:30.013 に答える
0

あなたのルックアップは機能しているように見えるので、これはおそらくあなたが探している以上のものですが、jndiTemplate (Spring 3.1) を使用して jndi 経由で接続ファクトリを取得する方法は次のとおりです。構成を介して(トランザクションマネージャーを介して)接続ファクトリーを提供することに注意してください。タイプミスで申し訳ありませんが、アイデアは得られます。

<bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="location">
        <value>classpath:connection.properties</value>
     </property>
</bean>
<bean name="jms" class="org.apache.camel.component.jms.JmsComponent">
    <property name="configuration" ref="jmsConfig" />
</bean>
<bean id="txManager" class="org.springframework.jms.connection.JmsTransactionManager">
   <property name="connectionFactory" ref="springConnectionFactory"/>
<bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
   <property name="connectionFactory" ref="springConnectionFactory" />
   <property name="transactionManager" ref="txManager" />
   <property name="testConnectionOnStartup" value="true" />
   <property name="destinationResolver" ref="jndiDestinationResolver" />
</bean>
<bean id="springConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
   <property name="clientId" ref="SubCid" />
   <property name="reconnectOnException" ref="true" />
   <property name="targetConnectionFactory">
        <bean parent="jndiObjectFactory"/>
   </property>
   <property name="sessionCacheSize" value="1"/>
 </bean>

 <bean id="jndiObjectFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName" value="TopicConnectionFactory"/>
   <property name="jndiTemplate">
        <ref bean="jndiTemplate"/>
   </property>
 </bean>
 <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
       <property name="environment">
           <props>
                <prop key="java.naming.provider.url">${db.jms.JNDIServerName}</prop>
           </props>
       </property>
  </bean>
于 2013-06-13T14:55:14.317 に答える