2010-08-19 15 views
12

J'ai un composant qui envoie des messages à une file d'attente pour être traité par un autre système. Il devrait également publier un sujet sur les statuts de travail de temps en temps. Puis-je simplement utiliser le même JmsTemplate utilisé pour envoyer à une file d'attente ET publier sur un sujet?Comment publier un sujet JMS avec Spring JMS?

J'ai créé un nouveau sujet dans ActiveMQ, sauf que lorsque j'envoie un message JmsTemplate, une nouvelle file d'attente avec le nom du sujet est créée avec le message envoyé (au lieu d'envoyer les données au sujet) faire mal ici?

voici ma 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 est la classe que j'utilise pour envoyer un message de file d'attente (et il fonctionne), je peux aussi simplement utilisé que pour publier un sujet?

Puis-je utiliser pour faire les deux files d'attente d'envoi et la publication de sujet ?:

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

Répondre

28

Cela peut sembler un peu bizarre, vous devez dire JmsTemplate que c'est un sujet plutôt que d'une file d'attente, en définissant sa pubSubDomain propriété à true.

Cela signifie que vous allez avoir besoin de deux JmsTemplate haricots, une pour la file d'attente, et un pour le sujet:

<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

Si vous créez la destination comme un grain de printemps plutôt que d'utiliser le nom de destination votre code, Spring n'aura pas besoin de savoir s'il s'agit d'un sujet ou d'une file d'attente. Sinon, la solution suggérée ci-dessus devrait également fonctionner.

destinations JMS AMQ peuvent être créées par directement les instanciation:

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

ou aller chercher de JNDI:

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

Je préfère la technique JNDI car il est plus standard.

1

Si c'est ok pour vous d'utiliser une convention de nommage pour la file d'attente/sujets, vous pouvez mettre en œuvre une mesure 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); 
    } 
} 

et référence à l'aide JmsTemplate.setDestinationResolver

+0

ont parfaitement fonctionné pour moi. Si vous ajoutez @Component à DestinationResolver, vous n'avez même pas besoin de le définir sur JmsTemplate – danielnovy

+0

@danielnovy si vous avez trouvé la réponse utile, un vote serait apprécié :) –