2011-01-27 13 views
8

Intentando configurar un proyecto pero falla en el autoenvío de objetos a través de Spring.@ Objetos autoajustados obteniendo un valor nulo

package se.hsr.web; 

public class TestRunner { 

    public static void main(String[] args) { 
     ContactDAO cd = new ContactDAOImpl(); 
     Contact contact = new Contact(); 
     contact.setFirstname("Zorro"); 
     cd.addContact(contact); 
    } 

} 

package se.hsr.web; 

La ejecución de este me da una NullPointerException cuando se invoca cd.addContact. El ContactDaoImpl:

import org.hibernate.SessionFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Repository; 

@Repository 
public class ContactDAOImpl implements ContactDAO { 

    @Autowired 
    private SessionFactory sessionFactory; 

    public void addContact(Contact contact) { 
     sessionFactory.getCurrentSession().save(contact); 
    } 

Mi archivo de servlet:

<?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:p="http://www.springframework.org/schema/p" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    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:component-scan 
     base-package="se.hsr.web"/> 

    <bean id="viewResolver" 
     class="org.springframework.web.servlet.view.UrlBasedViewResolver"> 
     <property name="viewClass" 
      value="org.springframework.web.servlet.view.JstlView" /> 
     <property name="prefix" value="/WEB-INF/jsp/" /> 
     <property name="suffix" value=".jsp" /> 
    </bean> 

    <bean id="propertyConfigurer" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" 
     p:location="/WEB-INF/jdbc.properties" /> 

    <bean id="dataSource" 
     class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" 
     p:driverClassName="${jdbc.driverClassName}" 
     p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" 
     p:password="${jdbc.password}" /> 

    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="configLocation"> 
      <value>classpath:hibernate.cfg.xml</value> 
     </property> 
     <property name="configurationClass"> 
      <value>org.hibernate.cfg.AnnotationConfiguration</value> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">${jdbc.dialect}</prop> 
       <prop key="hibernate.show_sql">true</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="contactDAOImpl" 
     class="se.hsr.web.ContactDAOImpl"/> 

    <context:annotation-config/> 

</beans> 

Mi archivo hibernate.cfg.xml:

<?xml version='1.0' encoding='utf-8'?> 
<!DOCTYPE hibernate-configuration PUBLIC 
    "-//Hibernate/Hibernate Configuration DTD//EN" 
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 

<hibernate-configuration> 
    <session-factory> 
     <mapping class="se.hsr.web.Contact" /> 
    </session-factory> 

</hibernate-configuration> 

Mi archivo web.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    id="WebApp_ID" version="2.5"> 
    <display-name>HSRMVC</display-name> 
    <welcome-file-list> 
     <welcome-file>index.jsp</welcome-file> 
    </welcome-file-list> 

    <servlet> 
     <servlet-name>HSR</servlet-name> 
     <servlet-class> 
      org.springframework.web.servlet.DispatcherServlet 
     </servlet-class> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>HSR</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 
</web-app> 

Supongo que el error es th en SessionFactory no se inicializa mediante @Autowired correctamente, pero ¿por qué? ¿Podría ser un problema simple de estructura de directorio/ruta de acceso o es algo más complicado?

Gracias de antemano.

ACTUALIZACIÓN: clase ContactDAOImpl:

@Repository 
public class ContactDAOImpl extends HibernateDaoSupport implements ContactDAO{ 

    @Autowired 
    @Qualifier("sessionFactory") 
    private SessionFactory sessionFactory; 

    public void addContact(Contact contact) { 
     sessionFactory.getCurrentSession().save(contact); 
    } 
+0

posible duplicado de [¿Por qué es mi primavera @Autowired nula campo ?] (http://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null) – chrylis

Respuesta

14

Para utilizar las funciones de Spring (autovínculo, llamada para publicar métodos de construcción o aspectos), debe dejar que Spring instancia las instancias en lugar de usar new.

Por ejemplo:

public static void main(String[] args) { 
    ApplicationContext context = AnnotationConfigApplicationContext("se.hsr.web") 
    ContactDAO cd = (ContactDAO)context.getBean("contactDAOImpl"); 
    Contact contact = new Contact(); 
    contact.setFirstname("Zorro"); 
    cd.addContact(contact); 
} 

AnnotationConfigApplicationContext explorará las clases en las clases del paquete se.hsr.web a las clases con las anotaciones de la primavera. Requiere Spring 3.0 para funcionar.Antes de que se debe añadir la siguiente línea en su archivo applicationContext.xml:

<context:component-scan base-package="se.hsr.web" /> 
+0

Muchas gracias, pero esto no está haciendo uso de la anotación @Autowired es ¿eso? ¿Hay alguna otra manera de hacer que esto funcione mediante el autoenvío? –

+1

@Emil - Está usando @Autowired. El punto es que las dependencias están auto conectadas, pero que el objeto raíz (ContactDao) necesita ser administrado por resorte para que esto suceda. Si desea que la primavera se autoenriquezca los frijoles cuando usa explícitamente algo nuevo, entonces investigue la anotación @Configurable. – GaryF

+0

¡Gracias por la explicación! Ahora obtengo una NoSuchBeanDefinitionException: no se ha encontrado un bean de tipo [org.hibernate.SessionFactory] para la dependencia: se espera al menos 1 bean que califique como candidato de autowire para esta dependencia. Anotaciones de dependencia: {@ org.springframework.beans.factory.annotation.Autowired (required = true), @ org.springframework.beans.factory.annotation.Qualifier (value = sessionFactory)}. Ahora, como puede ver en el HSR-servlet.xml, se declara el bean sessionFactory. ¿También actualicé la publicación original con mi DAOImpl, que me parece correcto? ¿Qué me estoy perdiendo? –

0

necesita recuperar la instancia de contexto ContactDAO primavera. Se está initiendo con la palabra clave new.

Consulte el siguiente enlace;

@Autowired annotation not able to inject bean in JUnit class

o si no prueba unitaria

ClassPathResource resource = new ClassPathResource("beans.xml"); 
BeanFactory factory = new XmlBeanFactory(resource); 
beanFactory.getBean("nameOfYourBean"); 

http://static.springsource.org/spring/docs/2.0.x/reference/beans.html

+0

¿Podría explicarme un poco sobre cómo quiere decir que debería hacer eso? Intenté reemplazar ContactDAO en el testrunner a @Autowired ContactDAO contactDAO; pero también me dio una NullPointerException. –

+0

Acabo de ver el enlace, lo leeré muchas gracias. –

2

usted necesita esta en la parte superior de su clase de prueba:

@RunWith(SpringJUnit4ClassRunner.class) 
// ApplicationContext will be loaded from "/applicationContext.xml" and "/applicationContext-test.xml" 
// in the root of the classpath 
@ContextConfiguration(locations={"/applicationContext.xml", "/applicationContext-test.xml"}) 
public class MyTest { 

asumí junit4; mi descuido

Necesita la etiqueta de configuración de contexto en un contexto de aplicación en alguna parte, pero no veo ningún lugar en su código donde esté realmente abriendo un archivo de contexto de aplicación y creando un ApplicationContext. Por lo general, eso se hace en un método de configuración para su prueba. Tendrás más suerte si realmente creas un ApplicationContext en alguna parte. Intente leer el XML de su CLASSPATH en un método de instalación y vea si eso ayuda.

+0

Lamento que mi clase haya sido engañosa, no es realmente una clase de prueba, solo una clase llamada TestRunner que he creado para probar la funcionalidad. ¿Se aplica lo de @ContextConfiguration? –

+0

No, necesita en su context.xml según la respuesta de Michael Borgwart. – sourcedelica

+0

Ver mi publicación original para un archivo de configuración de primavera editado. El problema aún persiste. –

1

Esto es necesario en la configuración de la primavera de Autowiring trabajar

xmlns:context="http://www.springframework.org/schema/context" 
.... 
<context:annotation-config/> 
+0

He intentado editar mi configuración de resorte, pero el problema persiste. He editado mi publicación original con la nueva configuración. –

+0

@Emil: bueno, esto es lo que hizo que fallara el autoenvío, pero supongo que también hay otras razones. –

1

Añadir @Component/@Repository a la DAO/DAOImpl.

1

está creando el POJO fuera del contexto de la primavera.

si realmente quiere ser capaz de instanciate "manualmente", puede solucionar este problema, mediante la adición de <context:spring-configured /> a su configuración, y luego anotar con ContactDAOImpl@Configurable

Cuestiones relacionadas