【问题标题】:Observable pattern in Remote EJB远程 EJB 中的可观察模式
【发布时间】:2017-03-30 07:30:28
【问题描述】:

我有 2 个应用程序。一个“主”,另一个带有远程 EJB。第一个应用程序在第二个应用程序中调用远程 EJB。

现在我想实现 Observable 模式。但它似乎不适用于跨应用程序。

所以我希望我的 Observable 在第二个应用程序中,而我的 Observers 在第一个应用程序中。当我尝试它时,它似乎不起作用。只有当我在同一个应用程序中创建 Observable 和 Observers 时它才有效。

我有另一个解决方案,但我认为它很脏。我可以在第二个应用程序中使用 MDB,并在主题上发布一条消息,然后在第一个应用程序中使用这些消息。但话说回来,这似乎有点脏。

我在 Payara 4.1.1.171 服务器上使用 JEE7。

编辑: 因为我发现触发事件不会退出 EAR 文件,所以我现在使用 MDB 方法。但这仍然行不通。 更多信息,这是EAR文件的包结构。

my-application.ear
+--- common-ejb.jar (EJB)
|       +--- MessageDrivenBean.java (Triggers the event)
+--- my-application.jar (EJB)
+--- my-application.war (WEB)
        +--- WEB-INF
                +--- lib
                |       +--- common-web.jar (Resources WEB jar)
                |           +--- SessionBean1 to receive the events
                +--- classes
                        +--- SessionBean2 to receive the events

如您所见,有 2 个会话 bean 来接收事件,但 2 个实际上都没有接收它们。

【问题讨论】:

  • 不太了解您想要实现的目标,但您是否尝试过 MBean 世界?
  • 以这种方式使用JMS是一个完全合理的解决方案。如果您确保您的事件是可序列化的,那么您可以想象使用 JMS 队列,并使用它在应用程序之间构建“事件桥”。
  • 使用 JMS 确实可以部分工作。但是现在我让 MDB 处理“触发消息”并希望触发所有活动的会话 bean(忽略它们的会话)。但由于某种原因,我需要在 MDB 和 SessionScoped bean 之间使用 ApplicationScoped bean。
  • 难道没有一个选项我不需要使用 ApplicationScoped bean,而只需在 MDB 中触发一个触发器并在所有 bean 中监听这些触发器,而忽略它们的状态。
  • 您的会话 bean 究竟是如何注释的?

标签: jakarta-ee glassfish ejb observable payara


【解决方案1】:

给定一个消息驱动的 bean:

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "java:jboss/queue/SampleQueue")
})
public class EventListener implements MessageListener {

    @Inject
    @Any
    Event<MyEvent> loggedInEvent;

    @Override
    public void onMessage(Message message) {
        if (message instanceof ObjectMessage) {
            try {
                ObjectMessage objectMessage = (ObjectMessage) message;
                loggedInEvent.fire(((MyEvent) objectMessage.getObject()));
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}

其中 MyEvent 是一个简单的 POJO:

public class MyEvent implements Serializable {

    private final String payload; 

    public MyEvent(String payload) {
        this.payload = payload;
    }

    public String getPayload() {
        return payload;
    }
}

然后这个@SessionScoped bean:

@SessionScoped
public class EventHandler {

    public void handleEvent(@Observes MyEvent myEvent) {
        System.out.println(myEvent.getPayload());
    }
}

MyEvent 对象被发送到与EventListener 关联的队列时,打印负载字符串

可以提供任意数量的观察者。

【讨论】:

  • 我已经尝试过了,但它不起作用。事件只是没有在我需要触发它们的地方触发。我已经登录了每种方法(Observable 方法,但也有两种 Observe 方法)。仅记录火灾。我已经在问题本身中设置了我的耳朵结构。
  • 将所有内容放入 WAR 文件中,它应该可以工作。您现在遇到的问题是 EAR 中的类(EJB 和 lib 目录)看不到 WAR 文件中的类。除非您需要,否则不要再构建 EAR(主要是因为其中有多个 WAR)。
  • 请注意,@OndrejM 的答案看起来很酷 - 但它不便携
【解决方案2】:

启用 Payara Server 171 版和 Hazelcast 后,您可以触发 CDI 事件并在另一个应用程序中观察它们。请参阅有关remote CDI events 的文档

如果两个应用程序都部署在同一个 Payara 服务器实例上,您将触发 MyEvent.class 类型的事件,如下所示:

@Inject
@Outbound(loopBack = true) // loopBack true is required if the observing application is deployed on the same Payara Server instance
Event<MyEvent> event;

...
event.fire(new MyEvent());

而另一个应用程序将通过以下方式观察这些事件:

public void receiveEvent(@Observes @Inbound MyEvent event) {
}

如果观察应用程序在同一个 Hazelcast 集群中的另一个 Payara 服务器实例上运行,它也会收到该事件。在这种情况下,loopBack 属性不是必需的,但也不会造成任何伤害。

远程 CDI 事件通过嵌入式 Hazelcast 数据网格进行调度,该数据网格将可靠地将事件传递给集群中的所有观察应用程序。观察应用程序必须在事件触发时运行 - 类似于通过 JMS 主题广播事件的行为。

【讨论】:

  • 这比我以前更有效,但现在我在 Hazelcast 上遇到了 ClassCastExceptions。更具体的org.glassfish.api.invocation.ComponentInvocation cannot be cast to com.sun.ejb.EjbInvocation。这是从com.hazelcast.util.executor.StripedExecutor$Worker.run(StripedExecutor.java:171) 抛出的。我已经尝试升级到 Payara 171.1,因为在发行说明中是关于带有远程 EJB 的 ClassCastExceptions(我正在使用),但它不能解决问题。
  • 如果您在应用程序中找不到错误,您应该在 Payara GitHub 上提出问题,提供尽可能多的信息,包括完整的堆栈跟踪。
猜你喜欢
  • 1970-01-01
  • 2013-02-12
  • 1970-01-01
  • 2012-09-02
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
相关资源
最近更新 更多