Search code examples
javaspring-integrationspring-jms

Spring JMS: replyQosSettings via XML Configuration


I'm using Spring JMS 5.3.6 for an application where I need to set a TimeToLive for my response messages. The application is configured via XML and is using the JMS namespace.

When reading the Spring documentation my guess was that I need to create a JmsListenerContainerFactory instance which I then pass to the listener-container via the factory-id attribute.

But the documentation is not really clear here (or doesn't match the description). Because it states:

You can automatically expose such settings as a JmsListenerContainerFactory by specifying the id of the bean to expose through the factory-id attribute, as the following example shows

But the following example then doesn't contain the factory-id attribute.

This is my current configuration:

  <bean id="replyQosSettings" class="org.springframework.jms.support.QosSettings">
    <constructor-arg name="deliveryMode" value="1"/>
    <constructor-arg name="priority" value="4"/>
    <constructor-arg name="timeToLive" value="300000"/>
  </bean>

  <bean id="jmsListenerContainerFactory" class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="replyQosSettings" ref="replyQosSettings"/>
  </bean>

  <jms:listener-container factory-id="jmsListenerContainerFactory">
    <jms:listener destination="starter.load" ref="starterJmsListener" method="startLoad" concurrency="3" selector="destinationServer = '${hub.name}' OR destinationServer IS NULL"/>
    <jms:listener destination="starter.isLoadRunning" ref="starterJmsListener" method="isRunning" selector="destinationServer = '${hub.name}' OR destinationServer IS NULL"/>
  </jms:listener-container>

But this doesn't work and after hours of debugging I've no idea how to get it working.

I also tried my own MessageListenerContainer implementation with hard-coded replyQosSettings but without success.


Solution

  • See the schema documentation for listener-container...

    Each listener child element will be hosted by a container whose configuration
    is determined by this parent element. This variant builds standard JMS
    listener containers, operating against a specified JMS ConnectionFactory. When
    a factory-id attribute is present, the configuration defined by this element is
    exposed as a org.springframework.jms.config.JmsListenerContainerFactory. It is
    therefore possible to only define this element without any child to just expose
    a container factory.
    

    and

            <xsd:attribute name="factory-id" type="xsd:string">
                <xsd:annotation>
                    <xsd:documentation><![CDATA[
    Expose the settings defined by this element as a org.springframework.jms.config.JmsListenerContainerFactory
    so that they can be reused with other endpoints.
                ]]></xsd:documentation>
                </xsd:annotation>
            </xsd:attribute>
    

    The factory-id is NOT a reference to a container factory, it turns the XML element into a container factory and it should not have any child elements.

    The reply QOS is not supported by the jms xml namespace.

    You need to define your listener container(s) as a <bean /> and set its replyQosSettings property.

    The messageListener should be a MessageListenerAdapter to wrap your listener bean, and set its replyQosSettings property.

    Container factories are normally used for creating containers for methods annotated with @JmsListener.