2010-08-19 20 views
12

Ho un componente che invia messaggi a una coda per essere gestito da un altro sistema. Dovrebbe anche pubblicare un argomento sugli stati dei lavori ogni tanto. Posso usare lo stesso JmsTemplate usato per inviare a una coda E per pubblicare su un argomento?Come si pubblica un argomento JMS con Spring JMS?

Ho creato un nuovo argomento in ActiveMQ, tranne che quando invio un messaggio da JmsTemplate, una nuova coda con il nome dell'argomento viene creata con il messaggio inviato (invece di inviare i dati all'argomento attuale), cosa sono io stai sbagliando qui?

qui è il mio 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 è la classe che uso per inviare un messaggio di coda (e funziona), posso anche appena usato che a pubblicare un argomento?

Posso usare questo per fare entrambe le cose coda di invio e argomento pubblicazione ?:

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

risposta

28

Questo potrebbe sembrare un po 'strano, è necessario indicare JmsTemplate che si tratta di un argomento piuttosto che una coda, impostando il suo pubSubDomain proprietà a true.

Ciò significa che si sta andando ad avere bisogno di due JmsTemplate fagioli, uno per la coda, e uno per il tema:

<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

Se si crea la destinazione come un fagiolo di primavera invece di usare il nome di destinazione in il tuo codice, Spring non avrà bisogno di sapere se si tratta di un argomento o di una coda. Altrimenti la soluzione suggerita sopra dovrebbe funzionare pure.

destinazioni AMQ JMS possono essere creati da loro istanziando direttamente:

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

o il recupero da JNDI:

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

preferisco la tecnica JNDI in quanto è più standard.

1

Se è ok per l'utilizzo di una convenzione di denominazione per la coda/argomenti, quindi è possibile implementare un custom 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); 
    } 
} 

e fare riferimento utilizzando JmsTemplate.setDestinationResolver

+0

ha funzionato perfettamente per me. Se aggiungi @Component a DestinationResolver, non hai nemmeno bisogno di impostarlo su JmsTemplate – danielnovy

+0

@danielnovy se hai trovato la risposta utile, un voto in su sarebbe apprezzato :) –