PersistenceContext EntityManager injection NullPointerException

j'ai une guerre contenant le texte suivant:

META-INF/MANIFEST.MF
WEB-INF/classes/META-INF/persistence.xml
WEB-INF/classes/com/test/service/TestServlet.class
WEB-INF/classes/com/test/service/TestEntity.class
WEB-INF/classes/jndi.properties
WEB-INF/classes/postgresql-ds.xml
WEB-INF/jboss-web.xml
WEB-INF/web.xml
index.jsp

la persistance.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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" version="1.0">
    <persistence-unit name="test">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/TestDS</jta-data-source>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

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>
  <display-name>Test Web Application</display-name>

    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>
    <listener>
        <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
    </listener>
    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>

    <resource-ref>
        <res-ref-name>TestDS</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
</web-app>

ma classe TestServlet est la suivante:

package com.test.service;

import java.util.*;
import javax.persistence.*;
import javax.ws.rs.*;

@Path("/service")
public class TestService {

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

    @GET
    @Path("/get")
    @Produces("application/json")
    public List get() {
        return em.createQuery("from TestEntity").getResultList();
    }
}

quand la méthode get() est invoquée je reçois une NullPointerException; le EntityManager n'a pas été injecté. Des suggestions sur ce que je pourrais manquer ou comment je peux le diagnostiquer? Il y a très peu dans le journal du serveur.

je suis sûr que j'ai eu ce travail sans le jboss-web.xml ou l'entrée datasource dans web.XML. J'ai déployé le ds.xml vers le répertoire deploy aussi séparément et c'est définitivement repris - je peux le voir dans la console JMX.

a essayé D'utiliser JBoss 4.2.3 et un build 6.0 avec le même résultat.

41
demandé sur Mohammad Faisal 2011-01-17 00:05:26

2 réponses

un gestionnaire d'entité ne peut être injecté que dans des classes s'étendant à l'intérieur d'une transaction. En d'autres termes, il ne peut être injecté que dans une EJB. Les autres classes doivent utiliser un EntityManagerFactory pour créer et détruire un EntityManager.

puisque votre service de test n'est pas un EJB, l'annotation @PersistenceContext est simplement ignorée. Non seulement cela, dans JavaEE 5, il n'est pas possible d'injecter un EntityManager ni un EntityManagerFactory dans un Service JAX-RS. Vous devez aller avec un Serveur JavaEE 6 (JBoss 6, Glassfish 3, etc).

voici un exemple d'injection D'une EntityManagerFactory:

package com.test.service;

import java.util.*;
import javax.persistence.*;
import javax.ws.rs.*;

@Path("/service")
public class TestService {

    @PersistenceUnit(unitName = "test")
    private EntityManagerFactory entityManagerFactory;

    @GET
    @Path("/get")
    @Produces("application/json")
    public List get() {
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        try {
            return entityManager.createQuery("from TestEntity").getResultList();
        } finally {
            entityManager.close();
        }
    }
}

la façon la plus simple d'aller ici est de déclarer votre service comme EJB 3.1, en supposant que vous utilisez un serveur JavaEE 6.

question connexe: injecter un EJB dans JAX-RS (RESTful service)

73
répondu Andre Rodrigues 2017-05-23 10:30:59

si le composant est un EJB, alors, il ne devrait pas y avoir de problème d'injection D'un EM.

mais ... Dans JBoss 5, l'intégration JAX-RS n'est pas bonne. Si vous avez un EJB, vous ne pouvez pas utiliser la numérisation et vous devez lister manuellement dans le contexte-param resteasy.jndi.ressources. Si vous avez encore le scan, Resteasy va scanner pour la classe de ressource et l'enregistrer comme un service JAX-RS à la vanille et gérer le cycle de vie.

C'est probablement le problème.

2
répondu Bill Burke 2012-10-26 07:59:59