Uploaded image for project: 'Spring Integration'
  1. Spring Integration
  2. INT-4385

Clarify how to (not) use jms:listener-container with int-jms:message-driven-channel-adapter

    XMLWordPrintable

    Details

      Description

      I was reading the documentation to set up my first int-jms:message-driven-channel-adapter. I was trying to wire it against my jms:listener-container and to specify the desired destination-name when my IDE told me: "The 'destination-name' attribute should not be provided when specifying a 'container' reference.".
      So I was wondering how I could specify the destination, since a listener container with the JMS namespace could be used to set up multiple listeners for different destinations... and I found this:

      The <jms:listener-container/> element is just a convenience. Each <jms:listener /> element gets its own DMLC (with shared attributes defined on the <jms:listener-container/> element). You "can" give each listener element an ID, and use that to inject into the channel adapter, however, the <jms:/> namespace requires a real listener. Since, for Spring Integration, the adapter itself needs to configure the listener, the configured listener will be overwritten. If you go this route, you will see a warning for each adapter...

      Code:

      if (logger.isWarnEnabled() && listenerContainer.getMessageListener() != null)

      Unknown macro: { logger.warn("The provided listener container already has a MessageListener implementation, " + "but it will be overridden by the provided ChannelPublishingJmsMessageListener."); }

      So, generally, you should use the <bean/> configuration you already have. If you want to configure multiple containers (with similar attributes), you can define an abstract <bean/> and set the 'parent' attribute on each DMLC.

      In that topic Gary explains that the logic is exactly the opposite of what I had in my mind.
      I thought that jms:listener-container allowed to set up a container of listeners, so that you could add specific listeners in that container by either using nested jms:listener elements or by using @JmsListener annotations. So I would have expected int-jms:message-driven-channel-adapter to provide a listener for me, after I specify the container ref and the destination name (of course, let's ignore for now the ability of int-jms:message-driven-channel-adapter to create a container listener from scratch on its own).

      Instead, Gary says that jms:listener-container is just a convenience tag that defines a factory, so that the nested jms:listener elements are the actual "containers" which inherit properties from the factory tag (named "container" though) and declare their own destination, while int-jms:message-driven-channel-adapter in its container attribute actually wants a "listener" (which however is a container indeed), not the container (which is a factory) reference!

      This becomes clear when we ignore the jms namespace for a while, and we define our listener container as a bean, since DefaultMessageListenerContainer wants to know also the destination name.

      I think this is quite confusing. Probably the choice made in Spring Framework for names like jms:listener-container, jms:listener and @JmsListener is rather unfortunate. But since the lexicon here is dictated by the Spring Framework, rather than by Spring Integration, I think the name of the container attribute of int-jms:message-driven-channel-adapter should not be changed, but some kind of explanation in the Spring Integration docs of how one should (not) use int-jms:message-driven-channel-adapter with jms:listener-container would be very useful, in order to avoid confusion.

      I would also say that int-jms:message-driven-channel-adapter could be flexible enough to allow to specify both container and destination-name attributes, in order to set up a listener container exactly like the nested jms:listener tag or @JmsListener annotation do, so that the user may combine int-jms:message-driven-channel-adapter and jms:listener-container without using the ugly workaround to define nested jms:listener with "empty" listeners, which also produce warnings on Spring Integration side when they are replaced by the SI adapter implementation.

        Attachments

          Activity

            People

            Assignee:
            abilan Artem Bilan
            Reporter:
            mauromol Mauro Molinari
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: