java EJB Stateless Session Bean 应该如何正确注入到 web 模块中?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6273047/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How should be EJB Stateless Session Bean correctly injected into the web module?
提问by merxbj
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. For this purposes I'm using the NetBeans 7 with GlassFish 3.1.
作为 Java EE 的新手(但不是 Java 本身),我正在尝试构建一个非常简单的“企业应用程序”,将 Hibernate 作为 JPA 提供程序,将 JSF 作为实际的 UI 框架。为此,我将 NetBeans 7 与 GlassFish 3.1 一起使用。
{ApplicationName}-ejb:
{ApplicationName}-ejb:
I've accomplished to generate entity classesfrom database and local sesssion beansfor these entities. Beans.xmlis in place.
我已经完成了从数据库和本地会话 bean为这些实体生成实体类的工作。Beans.xml已就位。
@Stateless
public class QuestFacade extends AbstractFacade<Quest> implements QuestFacadeLocal {
// some methods here as well as EntityManager injection ...
}
{ApplicationName}-war:
{ApplicationName}-War:
I've created a simple POJO as a backing bean for the JSF page. I've annotated it with javax.inject.@Named
and javax.enterprise.context.@SessionScoped
. This backing bean is now accessible from the JSF page as well as being injected when the actual page is accessed. Beans.xmlis in place as well.
我创建了一个简单的 POJO 作为 JSF 页面的支持 bean。我用javax.inject.@Named
和注释了它javax.enterprise.context.@SessionScoped
。现在可以从 JSF 页面访问这个支持 bean,也可以在访问实际页面时注入它。Beans.xml 也已就位。
@Named
@SessionScoped
public class QuestBean implements Serializable {
@EJB
protected QuestFacade questFacade;
// several methods delegating lookups to the questFacade ...
}
Having this deployed and page accessed, I'm, however, getting an error from GlassFish that the QuestFacade
cannot be looked up by the JNDI.
部署并访问页面后,我收到来自 GlassFish 的错误,即QuestFacade
JNDI 无法查找。
The stacktrace is quite long but the initial cause could be enough:
堆栈跟踪很长,但最初的原因可能就足够了:
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
I understand that I'm persuading GlassFish to inject an EJB from a different module within the same application. Should the @Remote
interface be used instead? I've also tried to explicitely specify the name for both @Stateless
and @EJB
annotation but without any success.
我知道我在说服 GlassFish 从同一应用程序中的不同模块注入 EJB。应该@Remote
改用接口吗?我还尝试明确指定@Stateless
和@EJB
注释的名称,但没有成功。
I believe that I'm doing something fundamentaly wrong, but I cannot find out what.
我相信我在做一些根本错误的事情,但我无法找出是什么。
Any suggestion or would be greatly appreciated!
任何建议或将不胜感激!
回答by Arjan Tijms
I believe that I'm doing something fundamentaly wrong, but I cannot find out what.
我相信我在做一些根本错误的事情,但我无法找出是什么。
What you're doing wrong is that if you implement a business interface (either @Local
or @Remote
), then you must declare the variable where injection takes place as having the type of that interface, not of the actual bean class.
你做错的是,如果你实现了一个业务接口(@Local
或者@Remote
),那么你必须将发生注入的变量声明为具有该接口的类型,而不是实际的 bean 类。
So in your case:
所以在你的情况下:
@Named
@SessionScoped
public class QuestBean implements Serializable {
@EJB
protected QuestFacadeLocal questFacade;
// several methods delegating lookups to the questFacade ...
}
However, a business interface is not required in EJB when you're doing local (in-jvm) communication. As you discovered, if you don't specify a business interface at all for your EJB, you can inject the bean class itself. This is because you then automatically get the so-called no-interface view
.
但是,当您进行本地(jvm 内)通信时,EJB 中不需要业务接口。正如您所发现的,如果您根本没有为 EJB 指定业务接口,您可以注入 bean 类本身。这是因为您随后会自动获得所谓的no-interface view
.
If you want, you can optionally declare that you want BOTH the local view and the no-interface view. In that way, you can inject your bean class in places whether either the bean type itself is declared or its business interface. For this you use the @LocalBean
.
如果需要,您可以选择声明您需要本地视图和无接口视图。通过这种方式,您可以在某些位置注入 bean 类,无论是声明 bean 类型本身还是它的业务接口。为此,您使用@LocalBean
.
@Stateless
@LocalBean
public class QuestFacade extends AbstractFacade<Quest> implements QuestFacadeLocal {
// some methods here as well as EntityManager injection ...
}
Injection can thus happen in two ways now:
因此,注入现在可以通过两种方式发生:
@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 ...
}
In practice I didn't found much use for having both methods available at the same time though, but maybe this adds to your understanding.
在实践中,我没有发现同时使用这两种方法有多大用处,但这可能会增加您的理解。
回答by merxbj
Apparently the problem was that I generated @Local
session beans. Per this tutorialit is no longer necessary (?) to specify the @Local
or @Remote
interface. I still not completely understand the problem though.
显然问题是我生成了@Local
会话 bean。根据本教程,不再需要 (?) 指定@Local
或@Remote
接口。我仍然没有完全理解这个问题。
I Hope this answer could potentialy save up some time to somebody :-)
我希望这个答案可以为某人节省一些时间:-)
Jarda
雅尔达