2012-04-26 16 views
6

He buscado y probado todo lo que se me ocurre para solucionarlo, pero Dao en la clase TestService siempre es nulo. Veo los registros de Spring que muestran que se inyecta Dao y la clase TestService. He intentado correr bajo WTP para eclipse, así como directamente en Tomcat. Ambos resultan en el mismo error. ¿Alguien puede ayudarnos a descifrar dónde está el error que hace que el Dao sea nulo en la clase TestService?Jersey + Spring 3 + Maven 3 + Tomcat 7 @Resource en @Component Class son siempre nulos

Versiones:

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 

registro - Mostrando la inyección sucediendo (Corte depurar y nombres de las clases por razones de brevedad)

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 - Excepción de puntero nulo en TestService.java porque TestClassDao es nulo

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> 

ACTUALIZACIÓN: Añadido esto para la aplicación Web, pero no cambia nada

<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 - Lo que creo que es donde el problema puede mentir, una dependencia o algo

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

ACTUALIZACIÓN ACTUALIZADA: Mi amigo echó un vistazo y se dio cuenta de que no tenía el conjunto de parámetros para com.sun.jersey.config.property.packages, una vez que agregamos eso, todo funcionó automágicamente.

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

Respuesta

7

resorte está inyectando un instancia de TestService con un DAO, pero esa instancia no es la que las solicitudes se van a. Está utilizando Jersey ServletContainer para alojar su aplicación Jersey, que no se integra con Spring de ninguna manera. Creará instancias según sea necesario por sí solo, lo que obviamente no será inyectado por Spring (sin hacer ningún bytecode weaving, de todos modos). Recomiendo usar el SpringServlet, que es un ServletContainer que sabe cómo obtener clases de recursos de un contexto Spring. Eso aclarará tu problema.

+0

Gracias por los comentarios, pero era un simple web.xml malo, ver la respuesta actualizada de cómo debido a un amigo que era capaz de arreglarlo – Dennis

+0

Me temo que su actualización está equivocada. No comenzó a funcionar debido a init-param. Está funcionando porque cambiaste a SpringServlet, como dije en mi respuesta. Tu init-param es superfluo. Solo lo usa ServletContainer. SpringServlet obtiene todos sus objetos de Spring. Además, tu valor param es incorrecto. Debe ser "test.service" o "test.service.admin" para encontrar su clase de recurso. Puede probar fácilmente todo lo que he dicho al volver a cambiar a ServletContainer y ver cómo se rompe nuevamente. –

+0

Es malo, ni siquiera lo vi anoche, aunque lo dijiste, aún no lo hice. Supongo que eso es lo que sucede cuando estás trabajando en estar despierto durante 20 horas. Gracias y buena llamada! – Dennis

0

Igual que Ryan señaló: su servlet ServletContainer no sabe acerca del contenedor Spring, por lo que su @Resource/@Autowired nunca recibe la inyección de la dependencia.

Use SpringServlet en su lugar, ya sea agregándolo a web.xml`, o agregándolo a Spring WebInitializer, no a ambos. Ver ejemplos a continuación.

Aquí es ejemplo de código para 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> 

Aquí es ejemplo de código para su encargo 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)); 

    } 

} 

se pueden ver algunas un buen ejemplo de la integración de la primavera + Jersey aquí: http://www.mkyong.com/webservices/jax-rs/jersey-spring-integration-example/