2012-04-26 10 views
6

Ho cercato e provato su tutto quello che posso pensare per risolvere questo problema ma il Dao nella classe TestService è sempre nullo. Vedo i log di Spring che mostrano che il Dao è stato iniettato così come la classe TestService. Ho provato a correre con WTP per eclipse e anche su dritto in Tomcat. Entrambi danno lo stesso errore. Qualcuno può aiutare a decifrare dove è l'errore che fa sì che il Dao sia nullo nella classe TestService.Jersey + Spring 3 + Maven 3 + Tomcat 7 @Resource in @Component Class sono sempre nulli

Versioni:

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 - Mostrando l'iniezione accadendo (Tagliare DEBUG e classnames per brevità)

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' 

Errore - Null Pointer Exception in TestService.java perché TestClassDao è nullo

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: aggiunte questo per il web-app, ma non ha cambiato nulla

<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 - Che credo è dove il problema può mentire, una dipendenza o qualcosa

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

AGGIORNAMENTO FISSO: il mio amico ha dato un'occhiata e ho notato che non avevo il set param per com.sun.jersey.config.property.packages, una volta aggiunto, tutto funzionava automagicamente.

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

risposta

7

Spring inietta un un'istanza di TestService con DAO, ma tale istanza non è quello che le richieste stanno per. Stai utilizzando Jersey ServletContainer per ospitare la tua app di Jersey, che non si integra con Spring in alcun modo. Creerà le istanze come necessario tutte da sole, che ovviamente non verranno iniettate da Spring (senza comunque eseguire alcune intrecci di bytecode). Ti consigliamo di utilizzare SpringServlet, che è un ServletContainer che sa come ottenere le classi di risorse da un contesto Spring. Questo chiarirà il tuo problema.

+0

Grazie per i commenti, ma si trattava di un semplice web.xml errato, vedere la risposta aggiornata su come a causa di un amico ero in grado di risolverlo. – Dennis

+0

Ho paura che il tuo aggiornamento sia sbagliato. Non ha iniziato a funzionare a causa di init-param. Funziona perché sei passato a SpringServlet, come ho detto nella mia risposta. Il tuo init-param è superfluo. È usato solo da ServletContainer. SpringServlet ottiene tutti i suoi oggetti dalla primavera. Inoltre, il valore param è sbagliato. Dovrebbe essere "test.service" o "test.service.admin" per trovare la classe di risorse. Puoi testare facilmente tutto ciò che ho detto tornando a ServletContainer e guardandolo rompere di nuovo. –

+0

Il mio male non l'ho nemmeno visto la scorsa notte, anche se l'hai detto che non lo avevo ancora fatto. Immagino sia quello che succede quando stai lavorando per stare su per 20 ore. Grazie e buona telefonata! – Dennis

0

Come ha sottolineato Ryan: il servlet ServletContainer non è a conoscenza del contenitore Spring, quindi il tuo @Resource/@Autowired non viene mai iniettato in dipendenza.

Utilizzare invece SpringServlet aggiungendolo a web.xml` o aggiungendolo in Spring WebInitializer, non entrambi. Vedi esempi di seguito.

Ecco esempio di codice per 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> 

Ecco esempio di codice per la vostra abitudine 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)); 

    } 

} 

potete vedere alcuni un bell'esempio su Spring + Jersey integrazione qui: http://www.mkyong.com/webservices/jax-rs/jersey-spring-integration-example/