2009-05-20 11 views
7

En el siguiente código tengo problemas con mi EnitityManager inyectado, que siempre aparece como nulo;¿Cómo reparar Null EntityManger en la aplicación Spring MVC?

public class GenericController extends AbstractController { 

    @PersistenceContext(unitName = "GenericPU") 
    private EntityManager em; 

    protected ModelAndView handleRequestInternal(
      HttpServletRequest request, 
      HttpServletResponse response) throws Exception { 
     //(em == null) is always trigged 
     if (em == null) throw new NullPointerException("em is null"); 
     Collection<Generic> Generics = em.createNamedQuery("Generic.findAll").getResultList(); 

     ModelAndView mav = new ModelAndView("Generic"); 
     mav.addObject(Generics); 
     return mav; 
    } 
} 

Aquí está la definición de frijol, que se define en despachador-servlet.xml.

<bean id="Generic" class="com.application.web.GenericController" /> 

EnitityManager debe inyectarse basado en TX: anotación basan, definido en el archivo persistencia-context.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: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-2.5.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> 
     <property name="url" value="removed" /> 
     <property name="username" value="removed" /> 
     <property name="password" value="removed" /> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="persistenceUnitName" value="GenericPU" /> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="jpaDialect"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
     </property> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="showSql" value="true" /> 
       <property name="generateDdl" value="false" /> 
       <property name="databasePlatform" value="org.hibernate.dialect.SQLServerDialect" /> 
      </bean> 
     </property> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory"/> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> 

    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 

</beans> 

La persistencia del contexto se carga desde el 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-2.5.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">  
    <import resource="classpath:META-INF/persistence-context.xml"/> 
</beans> 

La ruta de clases de importación se hace porque las entidades ORM se incluyen como un archivo JAR en el proyecto. Tenga en cuenta que creo que el contexto de persistencia se está cargando, ya que Spring no permitirá que la aplicación se implemente si no puede analizar sus archivos de configuración.

Aquí está mi persistence.xml.

<?xml version="1.0" encoding="UTF-8"?> 
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> 
    <persistence-unit name="CoolOrmJpaPU" transaction-type="RESOURCE_LOCAL"> 
    <class>com.application.orm.jpa.Generic</class> 
    <!-- bunch more classes --> 
    </persistence-unit> 
</persistence> 

Y mi Web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/applicationContext.xml</param-value> 
    </context-param> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <servlet> 
     <servlet-name>dispatcher</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <load-on-startup>2</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>*.htm</url-pattern> 
    </servlet-mapping> 
    <session-config> 
     <session-timeout> 
      30 
     </session-timeout> 
    </session-config> 
    <welcome-file-list> 
     <welcome-file>redirect.jsp</welcome-file> 
    </welcome-file-list> 
</web-app> 

¿Puede alguien ayudarme aquí?

+0

¿Cómo hace referencia a persistence-context.xml desde application-context.xml? ¿Usando importación? – Mark

+0

Mark, lo he agregado para usted. Lo siento, quería excluir detalles, pero hay tanta configuración aquí que no quería incluir todo. –

Respuesta

8

Tuve la suerte de poder hablar con un asesor sobre este tema, él fue capaz de ayudarme a resolver todo.

Así que mi problema es que Spring MVC estaba estableciendo dos contextos distintos, un contexto de aplicación, definido en applicationContext.xml y un contexto web, definido en dispatcher-servlet.xml.

Los beans de un contexto no pueden hablar con beans en otro contexto, por lo tanto, cuando inicié mi contexto de persistencia dentro de applicationContext.xml, no pude acceder a él en beans cargados por dispatcher-servlet.xml, es decir, mis controladores.

Cuando Netbeans auto-generó la base para mi Spring MVC configuró esto por defecto. En algunas aplicaciones web grandes, tendría sentido separar la parte web de la aplicación en un contexto distinto del resto de la lógica (persistencia, código comercial, etc.). En mi caso, cuando intento inyectar automáticamente mi administrador de entidades directamente en mis controladores, esto funcionó en mi contra.

Para solucionar el problema que se trasladó la línea

<import resource="classpath:META-INF/persistence-context.xml"/> 

Desde el applicationContext.xml, a mi despachador-servlet.xml. Luego, mis controladores se inyectaron correctamente con EntityManagers a partir de la anotación @PersistanceContext.

+0

Todo el proceso de configuración XML para la capa web se describe en el manual de referencia de Spring, capítulo 13: http://static.springframework.org/spring/docs/2.5.x/reference/mvc.html – MetroidFan2002

+0

Er, perdón, no solo la configuración de XML, sino la configuración en general, ¿dónde está el botón editar comentario ya? – MetroidFan2002

+0

Entonces, ¿cómo lo resolvió? Tal como lo entiendo, ApplicationContext sirve como el contexto "raíz" o "principal" para el contexto de dispatcherServlet (y para todos los demás contextos), por lo que todos los beans definidos en el contexto de la aplicación deberían estar disponibles. p.ej. Los controladores generalmente tienen inyectados otros beans @Service o @Component, que se pueden definir en applicationContext. Entonces, tu respuesta realmente no explica por qué no estaba funcionando para ti. –

0

Creo que se necesita un archivo persistence.xml:

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

    <persistence-unit name="GenericPU"> 
    <class>com.domain.MyClass</class> 
    </persistence-unit> 

</persistence> 

creo que no va a funcionar si el archivo tiene un nombre diferente, sobre todo, no ya no le dice a la fábrica EntityManager el nuevo nombre en ninguna parte.

+0

Tengo un persistence.xml, lo dejé porque no pensé que sería crítico para el problema. –

+0

Disculpa porque lo he agregado a la pregunta. –

0

Yo solía trabajar con una versión primaveral mayor, cuando había que poner setProperty() para el grano y establecer la etiqueta Propery dentro de la definición de frijol primavera como:

<bean id="Generic" class="com.application.web.GenericController" /> 
    <property name="em" ref="entityManager" /> 
</bean> 

tal vez debería trabajar con el transactionManager o los beans de entityManagerFactory ...

PD: Personalmente prefiero la forma antigua de inyectar dependencias.

0

Ha incluido

<context:annotation-config /> 

En el código XML primavera. Referencia here

+0

No tengo eso, pero creo que está activado implícitamente al establecer tx: anotado por la anotación. –