EJB添加到JNDI,但不能注入@EJB

时间:2015-12-21 13:46:19

标签: java hibernate java-ee ejb tomee

上周,我一直试图抓住Java EE和EJB。

我已经能够创建实体,DAO,持久单元等,但我仍然遇到了一些问题。

在我的项目中,我有一个Author和Book类。反过来,这些有各自的DAO。 (见下文)

问题是,我的EJB正在被创建并正确添加到JNDI树中,只是我似乎无法将它们注入到AuthorAPI REST提供程序中...当我调用AuthorAPI.getAllAuthors方法时,服务器以500错误响应,指向AuthorDAO对象为空。

非常感谢任何帮助!

TomEE日志

INFO: PersistenceUnit(name=libraryPU, provider=org.hibernate.ejb.HibernatePersistence) - provider time 969ms
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=BookDAOLocalBean) --> Ejb(deployment-id=BookDAO)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/BookDAO!org.ucll.rest.dao.BookDAO) --> Ejb(deployment-id=BookDAO)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/BookDAO) --> Ejb(deployment-id=BookDAO)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=AuthorDAOLocalBean) --> Ejb(deployment-id=AuthorDAO)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/AuthorDAO!org.ucll.rest.dao.AuthorDAO) --> Ejb(deployment-id=AuthorDAO)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/AuthorDAO) --> Ejb(deployment-id=AuthorDAO)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=AuthorLocalBean) --> Ejb(deployment-id=Author)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/Author!org.ucll.rest.model.Author) --> Ejb(deployment-id=Author)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/Author) --> Ejb(deployment-id=Author)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=BookLocalBean) --> Ejb(deployment-id=Book)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/Book!org.ucll.rest.model.Book) --> Ejb(deployment-id=Book)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.JndiBuilder bind
INFO: Jndi(name=global/rest-web/Book) --> Ejb(deployment-id=Book)
dec 21, 2015 2:25:53 PM org.apache.openejb.cdi.CdiBuilder initSingleton
INFO: Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@80169cf
dec 21, 2015 2:25:53 PM org.apache.openejb.cdi.OpenEJBLifecycle startApplication
INFO: OpenWebBeans Container is starting...
dec 21, 2015 2:25:53 PM org.apache.openejb.cdi.OpenEJBLifecycle startApplication
INFO: OpenWebBeans Container has started, it took 19 ms.
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Created Ejb(deployment-id=AuthorDAO, ejb-name=AuthorDAO, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Created Ejb(deployment-id=Book, ejb-name=Book, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Created Ejb(deployment-id=Author, ejb-name=Author, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Created Ejb(deployment-id=BookDAO, ejb-name=BookDAO, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Started Ejb(deployment-id=AuthorDAO, ejb-name=AuthorDAO, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Started Ejb(deployment-id=Book, ejb-name=Book, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Started Ejb(deployment-id=Author, ejb-name=Author, container=Default Stateless Container)
dec 21, 2015 2:25:53 PM org.apache.openejb.assembler.classic.Assembler startEjbs
INFO: Started Ejb(deployment-id=BookDAO, ejb-name=BookDAO, container=Default Stateless Container)

HTTP状态500堆栈跟踪

javax.servlet.ServletException: java.lang.NullPointerException
    org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:487)
    org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:425)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:383)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:336)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:223)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

root cause

java.lang.NullPointerException
    org.ucll.rest.web.api.AuthorAPI.getAllAuthors(AuthorAPI.java:25)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:497)
    org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161)
    org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
    org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305)
    org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154)
    org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:471)
    org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:425)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:383)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:336)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:223)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

Author.java

package org.ucll.rest.model;

import java.io.Serializable;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

/**
 *
 * @author larsv
 */
@Entity
@Table(name = "author", schema = "library")
@Stateless
public class Author implements Serializable {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private long id;

    @Column(name = "name", length = 100, nullable = false)
    private String name;

    @OneToMany(mappedBy = "author")
    private List<Book> books;

    public Author() {}

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }
}

Book.java

package org.ucll.rest.model;

import java.io.Serializable;
import javax.ejb.Stateless;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

/**
 *
 * @author larsv
 */
@Entity
@Table(name = "book", schema = "library")
@Stateless
public class Book implements Serializable {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private long id;

    @Column(name = "title", length = 100, nullable = false)
    private String title;

    @ManyToOne
    @JoinColumn(name = "name")
    private Author author;

    public Book() {}

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Author getAuthor() {
        return author;
    }

    public void setAuthor(Author author) {
        this.author = author;
    }
}

AuthorDAO.java

package org.ucll.rest.dao;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.ucll.rest.model.Author;

/**
 *
 * @author larsv
 */
@Stateless
public class AuthorDAO extends AbstractDAO<Author> {
    @PersistenceContext(unitName = "libraryPU")
    private EntityManager em;

    public AuthorDAO() {
        super(Author.class);
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
}

BookDAO.java

package org.ucll.rest.dao;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.ucll.rest.model.Book;

/**
 *
 * @author larsv
 */
@Stateless
public class BookDAO extends AbstractDAO<Book> {
    @PersistenceContext(unitName = "libraryPU")
    private EntityManager em;

    public BookDAO() {
        super(Book.class);
    }

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }
}

AuthorAPI.java

package org.ucll.rest.web.api;

import javax.ejb.EJB;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.ucll.rest.dao.AuthorDAO;
import org.ucll.rest.web.helper.JSONConverter;

/**
 *
 * @author larsv
 */
@Path("/author")
public class AuthorAPI {
    @EJB
    private AuthorDAO authorDAO;

    @GET
    @Path("/all")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getAllAuthors() {
        String json_response = JSONConverter.covertAuthorList(authorDAO.readAll());
        return Response.status(200).entity(json_response).build();
    }
}

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
  <persistence-unit name="libraryPU" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/library</jta-data-source>
    <class>org.ucll.rest.model.Author</class>
    <class>org.ucll.rest.model.Book</class>

    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
      <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
    </properties>
  </persistence-unit>
</persistence>

1 个答案:

答案 0 :(得分:0)

您的@EJB未被解析的原因是您不在EE容器上下文中。 最简单的解决方案是使您的Web服务成为EJB。 这可以通过添加无状态注释来完成:

@Path("/author")
@Stateless
public class AuthorAPI {

在这次改变之后你的dao应该被注入其中。

另外,请注意您的代码的一些提示,可能有助于防止将来出现问题: 你应该为

提供一个getter / setter方法
private AuthorDAO authorDAO;

否则容器无法在运行时注入实现。

相关说明:我不知道您使用的是哪个版本的EJB,但在3.0中为EJB创建接口是必要的。从3.1开始它不再需要了,但我仍然认为最好的做法是编码vs一个接口而不是一个实现类。