Vraag Hoe publiceert u een JMS-onderwerp met Spring JMS?


Ik heb een component die berichten naar een wachtrij verzendt om door een ander systeem te worden verwerkt. Het zou ook eens in de zoveel tijd een onderwerp over jobstatussen moeten publiceren. Kan ik dezelfde JmsTemplate gebruiken die wordt gebruikt om naar een wachtrij te verzenden EN om te publiceren naar een onderwerp?

Ik heb een nieuw onderwerp in ActiveMQ gemaakt, behalve dat wanneer ik vanuit JmsTemplate een bericht verzend, een nieuwe wachtrij met de onderwerpnaam wordt gemaakt met het verzonden bericht (in plaats van de gegevens naar het daadwerkelijke onderwerp te verzenden), wat doe ik hier verkeerd?

hier is mijn 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 is de klasse die ik gebruik om een ​​wachtrijbericht te verzenden (en het werkt), kan ik dat ook gewoon gebruiken om een ​​onderwerp te publiceren?

Kan ik dit gewoon gebruiken om zowel wachtrij verzenden als onderwerp publiceren te doen ?:

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

15
2017-08-19 02:32


oorsprong


antwoorden:


Dit lijkt misschien een beetje vreemd, je moet JmsTemplate vertellen dat het een onderwerp is in plaats van een wachtrij, door zijn pubSubDomain eigendom aan true.

Dat betekent dat je er twee nodig hebt JmsTemplate bonen, één voor de wachtrij en één voor het onderwerp:

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

30
2017-08-19 07:40



Als u de bestemming als springboon aanmaakt in plaats van de bestemmingsnaam in uw code te gebruiken, hoeft Spring niet te weten of het een onderwerp of een wachtrij is. Anders zou de hierboven voorgestelde oplossing ook moeten werken.

AMQ JMS-bestemmingen kunnen worden gemaakt door deze direct te instantiëren:

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

of ophalen bij JNDI:

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

Ik geef de voorkeur aan de JNDI-techniek omdat deze meer standaard is.


5
2017-08-20 12:53



Als het oké is dat u een naamgevingsconventie gebruikt voor wachtrij / onderwerpen, dan kunt u een aangepast gebruiken 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);
   }
}

en verwijs ernaar met JmsTemplate.setDestinationResolver


2
2017-10-07 14:53