Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java EJB中的IoC抛出ClassNotFoundException和';未能封送EJB参数';_Java_Jakarta Ee_Dependency Injection - Fatal编程技术网

Java EJB中的IoC抛出ClassNotFoundException和';未能封送EJB参数';

Java EJB中的IoC抛出ClassNotFoundException和';未能封送EJB参数';,java,jakarta-ee,dependency-injection,Java,Jakarta Ee,Dependency Injection,我有以下设置: 我们正在JBoss6.4上运行一个应用程序,其中部署了一个ear,其中包含业务逻辑的EJB。一些Web服务和WebSocket所在的地方也部署了war 现在我想要这样的东西: 耳侧 @Remote public interface EventConsumer extends Serializable { void onEventMessage(Topic topic, String message, String principalName); void on

我有以下设置:

我们正在JBoss6.4上运行一个应用程序,其中部署了一个ear,其中包含业务逻辑的EJB。一些Web服务和WebSocket所在的地方也部署了war

现在我想要这样的东西:

耳侧

@Remote
public interface EventConsumer extends Serializable {

    void onEventMessage(Topic topic, String message, String principalName);

    void onErrorMessage(Topic topic, Throwable t, String principalName);

}
@ServerEndpoint("/ws/eventLog/")
@Stateless
public class EventLogWebsocket implements EventConsumer {

    private static final long serialVersionUID = 1L;
    private final EventLog eventLogService;

    public EventLogWebsocket() {
        eventLogService = createEventLogService();
    }

    @OnOpen
    public void open(Session session) {
        eventLogService.registerEventConsumer(this);
    }

    // other ws stuff

    @Override
    public void onEventMessage(Topic topic, String message, String principalName) {
        System.out.println(message);
    }

    @Override
    public void onErrorMessage(Topic topic, Throwable t, String principalName) {
        System.out.println(message);
    }

    private EventLog createEventLogService() {
        EventLog logService = // some proxy stuff since its remote. works fine
        return logService;
    }

}

在战争方面

@Remote
public interface EventConsumer extends Serializable {

    void onEventMessage(Topic topic, String message, String principalName);

    void onErrorMessage(Topic topic, Throwable t, String principalName);

}
@ServerEndpoint("/ws/eventLog/")
@Stateless
public class EventLogWebsocket implements EventConsumer {

    private static final long serialVersionUID = 1L;
    private final EventLog eventLogService;

    public EventLogWebsocket() {
        eventLogService = createEventLogService();
    }

    @OnOpen
    public void open(Session session) {
        eventLogService.registerEventConsumer(this);
    }

    // other ws stuff

    @Override
    public void onEventMessage(Topic topic, String message, String principalName) {
        System.out.println(message);
    }

    @Override
    public void onErrorMessage(Topic topic, Throwable t, String principalName) {
        System.out.println(message);
    }

    private EventLog createEventLogService() {
        EventLog logService = // some proxy stuff since its remote. works fine
        return logService;
    }

}
问题

毫无疑问,当调用ws-open方法时,这不起作用:

ERROR [xyz.ws.EventLogWebsocket] (http-/0.0.0.0:8280-17) error occurred in websocket: java.lang.reflect.InvocationTargetException
...
Caused by: java.lang.RuntimeException: JBAS014154: Failed to marshal EJB Parameters
...
Caused by: java.lang.ClassNotFoundException: xyz.ws.EventLogWebsocket from [Module "deployment.abc-app-0.6.0-SNAPSHOT.ear.abc-infrastructure-ejb-0.6.0-SNAPSHOT.jar:main" from Service Module Loader]
...
在jboss ModuleClassLoader中调试表明EJB无法加载EventLogWebsocket类。但在这个IoC设置中,这正是我想要的:不关心这个特定接口的实现


现在我看不出解决办法。。。是吗?:)

您需要记住@Remote方法调用使用RMI,因此:

  • 所有方法参数和返回值必须是
    java.io.Serializable

  • 方法参数是通过值传递的,而不是引用,因此接收方法获取对象的副本,而不是实际对象

  • 如您所见,最初的调用:

     eventLogService.registerEventConsumer(this);
    
    有问题:

    当EJB端尝试反序列化
    使用者
    对象时,它尝试重新创建
    事件日志WebSocket
    的副本,但该类在EAR中不可用,因此失败

    此外,
    EventLogWebsocket
    参数必须是可序列化的对象。它声称是可序列化的,但这并不是因为它包含不可序列化的
    EventLog
    对象

    即使您纠正了所有这些问题,它仍然无法工作,因为EJB有一个
    EventLogWebsocket
    的副本,因此无论如何都不会发送任何事件通知

    因此,您需要做的第一件事就是去掉@Remote接口。这意味着您必须在EAR中包含WAR并使用@Local接口

    但是您仍然需要小心,因为EAR/WAR文件中的类可以看到EAR/EJB类,但反之则不然——EAR/EJB类无法看到EAR/WAR文件中的类


    如果你在重新打包后仍然有类装载问题,那么考虑把所有东西放在战争文件中,完全失去耳朵。

    是耳朵里的战争还是与之分离的?战争是分开的,但在同一个JJ中运行,谢谢你的回答。好像我太经常忘记这整件事了。在这种情况下,一些消息队列框架会有帮助吗(HornetQ可能可用?或者我们在那里也会面临同样的问题?我的意思是,他们是如何处理这种回调的?如果你需要单独的部署,那么你可以使用JMS来实现这一点-是的。您也可以尝试类似于本文中使用的ApacheKafka。但是,如果您可以将所有内容都放入同一个类加载器(单次WAR部署),那么您可以使用CDI事件和观察者。如果可以的话,你当然想避免RMI。