Java EE 7:如何将 EJB 注入 WebSocket ServerEndpoint?

Posted

技术标签:

【中文标题】Java EE 7:如何将 EJB 注入 WebSocket ServerEndpoint?【英文标题】:Java EE 7: How-to inject an EJB into a WebSocket ServerEndpoint? 【发布时间】:2014-01-19 06:32:18 【问题描述】:

总结一下我失败的项目:我的@ServerEndpoint 类与 beans.xml 文件一起打包在 WAR 中。我的 WAR 又被打包在一个 EAR 中,这个 EAR 文件被部署到内部使用 Tyrus 的 GlassFish 4 服务器上。

应该可以吗?

WebSocket specification 说:

在 Java EE 平台上运行的 Websocket 端点必须具有完整的 CDI 规范中描述的依赖注入支持。 Java EE 平台的 Websocket 实现部分需要 支持使用字段、方法和构造函数注入 javax.注入。将注解注入所有 websocket 端点类, 以及这些类的拦截器的使用。

我对这一段唯一能理解的是,将 Enterprise JavaBean 注入 WebSocket 应该不是火箭科学。但是,对我来说,无论我做什么,它都行不通。我觉得最直观的应该只需要在服务器端点实例字段前加上@EJB@Inject 注释,但这些注释都不起作用。该变量将为空。

已经是一个已知问题?

一位互联网source 有点含糊地说“由于一个错误”,他必须使用构造函数注入。我看到他在服务器端点上添加了注解@Named。我使用了著名的复制粘贴模式,并完全按照他的做法进行操作,无论有无 @Named 注释,但它仍然无法正常工作。事实上,我的 @Inject 带注释的构造函数甚至从未被调用过!

Tyrus user guide 表示可以将任何著名的会话 bean 声明注释与服务器端点(@Stateful@Stateless@Singleton)混合在一起。所以我做到了,但注射仍然失败。我使用注解@Inject 或@EJB 都没有关系。

这很奇怪,因为Java EE 7 Developer Handbook这本书声称在第 27 页和第 28 页有一个基于相同方法的工作示例。作者 Peter Pilgrim 注释了他的服务器端点 @Stateless。然后他使用@Inject 进行注射。他说:

在 Java EE 7 中,我们还必须将 [我们的服务器端点] 声明为无状态 带有@Stateless 的 EJB 以将 [另一个 EJB] 作为依赖项注入。 (这是 Java for WebSocket 1.0 规范的结果。) 注意 我们可以使用 CDI 中的@javax.annotation.Inject。

好的,所以他说我们必须使用@Stateless 注释,并“注意”可以使用@Inject。对我来说,我们“必须”在服务器端点上使用 @Stateless 注释,这听起来很奇怪,根据规范,除了无状态(!)之外的一切。我在 Internet 上的其他地方读到使用 @Inject 而不是 @EJB 应该是一种解决方法。彼得“注意到”“我们可以使用”@Inject,但它闻起来很腥,好像他根本没有让@EJB 工作,现在试图逃避责任。

好吧,不管是什么原因(“错误”或“规范的后果”),我无法让我的依赖注入工作在端点类本身或实例字段上使用的任何生动的注释组合。

终极修复

是以编程方式使用 JNDI 查找,但它看起来很难看,应该避免。

【问题讨论】:

嗨 Martin,您看过 Tyrus CDI 样品/测试吗? (github.com/tyrus-project/tyrus/tree/master/samples/cdi)。它基本上列出了您可以使用当前实现做什么。我们总是对新的测试用例持开放态度,但规范本身存在一些问题 - 标准请求范围不适用于 WebSocket 运行时,因为它处理 servlet 服务/doFilter 方法之外的消息。见java.net/jira/browse/WEBSOCKET_SPEC-196 和java.net/jira/browse/WEBSOCKET_SPEC-197 @PavelBucek 该评论似乎是一个很好的答案 在使用 glassfish 4.0 的类似情况下,我通过在 @ServerEndPoint 旁边添加 @Stateless 使注入的 bean 工作。 @Named 没用。在我注入的 bean 上,@EJB@Inject 都有效。我想这对你没有帮助,因为你已经尝试过了。但是谢谢你,因为你的一个建议确实对我有用。 @Toto2 我也在我的 Glassfish 4.0 安装上对其进行了测试。正如你所说,这个建议奏效了。我想知道是否将其注释为 @Stateless 是正确的做法。 对我来说已经很久了。将 WebSocket 类变成一个功能齐全的 EJB 是没有意义的。如果你注释类@ManagedBean怎么办? 【参考方案1】:

(只是重申我在评论中写的内容,以便从“未回答”列表中获取这个问题)

您应该结帐Tyrus CDI sample/test。

它演示了您可以使用当前实现执行的操作。我们总是对新的测试用例持开放态度,但规范本身存在一些问题 - 标准请求范围不适用于 WebSocket 运行时,因为它处理 servlet 服务/doFilter 方法之外的消息。请参阅WEBSOCKET_SPEC-196 和WEBSOCKET_SPEC-197。

【讨论】:

【参考方案2】:

对我来说。用@Stateful 注释websocket,用@EJB 声明EJB 对象就可以了。

@Stateful
@ServerEndpoint(value = "/profileregistration")
public class ProfileRegistrationEndpoint 


@EJB
private ProfileRegistration profileRegEJB;
....

【讨论】:

可以添加您的代码ProfileRegistration 还是直接说出您使用的注释?您使用的是哪个版本的 Java EE? 使用 Java EE 8,由于隐私问题,我无法提供整个代码。 所以只是注释 @Stateful 用于使服务器 websocket 成为有状态的 ejb @ServerEndpoint(value = "/profileregistration") 用于将类定义为 websocket 服务器,其 value 属性由 websocket 客户端使用 服务器 websocket 中的@Stateful 对我来说已经足够了:现在注入的 Singleton 不为空,我可以使用它。在 Wildfly 9、jdk 8 上测试

以上是关于Java EE 7:如何将 EJB 注入 WebSocket ServerEndpoint?的主要内容,如果未能解决你的问题,请参考以下文章

spring浅析

java ee EJB中的服务层和dao层

将资源注入无状态本地EJB

选择嵌入式 EJB 3.x 容器在 Tomcat 上运行 Java EE 5 应用程序

Java EE EJB 部署错误:容器已注册

使用MyEclipse开发Java EE应用:用XDoclet创建EJB 2 Session Bean项目