在TomEE中注入EntityManager导致NullPointerException?

时间:2013-05-19 20:32:55

标签: java ejb openejb

这是我的MovieBean.java:

@Stateless
public class MovieBean {

@PersistenceContext
private EntityManager em;

/**
 * Default constructor. 
 */
public MovieBean() {
    // TODO Auto-generated constructor stub
}

public List<Movie> getAllMovies() {
    Query query = em.createQuery("SELECT m FROM Movie m");
    return query.getResultList();
}

我的MoviesServlet像这样使用这个MovieBean:

@WebServlet("/MoviesServlet")
public class MoviesServlet extends HttpServlet {
private static final long serialVersionUID = 1L;

@EJB
private MovieBean mb;

private List<Movie> getMovies() {
    return mb.getAllMovies();
}

在我的doGet方法中,我使用getMovies方法获取所有电影的列表。但是,我有以下例外情况:

javax.ejb.EJBException: The bean encountered a non-application exception; nested exception is: 
java.lang.NullPointerException
org.apache.openejb.core.ivm.BaseEjbProxyHandler.convertException(BaseEjbProxyHandler.java:363)
org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:283)
bg.cinemate.beans.MovieBean$LocalBeanProxy.getAllMovies(bg/cinemate/beans/MovieBean.java)
bg.cinemate.servlets.MoviesServlet.getMovies(MoviesServlet.java:27)
bg.cinemate.servlets.MoviesServlet.doGet(MoviesServlet.java:42)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

java.lang.NullPointerException
bg.cinemate.beans.MovieBean.getAllMovies(MovieBean.java:31)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:181)
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:163)
org.apache.openejb.cdi.CdiInterceptor.invoke(CdiInterceptor.java:126)
org.apache.openejb.cdi.CdiInterceptor.access$000(CdiInterceptor.java:42)
org.apache.openejb.cdi.CdiInterceptor$1.call(CdiInterceptor.java:63)
org.apache.openejb.cdi.CdiInterceptor.aroundInvoke(CdiInterceptor.java:69)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:181)
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:163)
org.apache.openejb.monitoring.StatsInterceptor.record(StatsInterceptor.java:176)
org.apache.openejb.monitoring.StatsInterceptor.invoke(StatsInterceptor.java:95)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:601)
org.apache.openejb.core.interceptor.ReflectionInvocationContext$Invocation.invoke(ReflectionInvocationContext.java:181)
org.apache.openejb.core.interceptor.ReflectionInvocationContext.proceed(ReflectionInvocationContext.java:163)
org.apache.openejb.core.interceptor.InterceptorStack.invoke(InterceptorStack.java:138)
org.apache.openejb.core.stateless.StatelessContainer._invoke(StatelessContainer.java:239)
org.apache.openejb.core.stateless.StatelessContainer.invoke(StatelessContainer.java:191)
org.apache.openejb.core.ivm.EjbObjectProxyHandler.synchronizedBusinessMethod(EjbObjectProxyHandler.java:246)
org.apache.openejb.core.ivm.EjbObjectProxyHandler.businessMethod(EjbObjectProxyHandler.java:241)
org.apache.openejb.core.ivm.EjbObjectProxyHandler._invoke(EjbObjectProxyHandler.java:83)
org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:279)
bg.cinemate.beans.MovieBean$LocalBeanProxy.getAllMovies(bg/cinemate/beans/MovieBean.java)
bg.cinemate.servlets.MoviesServlet.getMovies(MoviesServlet.java:27)
bg.cinemate.servlets.MoviesServlet.doGet(MoviesServlet.java:42)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

我的persistance.xml文件配置如下:

<?xml version="1.0" encoding="UTF-8" ?>
    <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_2_0.xsd"
            version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
            <persistence-unit name="cinema" transaction-type="RESOURCE_LOCAL">
                    <properties>
                            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/cinema" />
                            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
                            <property name="javax.persistence.jdbc.user" value="root" />
                            <property name="javax.persistence.jdbc.password" value="password" />
                            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
                            <property name="eclipselink.ddl-generation.output-mode" value="database" />
                    </properties>

            </persistence-unit>
    </persistence>

我尝试更改它(尝试使用here显示的那个),但它甚至没有启动服务器(即使我尝试将其更改为200秒后仍然超出了时间限制)。 我使用Java7,OpenEJB和TomEE。

编辑1: 我将persistence.xml更改为:

    <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
      <persistence-unit transaction-type="RESOURCE_LOCAL" name="cinema">
        <jta-data-source>java:openejb/Connector/Default JDBC Database</jta-data-source>
        <non-jta-data-source>java:openejb/Connector/Default Unmanaged JDBC Database</non-jta-data-source>
        <class>bg.cinemate.beans.MovieBean</class>

        <properties>
          <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
        </properties>
      </persistence-unit>
    </persistence>

尝试@PersistenceContext(unitName="cinema")并且服务器已启动,但它给了我相同的例外情况。

4 个答案:

答案 0 :(得分:2)

这有几个原因:

  1. 您的班级Movie不是实体。在这种情况下,请发布您的Movie课程代码。检查是否使用@Entity进行了注释。或者在Movie内定义persistence.xml

    我正在查看您的persistence.xml,我在文件中看到MovieBean。这是错的。您的文件中不需要EJB。您需要定义类似于Movie的实体。

    像这样改变:

    <class>YourPackagePath.Movie</class>
    
  2. 您的EJB未受管理。表示您的EJB无法正确部署。在这种情况下,它不会由容器管理,注释查找将失败。检查EJB是否映射到JNDI名称。您可以通过服务器GUI,服务器启动日志或第三方应用程序进行检查。

  3. DataSource的名称有误。

    在此行<jta-data-source>java:openejb/Connector/Default JDBC Database</jta-data-source>中,您无需为java:添加前缀。仅使用DataSource的JNDI名称。再次检查DataSource的JNDI名称是否正确。您可以按照第2点中的说明进行检查。

  4. 不要将JTA和非JTA数据源一起使用。当您不手动处理事务时使用JTA,并且当您需要在代码中手动处理事务时使用非JTA。使用JTA。那应该没问题。

答案 1 :(得分:2)

使用具有类似结构的OpenJPA2时,我遇到了完全相同的问题。 解决我的NullPointer问题的那个问题是将transaction-type="RESOURCE_LOCAL"更改为transaction-type="JTA"。虽然在这种情况下我得到了这个例外:org.apache.openjpa.persistence.PersistenceException: user lacks privilege or object not found

校正: 在我将数据源从tomee正确映射到persistence.xml之后,最后一个异常得到了解决并且所有事务都正常运行

tomee.xml:

<Resource id="mydatabaseDS" type="DataSource">
    JdbcDriver org.postgresql.Driver
    JdbcUrl jdbc:postgresql://localhost:5432/mydatabase
    UserName myuser
    Password mypassword
    JtaManaged true
</Resource>

的persistence.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_2_0.xsd" version="2.0">

    <persistence-unit name="myPU" transaction-type="JTA">
        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
        <jta-data-source>mydatabaseDS</jta-data-source>
    </persistence-unit>
</persistence>

不要忘记将jdbc驱动程序库添加到{tomee} / lib目录中。

答案 2 :(得分:0)

在EJB中尝试:

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

此外,您的文件应该称为persistence.xml,而不是persistance.xml,并且需要位于META-INF文件夹下。

使用RESOURCE_LOCAL数据源时,必须在此文件中提供实体类的名称。

还应在此文件中提供持久性提供程序的名称:

<provider> org.apache.openjpa.persistence.PersistenceProviderImpl </provider>

编辑:当代码在服务器上运行时,确保PersistenceProviderImpl类在类路径上

答案 3 :(得分:0)

我正在开发一个与你的结构类似的项目。这是我和你之间的主要区别

protected static EntityManagerFactory
 em=Persistence.createEntityManagerFactory("cinema");

您可能在MovieBean类中获取空指针异常,因为您尚未创建entitymanager工厂。它没有实例化,这就是为什么你得到空指针异常。此代码尚未在您的情况下进行测试。它对我来说很突出所以我说我会这么说。

编辑: 通过链接查看tomcat网站后,还有

@PersistenceContext(unitName = "cinema", type = PersistenceContextType.EXTENDED)
 private EntityManager em;