EJB 3.1依赖注入失败

4

我创建了一个无状态会话 bean,就像这样:

@WebServlet(name = "ProductController", urlPatterns = {"/ProductController"})
public class ProductController extends HttpServlet {

  @EJB
  private ProductFacadeBean productBean;
}

@Stateless
public class ProductFacadeBean extends AbstractFacade<Product> implements ProductFacadeLocalInterface {
  @PersistenceContext(unitName = "OnlineStorePU")
  private EntityManager em;

  protected EntityManager getEntityManager() {
    return em;
  }

  public ProductFacadeBean() {
    super(Product.class);
  }

}

@Local
public interface ProductFacadeLocalInterface {

  void create(Product product);

  void edit(Product product);

  void remove(Product product);

  Product find(Object id);

  List<Product> findAll();

  List<Product> findRange(int[] range);

  int count();

}


public abstract class AbstractFacade<T> {
  private Class<T> entityClass;

  public AbstractFacade(Class<T> entityClass) {
    this.entityClass = entityClass;
  }

  protected abstract EntityManager getEntityManager();

  public void create(T entity) {
    getEntityManager().persist(entity);
  }

  public void edit(T entity) {
    getEntityManager().merge(entity);
  }

  public void remove(T entity) {
    getEntityManager().remove(getEntityManager().merge(entity));
  }

  public T find(Object id) {
    return getEntityManager().find(entityClass, id);
  }

  public List<T> findAll() {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityClass));
    return getEntityManager().createQuery(cq).getResultList();
  }

  public List<T> findRange(int[] range) {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityClass));
    javax.persistence.Query q = getEntityManager().createQuery(cq);
    q.setMaxResults(range[1] - range[0]);
    q.setFirstResult(range[0]);
    return q.getResultList();
  }

  public int count() {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    javax.persistence.criteria.Root<T> rt = cq.from(entityClass);
    cq.select(getEntityManager().getCriteriaBuilder().count(rt));
    javax.persistence.Query q = getEntityManager().createQuery(cq);
    return ((Long) q.getSingleResult()).intValue();
  }

}

问题:

  1. 这个错误是什么?如何解决?

    javax.naming.NamingException: 在SerialContext中查找'java:comp/env/Controller.ProductController/productBean'失败,myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming},根异常是javax.naming.NamingException: 为'Remote ejb-ref name=Controller.ProductController/productBean,Remote 3.x interface=EJB.ProductFacadeBean,ejb-link=null,lookup=,mappedName=,jndi-name=EJB.ProductFacadeBean,refType=Session'解析EJB时出现异常。实际(可能是内部)用于查找的远程JNDI名称是'EJB.ProductFacadeBean#EJB.ProductFacadeBean',根异常是javax.naming.NamingException: 在SerialContext中查找'EJB.ProductFacadeBean#EJB.ProductFacadeBean'失败,myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming},根异常是javax.naming.NameNotFoundException: 找不到EJB.ProductFacadeBean#EJB.ProductFacadeBean。

完整的异常信息请参考以下内容:

HTTP Status 500 -

type Exception report

message

descriptionThe server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: PWC1392: Error instantiating servlet class Controller.ProductController

root cause

com.sun.enterprise.container.common.spi.util.InjectionException: Error creating managed object for class Controller.ProductController

root cause

com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=Controller.ProductController/productBean,Remote
3.x interface =EJB.ProductFacadeBean,ejb-link=null,lookup=,mappedName=,jndi-name=EJB.ProductFacadeBean,refType=Session into class Controller.ProductController

root cause

javax.naming.NamingException: Lookup failed for 'java:comp/env/Controller.ProductController/productBean' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=Controller.ProductController/productBean,Remote
3.x interface =EJB.ProductFacadeBean,ejb-link=null,lookup=,mappedName=,jndi-name=EJB.ProductFacadeBean,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'EJB.ProductFacadeBean#EJB.ProductFacadeBean' [Root exception is javax.naming.NamingException: Lookup failed for 'EJB.ProductFacadeBean#EJB.ProductFacadeBean' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: EJB.ProductFacadeBean#EJB.ProductFacadeBean not found]]]

root cause

javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=Controller.ProductController/productBean,Remote
3.x interface =EJB.ProductFacadeBean,ejb-link=null,lookup=,mappedName=,jndi-name=EJB.ProductFacadeBean,refType=Session' .  Actual (possibly internal) Remote JNDI name used for lookup is 'EJB.ProductFacadeBean#EJB.ProductFacadeBean' [Root exception is javax.naming.NamingException: Lookup failed for 'EJB.ProductFacadeBean#EJB.ProductFacadeBean' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: EJB.ProductFacadeBean#EJB.ProductFacadeBean not found]]

root cause

javax.naming.NamingException: Lookup failed for 'EJB.ProductFacadeBean#EJB.ProductFacadeBean' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: EJB.ProductFacadeBean#EJB.ProductFacadeBean not found]

root cause

javax.naming.NameNotFoundException: EJB.ProductFacadeBean#EJB.ProductFacadeBean not found

note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.1 logs. GlassFish Server Open Source Edition 3.1
  1. 当我使用NetBeans创建实体bean的会话时,它为我们创建了抽象外观模式?这有什么用?我知道外观模式是作为接口来路由请求的。
  2. ejb-jar.xml的用途是什么?

所有设置都是默认的。EJB bean是在Java EE 6 Web应用程序内部创建的,而不是在另一个WAR或JAR中。Glassfish 3.1服务器。

请帮忙。

谢谢。


1
希望有人能在这个话题上给予帮助。 - nicholas
通过注入接口而不是具体类解决的问题。 - nicholas
1
为什么将ProductBean更改为@EJB private ProductFacadeLocalInterface productBean就可以工作了呢? - nicholas
1
如果接口被两个具体类所实现,容器如何知道应该实例化哪个类? - nicholas
你得到了关于你上一个问题的任何答案吗? - Unda
2个回答

6
你需要通过引用bean的接口而不是直接引用它的实现来进行注入。像这样...
@EJB
private ProductFacadeLocalInterface productBean;

您可以使用在ProductFacadeLocalInterface中公开的接口方法来访问bean。


为什么不直接注入实现而不是它的接口呢?如果有两个类,那么我需要将一个类标记为高级。 - nicholas
当一个EJB,在你的情况下是一个无状态的bean,实现了任何本地/远程接口时,需要使用接口来访问。在JavaEE6和EJB3.1中,可以拥有无接口的bean,并直接注入实现,但出于设计和可维护性的原因,应该避免这样做。 - aseychell
@aseychell,那peterwkc的问题呢?如果你有两个实现接口的EJB,容器如何知道选择哪一个? - Unda
@Unda,你不能这样做。你需要为每个无状态的bean创建一个本地接口来扩展公共接口。 - garfield

5

您必须使用接口。如果您使用 Seam SolderCDI,则可以使用精确的实现。

@Inject
@Exact(ProductFacadeBean.class)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接