2010-08-19 16 views
12

Ich habe eine Komponente, die Nachrichten an eine Warteschlange sendet, um von einem anderen System behandelt zu werden. Es sollte auch hin und wieder ein Thema zum Jobstatus veröffentlicht werden. Kann ich einfach das gleiche JmsTemplate verwenden, das zum Senden an eine Warteschlange UND zum Veröffentlichen in einem Thema verwendet wird?Wie publizieren Sie ein JMS-Thema mit Spring JMS?

Ich habe ein neues Thema in ActiveMQ erstellt, außer dass, wenn ich von JmsTemplate eine Nachricht senden, eine neue Warteschlange mit dem Thema Name mit der gesendeten Nachricht erstellt wird (anstatt die Daten an das eigentliche Thema zu senden), was bin ich hier falsch machen?

hier meine config:

<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 wird die Klasse verwende ich eine Warteschlange Nachricht zu senden (und es funktioniert), kann ich auch verwendet, nur, dass ein Thema zu veröffentlichen?

Kann ich dies nur beide Warteschlange zu tun, das Senden und Thema Publishing ?:

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

Antwort

28

Dies könnte ein wenig seltsam scheinen, müssen Sie JmsTemplate sagen, dass es ein Thema ist eher als eine Warteschlange, indem sein pubSubDomain Eigenschaft zu true.

Das bedeutet, Sie gehen zu müssen zwei JmsTemplate Bohnen, eine für die Warteschlange, und einen für das Thema:

<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> 
5

Wenn Sie das Ziel als Feder Bean erstellen, anstatt mit dem Zielnamen in In Ihrem Code muss Spring nicht wissen, ob es sich um ein Thema oder eine Warteschlange handelt. Andernfalls sollte die oben vorgeschlagene Lösung ebenfalls funktionieren.

AMQ JMS-Ziele können direkt erstellt werden, um sie zu instanziieren:

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

oder aus JNDI holen:

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

Ich ziehe die JNDI-Technik wie es Standard ist.

1

Wenn es in Ordnung ist für Sie eine Namenskonvention für queue/Themen zu verwenden, dann können Sie eine benutzerdefinierte implementieren 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); 
    } 
} 

und auf sie verweisen mit JmsTemplate.setDestinationResolver

+0

funktionierte perfekt für mich. Wenn Sie dem DestinationResolver @Component hinzufügen, müssen Sie es nicht einmal auf JmsTemplate setzen – danielnovy

+0

@danielnovy, wenn Sie die Antwort nützlich fanden, würde eine Abstimmung hochgeschätzt :) –

Verwandte Themen