将 weld-se 与 Gradle 应用程序插件配合使用时的 Bean 发现问题

2022-09-04 07:56:51

我正在构建一个基于Gradle的Java SE应用程序,该应用程序构建在Hibernate之上,作为我选择的ORM。我的计划是使用能够使用CDI注释来注入整个应用程序。weld-seEntityManagers

基于在Hibernate文档中找到的通用帮助器类,我转向JPA接口并添加了注释以提供生产者方法(我还添加了一个空):HibernateUtil@ProducesMETA-INF/beans.xml

package dao;

import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class HibernateUtil {
    private static final EntityManagerFactory emf = buildEntityManagerFactory();

    private static EntityManagerFactory buildEntityManagerFactory() {
        try {
            return Persistence.createEntityManagerFactory("persistenceUnit");
        } catch (Throwable ex) {
            System.err.println("Initial EntityManagerFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    @Produces
    public static EntityManager createEntityManager() {
        return emf.createEntityManager();
    }

    public static void closeEntityManager(@Disposes EntityManager em) {
        System.out.println("Closing EM");
        try {
            em.close();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

但是,当我尝试在字段上使用注释时,Weld 无法解析正确的生产者方法,而是生成异常:@Inject

线程“main” org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001308: 无法解析 Type: class app 的任何 bean 中的异常。演示应用程序;Qualifiers: [@javax.enterprise.inject.Any()] at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:101) at app.主.主(主.java:14)

违规代码通过 Weld 容器实例化,以支持 CDI,并且非常基本:

package app;

import javax.inject.Inject;
import javax.persistence.EntityManager;

public class DemoApplication {
    @Inject private EntityManager em;

    public void run() {
        try {
            em.getTransaction().begin();
            System.out.println("Inside transaction");
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            em.getTransaction().rollback();
            em.close();
        }
    }
}

我在这里错过了一个明显的要点吗?如何让 Weld 发现用于注入依赖项的生产者方法?

我已经把一个最小的项目放在一起,在Github上重现我的问题。感谢您的任何有用的建议!:)

2015-05-18 更新:

似乎我误解了错误消息。事实上,Weld甚至没有解决豆子的问题,这使我相信,豆子发现过程出了问题。在将我的 weld-se 依赖项更新到新发布的 3.0.0.Alpha8 版本(请参阅链接的 Github 存储库)后,我能够通过手动告知 Weld 有关我的 Bean 的信息来使应用程序正常工作:DemoApplicationMain.java

final Weld weld = new Weld()
        .enableDiscovery()
        .addPackage(false, HibernateUtil.class)
        .addPackage(false, DemoApplication.class);

尽管如此,任何关于为什么尽管有空的豆子没有自动被发现的建议都非常感谢!META-INF/beans.xml

2015-05-19 更新:

谜团解开了,请看下面我自己的答案。我更改了问题标题,以反映问题的实际性质。


答案 1

在这样的问题上花费了比看起来理智更多的时间之后,我终于能够找到我的问题的根源。它既不与Weld或Jandex有关,而是与Gradle构建其输出目录的方式有关:

该任务为实际编译结果和其他资源( 和 ) 创建两个单独的输出文件夹。只有在创建 JAR 归档文件时,这两个文件夹才会合并。但是,该任务直接从编译输出文件夹启动应用程序,该文件夹具有两个单独的类和资源类路径条目。:buildbuild/classesbuild/resources:run

Weld 的 bean 发现机制显然只尝试发现与文件相同的类路径条目的 bean,在本例中是文件夹。反过来,没有发现任何豆类,也从未有资格在任何地方注射。META-INF/beans.xmlbuild/resources/main

我现在的解决方法(请参阅 Git 存储库)是创建一个额外的 Gradle 任务,将资源复制到相应的文件夹中,以便在正确的类路径条目上进行 Bean 发现:

task copyResources(type: Copy) {
    from "${projectDir}/src/main/resources"
    into "${buildDir}/classes/main"
}

processResources.dependsOn copyResources

Gradle 论坛中也描述了具有类似问题的相同问题:https://discuss.gradle.org/t/application-plugin-run-task-should-first-consolidate-classes-and-resources-folder-or-depend-on-installapp-or-stuff-like-weld-se-wont-work/1248

感谢大家的提示!


答案 2

声明有问题。你能以非静态的方式做到这一点吗?static

关于 https://issues.jboss.org/browse/WELD-1505 应该在2.2.0.Beta2中修复


推荐