user130532
user130532

Reputation:

How do I instruct spring to instantiate message listener containers?

I am using Spring 4.2.3 and Java 1.7

I have a unit test

@ContextConfiguration(classes = TestConfiguration.class)
public class TestJmsListener extends AbstractTestNGSpringContextTests {

    @Autowired
    private JmsMessagingTemplate jmsTemplate;

    @Autowired
    @Qualifier("destination")
    private Destination destination;

    @Test
    public void test() {
        assert(jmsTemplate.convertSendAndReceive(destination, "test", Boolean.class));
    }

}

The test invokes the TestConfiguration class, but really that just extends the below configuration. In the TestConfiguration, I merely override the connectionFactory such that it instantiates an embedded activemq broker.

@Configuration
@EnableJms
@ComponentScan("messaging")
@PropertySource(value = "classpath:messaging.properties")
public class CommonMessagingConfiguration {

    // bunch of beans, connection factories, destinations, etc

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setConcurrency("10");
        return factory;
    }

}

The test executes and in the logs I can see that a queue is created for my "test" message. The message is pending on the queue, however, there are no consumers of the queue. Here is my listener implementation:

@Component
public class JmsExampleListener {

    @JmsListener(containerFactory = "jmsListenerContainerFactory",
            destination = "${messaging.destinations.example}")
    public boolean listen(String message) {
        return message != null;
    }
}

When I attach a debugger to DefaultJmsListenerContainerFactory#createContainerInstance() I notice that it is ever hit. However, when I attach one to JmsListenerAnnotationBeanPostProcessor#postProcessAfterInitialization it hits that break point and I can see that spring is detecting my component. Spring instantiates it and registers that instance with it's internal registrar (as I would expect).

The problem it seems is that the containers are never created for the endpoints that are registered. I tried following the Spring example however, they offer no insight.

One thing I noticed was that the Listener post processor has an internal registrar and that has an internal property startImmediately which is false. It seems that it extends the InitializingBean and as such, sets the start property to true which I would presume would start kicking off the containers... However, this does not happen. In fact, if I put a break point on the afterPropertiesSet, it is never invoked. I would assume because the instance in the post processor is not a spring managed bean.

Has anyone tried something similar to what I am doing and had the same issue?

Update

After further investigation, it would seem as though the JmsListenerAnnotationBeanPostProcessor that is instantiated by the @EnableJms isn't having it's afterSingletonsInstantiated invoked after the container is configured. The logic in aforementioned method is what is responsible for constructing the MessageListenerContainer for all the registered endpoints. Why would the afterSingletonsInstantiated not get called? Shouldn't the application context automatically invoke that?

Upvotes: 1

Views: 2097

Answers (1)

user130532
user130532

Reputation:

It turns out that I had a project dependency that was causing the spring-context sources to be version 4.0.9. After I resolved the conflict and effectively had the AbstractApplicationContext from 4.2.3 loaded, the components began working.

Upvotes: 3

Related Questions