I have a open source project hosted at this github. I am facing a weird scenario. I found many people who could make @Autowired Spring annotation work on their main classes but not on their JUnit test classes. My problem is the other way around. I can successfully use @Autowired in my JUnit test class but when a test calls my main class, the dependencies don't get injected there. Here is my context (simplified version):
Login Class:
package net.openrally.restaurant.core.exposure.resource;
@Path("/login")
@Component
@Transactional
@Singleton
@Produces("application/json")
@Consumes("application/json")
public class Login extends BaseResource{
@Autowired
private UserDAO userDAO;
@POST
public Response post(String requestBody){
...
//NullPointerException
User user = userDAO.loadByCompanyIdAndLogin(companyId, login);
}
...
}
LoginTest Class:
package net.openrally.restaurant.core.exposure.resource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class LoginTest extends BaseResourceTest {
@Autowired
private UserDAO userDAO;
...
@Test
public void testInvalidPassword() {
....
// Works perfectly!
userDAO.save(user);
....
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:configuration.properties</value>
</list>
</property>
</bean>
<context:annotation-config />
<context:component-scan base-package="net.openrally.restaurant.core" />
<import resource="db-config.xml" />
</beans>
I am searching for a solution for a few days now. From what I could find so far, most of the people who have @Autowired problems dont have either <context:annotation-config /> or xmlns:context="http://www.springframework.org/schema/context" in their spring xml or dont have a @Component family annotation in the class they want DI to take place, and as you can see, they are both there :(. I have only one applicationContext.xml in my project which suits for both runtime and test (I have distinct configuration.properties to set database credentials and log levels differently, but no spring configuration there)
I'm using:
Spring: 3.1.0.RELEASE
JUnit: 4.10
Jersey: 1.11
CLIB: 2.2.2
Any ideas, and I mean ANY :), is much appreciated.
UPDATE
The following logs come up when I run the test:
2012-03-27 07:37:02,457 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'login'
2012-03-27 07:37:02,457 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'login'
2012-03-27 07:37:02,459 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Found injected element on class [net.openrally.restaurant.core.exposure.resource.Login]: AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.ConfigurationDAO net.openrally.restaurant.core.exposure.resource.Login.configurationDAO
2012-03-27 07:37:02,459 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Found injected element on class [net.openrally.restaurant.core.exposure.resource.Login]: AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.UserDAO net.openrally.restaurant.core.exposure.resource.Login.userDAO
2012-03-27 07:37:02,459 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'login' to allow for resolving potential circular references
2012-03-27 07:37:02,459 TRACE [main] org.springframework.beans.CachedIntrospectionResults - Getting BeanInfo for class [net.openrally.restaurant.core.exposure.resource.Login]
2012-03-27 07:37:02,462 TRACE [main] org.springframework.beans.CachedIntrospectionResults - Caching PropertyDescriptors for class [net.openrally.restaurant.core.exposure.resource.Login]
2012-03-27 07:37:02,462 TRACE [main] org.springframework.beans.CachedIntrospectionResults - Found bean property 'class' of type [java.lang.Class]
2012-03-27 07:37:02,462 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'login': AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.ConfigurationDAO net.openrally.restaurant.core.exposure.resource.Login.configurationDAO
2012-03-27 07:37:02,462 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'configurationDAO'
2012-03-27 07:37:02,462 DEBUG [main] org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'login' to bean named 'configurationDAO'
2012-03-27 07:37:02,463 DEBUG [main] org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'login': AutowiredFieldElement for private net.openrally.restaurant.core.persistence.dao.UserDAO net.openrally.restaurant.core.exposure.resource.Login.userDAO
2012-03-27 07:37:02,463 DEBUG [main] org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userDAO'
2012-03-27 07:37:02,463 DEBUG [main] org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 'login' to bean named 'userDAO'
2012-03-27 07:37:02,464 DEBUG [main] org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator - Creating implicit proxy for bean 'login' with 0 common interceptors and 1 specific interceptors
2012-03-27 07:37:02,464 DEBUG [main] org.springframework.aop.framework.Cglib2AopProxy - Creating CGLIB2 proxy: target source is SingletonTargetSource for target object [net.openrally.restaurant.core.exposure.resource.Login@60532a0a]
2012-03-27 07:37:02,465 DEBUG [main] org.springframework.aop.framework.Cglib2AopProxy - Unable to apply any optimisations to advised method: public javax.ws.rs.core.Response net.openrally.restaurant.core.exposure.resource.Login.post(java.lang.String)
Could Spring be creating my bean correctly but Jersey using its own non-autowired instance?
@Componentand@Singletonon your bean ? And how is loaded yourapplicationContext.xmlfile for runtime ? - ndeverge@Singletonis just an optimization. I tried removing it after your comment but no luck... TheappliationContext.xmlis in the resources folder and project has spring dependencies controlled by maven. I plan to use jetty as a web container but for the tests I am using Grizzly Web Container from Jersey. - robertobadoapplicationContext.xmlfile is loaded in your runtime app ? By aClassPathXmlApplicationContext? By a webapp ? - ndevergeContextLoaderListener: static.springsource.org/spring/docs/2.5.x/reference/… - ndeverge