2016-10-15 1 views
0

J'utilise Spring 4.3.3 et j'essaie d'écouter un message où le type de destination est sujet.Comment utiliser @JmsListener pour le sujet dans Spring 4

je peux obtenir en xml:

<jms:listener-container connection-factory="connectionFactory" 
         destination-type="topic" 
         message-converter="jackson2MessageConverter"> 
    <jms:listener destination="test.topic" ref="jmsTopicMessageListener1" method="receiveMessage"/> 
    <jms:listener destination="test.topic" ref="jmsTopicMessageListener2" method="receiveMessage"/> 
</jms:listener-container> 

Mais je veux utiliser @JmsListener. au moment où il ne fonctionne que pour comme destination de file d'attente ceci:

@JmsListener(destination = "mailbox", containerFactory = "jmsListenerContainerFactory") 
public void receiveMessage(DataObject dataObject) { 
    System.out.println("Received <" + dataObject.getName() + ">"); 
} 

Comment puis-je écouter un sujet avec cette @JmsListener d'annotation?

Merci d'avance.

MISE À JOUR:

Je l'ai essayé dans la config:

<bean id="topicJmsListenerContainerFactory" 
     class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"> 
    <property name="connectionFactory" ref="cachingConnectionFactory"/> 
    <property name="destinationResolver" ref="jmsDestResolver"/> 
    <property name="concurrency" value="3-10"/> 
    <property name="messageConverter" ref="jackson2MessageConverter"/> 
    <property name="pubSubDomain" value="true"/> 
</bean> 

alors ceci:

@JmsListener(destination = "test.topic", containerFactory = "topicJmsListenerContainerFactory") 
public void receiveMessage(DataObject dataObject) { 
    System.out.println("Received <" + dataObject.getName() + ">" + 1); 
} 

Je peux obtenir les valeurs maintenant, mais j'obtenir des doublons.

Répondre

2

Puisque vous avez corrigé votre configuration (vous recevez des messages), le seul problème à résoudre est le fait que vous recevez des messages en double. Cela est dû à ce morceau de votre config:

<property name="concurrency" value="3-10"/> 

Si vous cochez la javadoc de DefaultMessageListenerContainer (qui JmsListenerContainerFactory étend), vous constaterez que:

... pour un sujet, vous allez généralement coller avec le nombre par défaut de 1 consommateur, sinon vous recevriez le même message plusieurs fois sur le même nœud.

Cela est dû à l'architecture du sujet lui-même, plusieurs consommateurs seront traités comme plusieurs abonnés qui ont besoin de recevoir chaque message qui a été envoyé.

Du côté de la solution:

Vous pourriez avoir besoin de reachitecture votre code un peu. Mais la plupart des cas passant de Topic à VirtualTopic font le travail. Avec VirtualTopics, vous pouvez obtenir un comportement semblable à celui de la file d'attente du côté consommateur, ce qui signifie que les messages seront consommés par un consommateur, de sorte que plusieurs consommateurs ne peuvent pas voir le même message deux fois.

L'autre option consiste bien sûr à déplacer la charge de traitement parallèle vers un autre endroit et d'utiliser un seul consommateur à l'entrée JMS. Selon la tâche à accomplir, cela pourrait aussi être une solution suffisante.

+0

Merci pour la bonne explication. en passant, comment puis-je changer de sujet virtuel? – Ikthiander

+0

Cela dépend de votre configuration actuelle. Courtier intégré/autonome, sujets préconfigurés ou à la volée, etc ... Lisez-les un peu ici: http://activemq.apache.org/virtual-destinations.html Les mettre en place est assez facile, surtout repose simplement sur une convention de nommage de base. –