web-dev-qa-db-ja.com

Spring JMSでJMSトピックをどのように公開しますか?

メッセージをキューに送信して別のシステムで処理するコンポーネントがあります。また、時々、ジョブステータスに関するトピックを公開する必要があります。キューへの送信とトピックへの公開に使用されるのと同じJmsTemplateを使用できますか?

ActiveMQで新しいトピックを作成しましたが、JmsTemplateからメッセージを送信すると、(実際のトピックにデータを送信するのではなく)送信されたメッセージでトピック名を持つ新しいキューが作成されますが、ここで何が間違っていますか?

これが私の設定です:

<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="amqConnectionFactory" />
    <property name="exceptionListener" ref="jmsExceptionListener" />
    <property name="sessionCacheSize" value="100" />
</bean>

<!--  JmsTemplate Definition -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <constructor-arg ref="connectionFactory" />
</bean>


<bean id="messageFacade" class="org.foo.MessageFacadeJms">
    <property name="jmsTemplate" ref="jmsTemplate" />
</bean>

MessageFacadeJmsは、キューメッセージを送信するために使用するクラスです(そして機能します)。それを使用してトピックを公開することもできますか?

これを使用して、キュー送信とトピック発行の両方を実行できますか?:

jmsTemplate.convertAndSend("TOPIC_NAME" /* or queue name */, message);
20
wsb3383

これは少し奇妙に見えるかもしれませんが、pubSubDomainプロパティをtrueに設定して、キューではなくトピックであることをJmsTemplateに伝える必要があります。

つまり、キュー用とトピック用に2つのJmsTemplate Beanが必要になるということです。

<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
   <constructor-arg ref="connectionFactory" />
   <property name="pubSubDomain" value="false"/>
</bean>

<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
   <constructor-arg ref="connectionFactory" />
   <property name="pubSubDomain" value="true"/>
</bean>
36
skaffman

コードで宛先名を使用するのではなく、Spring Beanとして宛先を作成する場合、Springはそれがトピックであるかキューであるかを認識する必要はありません。それ以外の場合は、上記で提案されたソリューションも機能するはずです。

AMQ JMS宛先は、直接インスタンス化することで作成できます。

  <bean id="destination" class="org.Apache.activemq.command.ActiveMQTopic">
    <constructor-arg value="TOPIC_NAME" />
  </bean>

またはJNDIからのフェッチ:

<bean id="topic" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="TOPIC_NAME"/>
        <property name="jndiTemplate" ref="jmsJndiTemplate"/> 
</bean>

JNDI手法の方が標準なので、私はそれを好みます。

5
Eran Harel

キュー/トピックの命名規則を使用しても問題ない場合は、カスタムorg.springframework.jms.support.destination.DestinationResolverを実装できます

public class NamingDestinationResolver implements DestinationResolver {
   public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException {
      if (destinationName.endsWith("Queue")) {
         return session.createQueue(destinationName);
      } else if (destinationName.endsWith("Topic")) {
         return session.createTopic(destinationName);
      }
      throw new RuntimeException("Naming convention not respected for destination " + destinationName);
   }
}

JmsTemplate.setDestinationResolverを使用して参照します

2