dimanche 19 avril 2015

Spring attempting to @Autowire my dependencies twice

I have a Spring MVC application in which I'm trying to use @Autowired inside a class annotated with @Controller. In classes without the @Controller annotation, @Autowired works fine, as soon as I add the @Controller annotation, I get an enormous stacktrace at startup which mainly boils down to No qualifying bean of type [com.fasterxml.jackson.databind.ObjectMapper] found for dependency


I'm sensing that Spring is trying to autowire my dependency twice? I'll get to the prove further down in my question ...


In my web.xml, I'm loading both my contextConfigLocation and DispatcherServlet:



....

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext.xml</param-value>
</context-param>

....

<servlet>
<servlet-name>ahpw-api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ahpw-api</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

....


webmvc-config.xml contains just the bare basics to allow me to open up a Jackson JSON API:



<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://ift.tt/GArMu6" xmlns:context="http://ift.tt/GArMu7"
xmlns:mvc="http://ift.tt/1bHqwjR"
xmlns:xsi="http://ift.tt/ra1lAU"
xsi:schemaLocation="http://ift.tt/GArMu6 http://ift.tt/1cMYE2s http://ift.tt/GArMu7 http://ift.tt/1dfrlFf http://ift.tt/1bHqwjR http://ift.tt/1cKeJ91">

<context:component-scan base-package="com.ahpw.api" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

<mvc:default-servlet-handler/>

<mvc:annotation-driven/>

<!-- Cookies Filter to set cookies on JSON AJAX responses -->
<mvc:interceptors>
<bean id="cookieInterceptor" class="com.ahpw.api.controller.COOKIEFilter"/>
</mvc:interceptors>

</beans>


In my applicationContext.xml I have the following:



<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://ift.tt/GArMu6"
xmlns:context="http://ift.tt/GArMu7"
xmlns:rabbit="http://ift.tt/VwJ3iM"
xmlns:xsi="http://ift.tt/ra1lAU"
xsi:schemaLocation="http://ift.tt/GArMu6 http://ift.tt/18sW2ax
http://ift.tt/GArMu7 http://ift.tt/1bGeTcI
http://ift.tt/VwJ3iM http://ift.tt/1ECnZrZ">

<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>

<context:spring-configured/>

<context:component-scan base-package="com.ahpw.api" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Service" type="annotation"/>
</context:component-scan>

<!-- Setup Jackson instance -->
<bean id="jackson" class="com.fasterxml.jackson.databind.ObjectMapper" />

<!-- Setup RabbitMQ -->
<bean id="nativeConnectionFactory" class="com.rabbitmq.client.ConnectionFactory">
<property name="connectionTimeout" value="${rabbit.connection.timeout}"/>
<property name="requestedHeartbeat" value="${rabbit.heartbeat}"/>
</bean>
<rabbit:connection-factory
id="connectionFactory"
port="${rabbit.port}"
virtual-host="${rabbit.virtual}"
host="${rabbit.host}"
username="${rabbit.username}"
password="${rabbit.password}"
connection-factory="nativeConnectionFactory"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:template id="amqpTemplate" connection-factory="connectionFactory" reply-timeout="${rabbit.rpc.timeout}" />


</beans>


My class where the conflict is happening starts like this:



@Service
@Controller
@RequestMapping("/auth")
@JsonIgnoreProperties(ignoreUnknown = true)
public class AuthenticationController extends AbstractRPCPublisher<AuthenticationRequest, AuthenticationResponse> {

@Autowired
AmqpTemplate template;

@Autowired
ObjectMapper mapper;


If I remove @Controller, everything starts up fine, but obviously the request mapping of /auth stops working.


If I put @Controller back and duplicate the jackson bean and rabbitMQ goodies in webmvc-config.xml, it starts up without errors, but it means having two instances of each resource, a copy of the configs in both WEB-INF and META-INF, not desirable.


Is there a way to instantiate my controllers via webmvc-config.xml, but tell it to ignore @Autowired so that my applicationContext can take care of them and if so, will @Autowire function as normal?


Aucun commentaire:

Enregistrer un commentaire