Jakarta ee EJB3-自远程注入/EJB插件

Jakarta ee EJB3-自远程注入/EJB插件,jakarta-ee,plugins,classpath,ejb-3.1,Jakarta Ee,Plugins,Classpath,Ejb 3.1,我想用EJB3实现一种插件机制。我有两个+war,每个都包含自己的bean类型,使用在单独项目中定义的远程接口。基本上,我希望始终部署我的主Bean产品,并为不同项目Bean的其他Bean提供注册机制。重要的是,任意bean可以注册,只要它们知道产品的远程接口。示例代码: 成品豆 项目Bean 产品界面 项目接口 不幸的是,当我尝试部署项目时,我得到一个ClassNotFoundException: 22:56:33,146 ERROR [org.jboss.as.controller.mana

我想用EJB3实现一种插件机制。我有两个+war,每个都包含自己的bean类型,使用在单独项目中定义的远程接口。基本上,我希望始终部署我的主Bean产品,并为不同项目Bean的其他Bean提供注册机制。重要的是,任意bean可以注册,只要它们知道产品的远程接口。示例代码:

成品豆

项目Bean

产品界面

项目接口

不幸的是,当我尝试部署项目时,我得到一个ClassNotFoundException:

22:56:33,146 ERROR [org.jboss.as.controller.management-operation] (XNIO-1 task-7) JBAS014613: Operation ("add") failed - address: ([{"deployment" => "project-0.1-SNAPSHOT.war"}]) - failure description: {"JBAS014671: Failed services" => {"jboss.deployment.unit.\"project-0.1-SNAPSHOT.war\".component.ProjectBean.START" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"project-0.1-SNAPSHOT.war\".component.ProjectBean.START: java.lang.IllegalStateException: JBAS011048: Failed to construct component instance
Caused by: java.lang.IllegalStateException: JBAS011048: Failed to construct component instance
Caused by: javax.ejb.EJBException: java.lang.RuntimeException: JBAS014154: Failed to marshal EJB parameters
Caused by: java.lang.RuntimeException: JBAS014154: Failed to marshal EJB parameters
Caused by: java.lang.ClassNotFoundException: com.xxx.test.project.ProjectBean from [Module \"deployment.product-0.1-SNAPSHOT.war:main\" from Service Module Loader]"}}

所以我的问题是:有没有办法实现这样的功能?还是因为每次战争的类路径不同而完全不可能

我认为第一个问题是,即使您正在共享接口,客户机实现类仍然不能用于其他项目,并且它的实例是用另一个类加载器加载的,即另一个war容器

您可以使用MessageBeanJMS设计来实现这些事情,这将允许分离关注点,准注册到队列/主题,并允许您部署任何您想要的实现。看看我是如何工作的

另一种解决方案是使用委托模式,例如:

假设您从两个独立的war部署到单个EAR部署,您的项目将具有以下模块

我的图书馆

EJB接口:

@Local
public interface MyBeanLocal
    public void doSomething(String something);
MyClient注释:

@Documented
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface MyClient {

}
@Documented
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface MyDefault {

}
MyDefault注释:

@Documented
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface MyClient {

}
@Documented
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public @interface MyDefault {

}
我的客户

myDefaultEJB

myWeb


<>最后,您可能需要考虑OSGi。我还没有做过任何事情,但它可能是您正在寻找的注册资源。当然,你可以根据你的问题域考虑一个资源适配器。

< P>我的一个同事给了我正确的暗示,关于我在代码中犯了什么错误——我写的方式我试图让我的实现被注入。显然,这不起作用,因为类路径和JVM不同。相反,我必须将对为远程接口创建的代理对象的引用传递到注册方法中

因此,为了使上述代码正常工作,对Project.java进行了两项更改:

为自身添加EJB:

@EJB
private ProjectRemote self;
更改@PostConstruct方法以引用EJB

@PostConstruct
private void registerSelf() {
    product.registerProject(self);
}
这样,使用该类的类就不需要知道该类的实际实现。容器根据为EJB创建的代理对象知道在何处传递信息

@Stateless
@MyClient
public class MyBean implements MyBeanLocal {
@Inject
@MyDefault
private MyBeanLocal myDefault;

@Override
public void doSomething(String something) {
    myDefault.doSomething(something);
}
}
@Stateless
@MyDefault
public class MyBean implements MyBeanLocal {

@Override
public void doSomething(String something) {
    // do something
}
}
@Named
@Request
public class MyRequestBean {

@Inject
@MyClient
private MyBeanLocal myClient;

public void something() {
    myClient.doSomething("...");
}
}
@EJB
private ProjectRemote self;
@PostConstruct
private void registerSelf() {
    product.registerProject(self);
}