Issue
I am trying to send the output from a spring batch process to RabbitMQ. To avoid hard dependency on Rabbitmq, I used spring-integration as suggested in Is there an API in spring-xd to write to a message bus?. I had everything working fine with messages being pushed to RabbitMQ, until I decided to autowire or instantiate the beans via Spring.
<context:component-scan base-package="com.test.*"/>
<channel id="input" />
<rabbit:connection-factory id="connectionFactory" />
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
exchange="testExchange" routing-key="foo.bar" />
<rabbit:admin connection-factory="connectionFactory" />
<rabbit:queue name="testQueue" id="timeseriesQueue" />
<rabbit:topic-exchange name="testExchange"
id="testExchange">
<rabbit:bindings>
<rabbit:binding queue="testQueue" pattern="foo.*" />
</rabbit:bindings>
</rabbit:topic-exchange>
<!-- Send message to rabbitmq -->
<gateway id="testGateway"
service-interface="com.test.TestService"
default-request-channel="input" />
<amqp:outbound-channel-adapter channel="input"
amqp-template="amqpTemplate" exchange-name="testExchange"
routing-key="foo.bar" />
The testService is just an interface with the method sendMessage.
The spring batch job has an itemWriter, which uses the gateway bean to write to RabbitMQ
In the write method of itemWriter, when I instantiated the bean using ApplicationContext, like below, it worked well
AbstractApplicationContext ctx =
new ClassPathXmlApplicationContext("META-INF/spring/integration/rabbit.xml");
TestService service = ctx.getBean("testGateway", TestService.class);
service.sendMessage(items);
ctx.close();
However, when I tried to autowire it, like below:
@Autowired
TestService service;
I get the following exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.test.TestService com.test.TransportItemWriter.testGateway; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.TestService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
... 22 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.test.TestService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1103)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:963)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 24 more
I tried looking around, but most examples (in spring-integration samples) of Gateway invoke it via ApplicationContext. I found http://java.dzone.com/articles/spring-integration-gateways-1, and added whatever annotation I thought I was missing, but could not get it working.
Any pointers are greatly appreciated.
Solution
Autowiring is functionally equivalent to getting the bean from the context (unless there's more than one instance, in which case, you need the right variable name, or a @Qualifier
), but that would give you a different error. Is the gateway in the same context as the ItemWriter
?
`META-INF/spring/integration/rabbit.xml`
implies it's in its own context. Are you <import/>
ing in into your job context?
I usually debug issues like this by turning on debug logging for org.springframework
; it emits copious logs for bean wiring.
Another good debug technique is to @Autowire
the ApplicationContext
and print out ctx.getBeanFactory().toString()
.
Answered By - Gary Russell