Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey + Spring 3 + Maven 3 + Tomcat 7 @Resource in @Component Class are always null

I have searched and tried about everything I can think of to fix this but the Dao in the TestService class is always null. I see the Spring logs showing that the Dao is injected as well as the TestService class. I have tried running under WTP for eclipse as well as straight up in Tomcat. Both result in the same error. Can anybody please help decipher where the error is that causes the Dao to be null in the TestService Class.

Versions:

Jersey 1.8
Spring 3.0.5Release
Tomcat apache-tomcat-7.0.27 
Maven  3.0.3 (r1075438; 2011-02-28 12:31:09-0500)
Java 1.6.0_31

Eclipse Java EE IDE for Web Developers. 
Version: Indigo Service Release 2
Build id: 20120216-1857 

Logging - Showing the injection happening (Cut off DEBUG and ClassNames for brevity)

 Creating shared instance of singleton bean 'dataSource' 
 Creating instance of bean 'dataSource' 
 Eagerly caching bean 'dataSource' to allow for resolving potential circular references 
 Finished creating instance of bean 'dataSource' 
 Creating shared instance of singleton bean 'jdbcTemplate' 
 Creating instance of bean 'jdbcTemplate' 
 Eagerly caching bean 'jdbcTemplate' to allow for resolving potential circular references 
 Returning cached instance of singleton bean 'dataSource' 
 Invoking afterPropertiesSet() on bean with name 'jdbcTemplate' 
 Finished creating instance of bean 'jdbcTemplate' 
 Creating shared instance of singleton bean 'testClassDao' 
 Creating instance of bean 'testClassDao' 
Found injected element on class [test.dao.TestClassDao]: AutowiredMethodElement for public void test.dao.TestClassDao.setDataSource(javax.sql.DataSource) 
 Eagerly caching bean 'testClassDao' to allow for resolving potential circular references 
Processing injected method of bean 'testClassDao': AutowiredMethodElement for public void test.dao.TestClassDao.setDataSource(javax.sql.DataSource) 
 Returning cached instance of singleton bean 'dataSource' 
 Autowiring by type from bean name 'testClassDao' to bean named 'dataSource' 
 Finished creating instance of bean 'testClassDao' 
 Creating shared instance of singleton bean 'testService' 
 Creating instance of bean 'testService' 
Found injected element on class [test.service.admin.TestService]: AutowiredFieldElement for test.dao.TestClassDao test.service.admin.TestService.dao 
 Eagerly caching bean 'testService' to allow for resolving potential circular references 
Processing injected method of bean 'testService': AutowiredFieldElement for test.dao.TestClassDao test.service.admin.TestService.dao 
 Returning cached instance of singleton bean 'testClassDao' 
Autowiring by type from bean name 'testService' to bean named 'testClassDao' 
 Finished creating instance of bean 'testService' 

Error - Null Pointer Exception in TestService.java because TestClassDao is null

Apr 25, 2012 9:07:04 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [jersey] in context with path [/test-service]     threw exception
java.lang.NullPointerException
at test.service.admin.TestService.createCompanyProfile(TestService.java:35)

TestClassDao.java

package test.dao;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import test.domain.TestClass;

@Repository
public class TestClassDao {

    private NamedParameterJdbcTemplate namedParamJdbcTemplate;
    private DataSource dataSource;


    @Autowired 
    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
        this.namedParamJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    public void insertTestClass(TestClass testClass)
    {       
        String query = "INSERT INTO TEST_CLASS_TABLE(NAME) VALUES (:NAME)";

        MapSqlParameterSource namedParams = new MapSqlParameterSource();

        mapParams(namedParams, testClass);

        namedParamJdbcTemplate.update(query, namedParams);
    }




    private void mapParams(MapSqlParameterSource  namedParams, TestClass testClass)
    {

            namedParams.addValue("NAME", testClass.getName());

    }
}

TestClass.java

 package test.domain;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.Set;

public class TestClass  implements java.io.Serializable {
    private String name;

    public TestClass(String name){
        this.name = name;

    }

    public String getName() {
        return this.name;
    }
}

TestService.java

package test.service.admin;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Request;
import javax.ws.rs.core.UriInfo;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import test.dao.TestClassDao;
import test.domain.TestClass;

@Path("/resttest")
@Component
public class TestService {
    @Context
    UriInfo uriInfo;
    @Context
    Request request;
    @Autowired 
    TestClassDao dao;

    static Logger log = Logger.getLogger(TestService.class);

    @GET
    @Path("/test")
    public String createCompanyProfile() {

        TestClass test = new TestClass("MyTestName");

        dao.insertTestClass(test);

        return "test done";
    }
}

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">

    <context:annotation-config />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:1234/testClassDatabase" />
        <property name="username" value="user" />
        <property name="password" value="password" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
    </bean>
    <context:component-scan base-package="test"/>
</beans>

web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.container.servlet.ServletContainer
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>  
</web-app>

UPDATE: Added this for the web-app but it didn't change anything

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

pom.xml - Which I think is where the issue may lie, a dependency or something

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test-service</groupId>
    <artifactId>test-service</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>Test Service</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <!-- Jersey -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.19</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>

        <!-- Spring 3 dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${org.springframework.version}</version>
        </dependency>

        <!-- Jersey + Spring -->
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-spring</artifactId>
            <version>${jersey.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-web</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>test-service</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <properties>
        <org.springframework.version>3.0.5.RELEASE</org.springframework.version>
        <jersey.version>1.8</jersey.version>
    </properties>
</project>

UPDATE FIXED: My friend took a look and noticed I didn't have the param set for com.sun.jersey.config.property.packages, once we added that in, everything automagically worked.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:server-context.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
    </listener>
    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
        <init-param>
            <param-name>
                                 com.sun.jersey.config.property.packages
                        </param-name>
            <param-value>service</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>  
</web-app>
like image 887
Dennis Avatar asked Apr 26 '12 00:04

Dennis


1 Answers

Spring is injecting an instance of TestService with a DAO, but that instance isn't the one that requests are going to. You're using Jersey's ServletContainer to host your Jersey app, which doesn't integrate with Spring in any way. It'll be creating instances as needed all on its own, which obviously won't be injected by Spring (without doing some bytecode weaving, anyway). I'd recommend using the SpringServlet, which is a ServletContainer that knows how to get resource classes from a Spring context. That'll clear up your problem.

like image 165
Ryan Stewart Avatar answered Sep 24 '22 14:09

Ryan Stewart