Reputation:
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?
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
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