2012-04-26 60 views
6

我已經搜索並嘗試了所有我能想到的方法來解決此問題,但是TestService類中的Dao始終爲空。我看到Spring日誌顯示Dao被注入以及TestService類。我曾嘗試在WTP下運行eclipse以及直接在Tomcat中運行。兩者都導致相同的錯誤。任何人都可以幫助解碼錯誤,導致Dao在TestService類中爲null。Jersey + Spring 3 + Maven 3 + Tomcat 7 @Component類中的資源始終爲空

版本:

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 

記錄 - 顯示注射發生(切斷DEBUG和類名爲了簡潔)

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' 

錯誤 - 空指針異常在TestService.java因爲TestClassDao爲空

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> 

更新:增加了本作的網絡應用程序,但它並沒有改變任何東西

<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的 - 我認爲這是其中的問題可能在於,依賴什麼

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

更新固定:我的朋友看了看,注意到我沒有爲com.sun.jersey.config.property.packages設置參數,一旦我們添加了,一切都自動工作。

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

回答

7

春天注入TestService的一個DAO的實例,但該實例不是請求要去一個。您正在使用Jersey的ServletContainer來託管您的Jersey應用程序,它不以任何方式與Spring集成。它將根據需要自行創建實例,這顯然不會由Spring注入(無論如何不進行字節碼編織)。我建議使用SpringServlet,它是一個ServletContainer,它知道如何從Spring上下文獲取資源類。這將清除你的問題。

+0

感謝您的評論,但它是一個簡單的糟糕的web.xml,請參閱更新的答案,瞭解我的朋友能夠修復它。 – Dennis 2012-04-26 04:38:19

+0

恐怕你的更新是錯誤的。它沒有開始工作,因爲init-param。這是因爲你切換到SpringServlet,就像我在我的回答中所說的那樣。你的init-param是多餘的。它只被ServletContainer使用。 SpringServlet從Spring獲取它的所有對象。此外,你的參數值是錯誤的。它應該是「test.service」或「test.service.admin」以查找您的資源類。您可以輕鬆地測試我所說的所有內容,方法是更換回ServletContainer並觀察它再次中斷。 – 2012-04-26 05:11:24

+0

我的不好我甚至沒有看到昨晚,即使你說我仍然沒有。我想這就是你在工作20小時後會發生什麼。謝謝,很好的電話! – Dennis 2012-04-26 14:15:34

0

同瑞恩指出的 - 你的ServletContainer的servlet不知道Spring容器,所以你@Resource/@Autowired永遠不會被依賴注入。

改爲使用SpringServlet,或者將它添加到web.xml中,或者將它添加到Spring WebInitializer中,而不是兩者都使用。看下面的例子。

這裏的代碼示例web.xml

<servlet> 
    <servlet-name>jersey-spring</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
</servlet> 
<servlet-mapping> 
    <servlet-name>jersey-spring</servlet-name> 
    <url-pattern>/resources/*</url-pattern> 
    <load-on-startup>1</load-on-startup> 
    <init-param> 
     <param-name>com.sun.jersey.config.property.packages</param-name> 
     <param-value>phonebook.rest</param-value> 
    </init-param> 
</servlet-mapping> 

這裏是爲您定製WebInitializer代碼示例:

public class PhonebookApplicationWebInitializer implements WebApplicationInitializer { 

    @Override 
    public void onStartup(ServletContext container) throws ServletException { 

     AnnotationConfigWebApplicationContext factory = new AnnotationConfigWebApplicationContext(); 
     // factory.scan("phonebook.configuration"); 
     factory.register(PhonebookConfiguration.class); 

     ServletRegistration.Dynamic dispatcher = container.addServlet("jersey-spring", new SpringServlet()); 
     dispatcher.setLoadOnStartup(1); 
     dispatcher.addMapping("/resources/*"); 
     dispatcher.setInitParameter("com.sun.jersey.config.property.packages", "phonebook.rest"); 

     container.addListener(new ContextLoaderListener(factory)); 

    } 

} 

你可以看到春+新澤西集成這裏有些一個很好的例子: http://www.mkyong.com/webservices/jax-rs/jersey-spring-integration-example/