如何在wildfly上调用单独部署的ejb3

How to call separately deployed ejb3 on wildlfy

只要我的 EJB 部署在使用它的应用程序的 war 内,一切正常,我只需要 @Inject 它,不需要 xml,不需要本地或远程接口。该 webapp 是一个使用 vaadin-cdi 的 Vaadin 7.5.6 应用程序。

将 ejb 作为单独的 jar 部署时,调用它的 Web 应用程序失败并显示 "Forbidden"。我用

注释了它
@SecurityDomain("other")
@RolesAllowed({ "guest" })

不过,还是"Forbidden"。 webapp 中可能也需要一些配置。到目前为止,我发现的所有示例都提到了 jndi-lookup、ejb-jar.xml、web.xml、jboss-ejb.xml、ejb 接口等等。甚至可以单独部署并访问 ejb,同时避免所有这些额外的配置吗?我想分解我的应用程序,这样我就不必在每次更改 gui 时都部署所有内容,但是如果我必须恢复到 "old school" ejb 配置,我不确定是否有点.

使用 Wildfly 9.0.2、Java8 和 Maven。

编辑:

EJB : Hello World EJB 存在于 maven 子项目中,它有 jar 包。它没有 xml 配置,也没有本地或远程接口。没有使用 maven-ejb-plugin。实现如下所示:

import javax.ejb.Stateless;

@Stateless
public class ReceptionService {
    public String welcome() {
        return "Hello, Developer! No XML, No Configuration, and it works!";
    }
}

还有许多真实世界的会话 bean 在方法内部使用 JPA,看起来像这样(如下),因此这里可能还会出现一些持久性和事务问题,但直到简单的 hello-世界案例正在发挥作用。 hello-world-webapp 不包含任何这些 EJB,仅包含简单的 hello-world-EJB。

@Stateless
@TransactionManagement(value = TransactionManagementType.CONTAINER)
public class DealerSession {

    private Logger logger = LoggerFactory.getLogger(DealerSession.class);

    @PersistenceContext(unitName = "MyUnit")
    protected EntityManager em;

    @TransactionAttribute(REQUIRED)
    public Long create(DealerUpdate update) {
        notNull(update, "update"); // and so on ....

持久性单元在 EJB 项目中定义,它连接到 Wildfly 中的数据源。在现实世界中,bean 事务会在失败时回滚。

WAR :这是一个 Vaadin 7 webapp。它看起来像这样:

@CDIUI("")
@Theme("valo")
public class WelcomePage extends UI {

    @Inject
    ReceptionService service;

    @Override
    protected void init(VaadinRequest request) {
        setSizeFull();
        String message = service.welcome();
        Label label = new Label("this is the message: " + message);
        setContent(new HorizontalLayout(label));
    } ....

依赖项中引用了 EJB jar 文件。所以它被包括在内,并且一切正常,就好像 EJB bean 只是 war 中的一个 .class 文件一样。这非常方便,因为几乎不涉及任何配置。但是随着这里真实世界项目的增长,我想拆分部署,这样我就不必在每次更新 gui 时将所有 EJB 作为 war 的一部分部署,因为它会减慢速度缩短开发周期。

war 项目依赖于 vaadin-cdi 1.0.3 和 vaadin-bom 7.5.6,当然还有带有 EJB 的 jar(有 jar 而不是 ejb 包装)。还使用了 vaadin-maven-plugin、maven-resource-plugin 和 maven-war-plugin。

这两个项目也使用wildly-plugin 1.0.2.Final。并依赖于 java javaee-api 7.0.

现在,到目前为止,我天真的尝试是将 EJB jar 的包装更改为 "ejb",添加 maven-ejb-plugin,在 [=55] 的 pom 文件中指定依赖项中提供的范围=]-project,并分别部署war和jar。到目前为止,没有错误消息或 warning,两者都已部署。但是访问ejb是"Forbidden",gui中有一条错误消息说,奇怪的是wildfly控制台中没有。我已尝试向 EJB 添加 @SecurityDomain 和 @RolesAllowed 注释(见上文),但也必须在 webapp 上配置这些内容。如果是这样,CDI 无论如何只会将 EJB 作为 pojo 注入,或者我必须添加本地 and/or 远程接口,执行 JNDI 查找,向 xml 配置文件添加很多东西等等,我可以解决这个问题,因为有示例应用程序和文档,但一切都会变得更加复杂,我想避免这种情况。

首先,您的 EJB 并没有被注入,即使它们是与您的 WAR 一起部署的。这是因为您没有声明接口。在这种情况下,您至少必须使用 @LocalBean 注释它们,它声明了 bean 的无接口视图。

当您将 EJB 外包到 jar 中时,CDI 无法注入将由 EJB(代理)生成的 bean 实例,而是注入 pojo 实例。为避免这种情况,您可以为 WAR 中的每个 EJB 创建生产者字段或方法。然后使用 CDI 注入 bean 调用生产者。该生产者必须执行特定的 JNDI 查找 (java:global/...) 才能获取 EJB bean 实例。

然后,当部署到 wildfly 时,您必须将 WAR 的依赖项添加到 JAR,因为两个部署都有单独的 class 加载程序并且彼此看不到。该依赖关系连接两个 class 加载器,以便 WAR 之一能够加载 JAR 的 classes。

在这种情况下,您只需为 WAR 而不是 JAR 激活 CDI,因为 EJB 实例是通过显式 JNDI 查找检索的。

如果您绝对需要使用 cdi 注入,我为我的问题批准的答案可能是正确的。不过,我从来没有达到我让它工作的程度。

相反,我决定尝试使用@EJB 注释,而不是@Inject。当我部署我的 ejb(在我的网络应用程序的一个单独的 jar 中,它位于 war 文件中)Wildfly 注册 jndi-names 并在控制台中报告它。其中一个名字是 "java:global/template-service-1.0.0-SNAPSHOT/ReceptionService"。注意 "global" 范围。

@EJB 注释有一个名为 mappedName 的参数。像这样注入和使用 ejb 就成功了:

@EJB(mappedName = "java:global/template-service-1.0.0-SNAPSHOT/ReceptionService")
ReceptionService service;

@Override
protected void init(VaadinRequest request) {
    UI.getCurrent().setLocale(new Locale("nb","no"));
    setSizeFull();
    String message = service.welcome();
    Label label = new Label("message: " + message);
    setContent(new HorizontalLayout(label));
}

还需要注册模块依赖,这样客户端class加载器才能看到服务。我在 webapp pom.xml 中使用 war-plugin:

         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <archive>
                    <manifestEntries>
                        <Dependencies>deployment.template-service-1.0.0-SNAPSHOT.jar</Dependencies>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>

这样我就可以单独部署我的 ejb,然后我可以将我的 war-文件部署为 "thin" 部署。我的真实世界项目有一堆 ejbs 和 jpa-stuff,当我处理这些内容时,它们会减慢开发-编译-部署周期,有了这个设置,我可以在摆弄 gui 时节省很多时间。

EJB长这样,没有ejb-jar.xml.

@Stateless
public class ReceptionService {
    public String welcome() {
        return "Hello, Developer! No XML, No Configuration, and it works!!!";
    }
}

消息中的 no-xml- 部分只有在您手动将模块依赖项添加到清单中并且不使用 war-plugin 时才为真:o)

编辑:要在 ejb jar 中包含依赖项,可以使用 one-jar 插件或类似插件。