【问题标题】:Add External jar with beans (outside the war)添加带有豆子的外部罐子(战争之外)
【发布时间】:2020-01-21 09:53:46
【问题描述】:

我正在尝试在 war 文件之外加载 bean。目标是应该可以在没有新的 war 文件的情况下更改 jar 文件。

我的 war 文件包含外部 jar 作为提供的依赖项:

        <dependency>
            <groupId>com.lube</groupId>
            <artifactId>foo</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>

我将jar文件添加到域目录(domain/lib/applibs)的applibs文件夹中,并在部署时填写了库字段。

似乎没有从这个 jar 文件加载任何 bean(无法注入),但可以使用该类。 (该类在当前类加载器中可用)。

如果我从 war 文件的类中注入一些东西,我会得到以下异常 UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type XXX with qualifiers

我正在使用 payara 4.1.2.174,但它也不适用于 payara 5。

主要问题是:是否可以在战争之外加载 bean (ejb/cdi)?我在网上找不到任何好的解决方案。

P.S.:我不能使用微服务 ;)

编辑: war 文件包含 jar 文件。 jar 文件当前位于 /lib/applibs 下的域中(我也测试了所有其他文件夹)

我执行的命令如下asadmin add-library --type app C:\library.jar

library.jar 只包含一个 CDI bean

@Model
public class CdiBean {
    public void test() {
        System.out.println("It works!");
    }
}

还有 beans.xml 文件。 (resources/META-INF - 我在没有 META-INF 文件夹的情况下也对其进行了测试)

WAR 文件有一个尝试加载 Bean 的启动类。

@Singleton
@Startup
@TransactionManagement(value = javax.ejb.TransactionManagementType.BEAN)
public class AppStartup {
    @PostConstruct
    public void postConstruct() {
        try {
            System.out.println(CdiBean.class);
            CDI.current().select(CdiBean.class).get().test();
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
}

战争部署后的输出为:

[2020-01-21T13:47:36.413+0100] [Payara 4.1] [INFO] [] [] [tid: _ThreadID=103 _ThreadName=admin-thread-pool::admin-listener(3)] [timeMillis: 1579610856413] [levelValue: 800] [[   class com.lube.CdiBean]]

[2020-01-21T13:47:36.474+0100] [Payara 4.1] [SEVERE] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=103 _ThreadName=admin-thread-pool::admin-listener(3)] [timeMillis: 1579610856474] [levelValue: 1000] [[
  Exception while invoking class org.glassfish.ejb.startup.EjbApplication start method
javax.ejb.EJBException: javax.ejb.CreateException: Initialization failed for Singleton AppStartup
    ...
Caused by: javax.ejb.CreateException: Initialization failed for Singleton AppStartup
    at com.sun.ejb.containers.AbstractSingletonContainer.createSingletonEJB(AbstractSingletonContainer.java:553)
    at com.sun.ejb.containers.AbstractSingletonContainer.access$000(AbstractSingletonContainer.java:82)
    at com.sun.ejb.containers.AbstractSingletonContainer$SingletonContextFactory.create(AbstractSingletonContainer.java:723)
    ... 72 more
Caused by: java.lang.IllegalStateException: WELD-001334: Unsatisfied dependencies for type CdiBean with qualifiers  
    ... 74 more
Caused by: org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type CdiBean with qualifiers  
    ... 102 more
]]

【问题讨论】:

标签: java jakarta-ee cdi payara


【解决方案1】:

经过 3 天的测试,我找到了解决方案 - 终于:D 我没有找到任何解决方案,所以我在 payara github repo 中搜索“applibs”,我发现了以下有趣的课程。 appserver/web/weld-integration/src/main/java/org/glassfish/weld/DeploymentImpl.java

有一个名为private void processBdasForAppLibs( ReadableArchive archive, DeploymentContext context ) 的方法带有一个不错的 java 文档。

 // These are application libraries that reside outside of the ear.  They are usually specified by entries
    // in the manifest.
    // to test this put a jar in domains/domain1/lib/applibs and in its manifest make sure it has something like:
    //                           Extension-Name: com.acme.extlib
    // In a war's manifest put in something like:
    //                           Extension-List: MyExtLib
    //                           MyExtLib-Extension-Name: com.acme.extlib

我发现我在jar文件中添加了以下插件:

            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Extension-Name>com.lube</Extension-Name>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>

以及war文件的以下内容

            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.3</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Extension-List>ExternalLib</Extension-List>
                            <ExternalLib-Extension-Name>com.lube</ExternalLib-Extension-Name>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>

之后,我构建了 jar 并将其添加到 domain/lib/applibs。比我部署战争,一切都按预期工作!

【讨论】:

    【解决方案2】:
    • 您可以将多个战争合并到一个耳朵并运行它。
    • 或者可以使用add-library 命令。它适用于GlassFish Server,它适用于Payara Micro。我相信应该有这样的功能(不过我可以为 Payara Server 找到它)。

    【讨论】:

    • 如果你在一个耳朵里合并了多个战争,默认情况下战争仍然不能“看到”对方。添加为库是不需​​要的非常具体的事情。 stackoverflow.com/questions/39112542/…
    • @Kukeltje 当您指定 &lt;scope&gt;provided&lt;/scope&gt; 时,您表明它应该在运行时以某种方式提供。从您提供的链接中回答建议使用beans.xml 来配置类加载。 add-library 允许指定容器“提供”的共享库。如果这一切都不适合你,你可以尝试加载你的课程dynamically with URLClassLoader
    • @Kukeltje 我知道提供的意思是,容器应该提供“正确的”jar 文件。但这是我的问题。 jar 文件已加载,但定义的 bean 不是 bean。 (不能注入/我有一个 beans.xml)
    • 但正题:我现在看到 OP 正试图将一个共享罐子放在战争之外和耳朵之外......对不起。我被你的第一句话误导了
    • 哦,provided 没有在任何地方被我提及...不知道你从哪里得到的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    • 2010-11-18
    • 1970-01-01
    • 2013-02-01
    相关资源
    最近更新 更多