[英]How should be EJB Stateless Session Bean correctly injected into the web module?
Being completely new to Java EE (but not to Java itself) I'm trying to build a very simple "Enterprise Application" with Hibernate as JPA provider and JSF as the actual UI framework. 为此,我将 NetBeans 7 与 GlassFish 3.1 一起使用。
{应用程序名称}-ejb:
我已经完成了从这些实体的数据库和本地会话 bean生成实体类。 Beans.xml就位。
@Stateless
public class QuestFacade extends AbstractFacade<Quest> implements QuestFacadeLocal {
// some methods here as well as EntityManager injection ...
}
{应用程序名称}-战争:
我创建了一个简单的 POJO 作为 JSF 页面的支持 bean。 我已经用javax.inject.@Named
和javax.enterprise.context.@SessionScoped
对其进行了注释。 这个支持 bean 现在可以从 JSF 页面访问,并且在访问实际页面时被注入。 Beans.xml也已到位。
@Named
@SessionScoped
public class QuestBean implements Serializable {
@EJB
protected QuestFacade questFacade;
// several methods delegating lookups to the questFacade ...
}
然而,在部署了这个并访问了页面后,我从 GlassFish 收到了一个错误,即 JNDI 无法查找QuestFacade
。
堆栈跟踪很长,但最初的原因可能就足够了:
Caused by: javax.naming.NamingException: Lookup failed for 'model.session.QuestFacade#model.session.QuestFacade' 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: model.session.QuestFacade#model.session.QuestFacade not found]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:173)
... 74 more
Caused by: javax.naming.NameNotFoundException: model.session.QuestFacade#model.session.QuestFacade not found
at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:248)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:215)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:77)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:119)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:505)
... 78 more
我知道我正在说服 GlassFish 从同一应用程序中的不同模块注入 EJB。 应该改用@Remote
接口吗? 我还尝试明确指定@Stateless
和@EJB
注释的名称,但没有任何成功。
我相信我在做一些根本错误的事情,但我不知道是什么。
任何建议或将不胜感激!
我相信我在做一些根本错误的事情,但我不知道是什么。
你做错的是,如果你实现了一个业务接口( @Local
或@Remote
),那么你必须将发生注入的变量声明为具有该接口的类型,而不是实际的 bean class。
所以在你的情况下:
@Named
@SessionScoped
public class QuestBean implements Serializable {
@EJB
protected QuestFacadeLocal questFacade;
// several methods delegating lookups to the questFacade ...
}
但是,当您进行本地(in-jvm)通信时,EJB 中不需要业务接口。 正如您所发现的,如果您根本没有为您的 EJB 指定业务接口,您可以注入 bean class 本身。 这是因为您随后会自动获得所谓的no-interface view
。
如果你愿意,你可以选择声明你想要本地视图和无接口视图。 通过这种方式,您可以将 bean class 注入到任何位置,无论是声明了 bean 类型本身还是它的业务接口。 为此,您使用@LocalBean
。
@Stateless
@LocalBean
public class QuestFacade extends AbstractFacade<Quest> implements QuestFacadeLocal {
// some methods here as well as EntityManager injection ...
}
因此,现在可以通过两种方式进行注入:
@Named
@SessionScoped
public class QuestBean implements Serializable {
@EJB
protected QuestFacadeLocal questFacade; // possible because of local view
@EJB
protected QuestFacade questFacadeN; // possible because of no-interface view
// several methods delegating lookups to the questFacade ...
}
在实践中,我发现同时使用这两种方法并没有多大用处,但也许这会增加你的理解。
显然问题是我生成了@Local
session bean。 根据本教程,不再需要 (?) 指定@Local
或@Remote
接口。 我仍然没有完全理解这个问题。
我希望这个答案可以为某人节省一些时间:-)
雅尔达
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.