Search code examples
spring-mvcjndi

DataSource not injected to @Resource annotated field with alwaysUseJndiLookup setting


I've just read about @Resource annotation from this article (http://www.infoq.com/articles/spring-2.5-part-1) and wish to use it on Tomcat 6.0.26 and Spring 3.0.3

But it does not work -- field ds in Users class does not initialized and I've got NullPointerException when I try to made a query.

File src/org/example/db/Users.java

package org.example.db;
import javax.sql.DataSource;
import javax.annotation.Resource;

@Repository
public class Users {

 @Resource private DataSource ds;
 ...
}

File WEB-INF/spring-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:jee="http://www.springframework.org/schema/jee"
 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/jee
 http://www.springframework.org/schema/jee/spring-jee-2.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 <context:component-scan base-package="org.example.web.controller,org.example.db" />

 <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor">
  <property name="alwaysUseJndiLookup" value="true" />
 </bean>

 <jee:jndi-lookup id="ds" jndi-name="java:comp/env/jdbc/mydb" />

</beans>

File WEB-INF/web.xml

 <resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/mydb</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
 </resource-ref>

In log file:

DEBUG 2010-09-27 21:56:00,085: Creating shared instance of singleton bean 'ds'
DEBUG 2010-09-27 21:56:00,085: Creating instance of bean 'ds'
DEBUG 2010-09-27 21:56:00,086: Eagerly caching bean 'ds' to allow for resolving potential circular references
DEBUG 2010-09-27 21:56:00,106: Invoking afterPropertiesSet() on bean with name 'ds'
DEBUG 2010-09-27 21:56:00,116: Finished creating instance of bean 'ds'
DEBUG 2010-09-27 21:56:00,149: Found injected element on class [org.example.db.Users]: ResourceElement for private javax.sql.DataSource org.example.db.Users.ds
DEBUG 2010-09-27 21:56:00,152: Found injected element on class [org.example.db.Users]: ResourceElement for private javax.sql.DataSource org.example.db.Users.ds
DEBUG 2010-09-27 21:56:00,161: Processing injected method of bean 'users': ResourceElement for private javax.sql.DataSource org.example.db.Users.ds
DEBUG 2010-09-27 21:56:00,163: Returning cached instance of singleton bean 'ds'
DEBUG 2010-09-27 21:56:00,442: Returning cached instance of singleton bean 'ds'
DEBUG 2010-09-27 21:56:00,593: Rejected bean name 'ds': no URL paths identified
DEBUG 2010-09-27 21:56:00,738: Rejected bean name 'ds': no URL paths identified

I don't know why it does not work. I found in documentation this:

NOTE: A default CommonAnnotationBeanPostProcessor will be registered by the "context:annotation-config" and "context:component-scan" XML tags. Remove or turn off the default annotation configuration there if you intend to specify a custom CommonAnnotationBeanPostProcessor bean definition!

I think it may be about my problem, but in this case I don't know how to "Remove or turn off the default annotation configuration".

Please help. Thanks in advance!


Solution

  • For now this issue is resolved.

    All this code works, but I think the problem was in some of the related classes. For example, I have following autowiring hierarchy: dataSource injects to Users class, Users class injects to Validator, Validator is called from Controller. In this chain were a few bugs:

    • Users are created using a new Validator instance
    • after @Autowiring propagation, User did not inject to Validator because this class was in another package and component-scan not find it
    • later User did not inject to Validator because this class does not have @Component annotation
    • Controller creates new instance of Validator using the default constructor

    After I resolve all these issues all works fine.