使用带有Gradle应用程序插件的weld-se时的Bean发现问题

Adr*_*oKF 13 java gradle jboss-weld weld-se

我正在构建一个基于Gradle的Java SE应用程序,它基于Hibernate构建,是我的首选ORM.我的计划是weld-se使用CDI注释EntityManagers在整个应用程序中进行注射.

基于HibernateUtilHibernate文档中的常见帮助程序类,我转向JPA接口并添加了@Produces注释以提供生产者方法(我还添加了一个空META-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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

线程"main"中的异常org.jboss.weld.exceptions.UnsatisfiedResolutionException:WELD-001308:无法解析Type:class app.DemoApplication; 限定符:[@ javax.enterprise.inject.Any()] at app.Main.main上的org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:101)(Main.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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里错过了一个明显的观点吗?我怎样才能让Weld发现注入依赖项的生产者方法?

我已经整理了一个在Github上重现我的问题的最小项目.谢谢你的任何有用的建议!:)

更新2015-05-18:

好像我误解了错误信息.事实上,Weld甚至没有解决DemoApplicationbean,这让我相信,bean发现过程出了问题.在将我的焊接依赖关系更新到新发布的3.0.0.Alpha8版本(参见链接的Github repo)之后,我能够通过手动告诉Weld关于我的bean的应用程序来运行Main.java:

final Weld weld = new Weld()
        .enableDiscovery()
        .addPackage(false, HibernateUtil.class)
        .addPackage(false, DemoApplication.class);
Run Code Online (Sandbox Code Playgroud)

尽管如此,我们仍然META-INF/beans.xml非常感谢任何关于为什么豆子没有自动发现的建议,尽管它们已经空了.

更新2015-05-19:

这个谜团被揭开了,请看下面我自己的答案.我更改了问题标题,以反映问题的实际性质.

Adr*_*oKF 17

花了更多的时间而不是像这样的问题似乎是理智的,我终于能够找到我的问题的起源.它既不用于Weld也不用于Jandex,而是Gradle构造其输出目录的方式:

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

Weld的bean发现机制显然只是尝试发现与META-INF/beans.xml文件相同的类路径条目的bean ,在本例中是build/resources/main文件夹.反过来,没有豆子被发现,并且永远不会有资格在任何地方注射.

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

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

processResources.dependsOn copyResources
Run Code Online (Sandbox Code Playgroud)

Gradle论坛中描述了类似的相同问题:https://discuss.gradle.org/t/application-plugin-run-task-should-first-consolidate-classes-and-resources-folder-or-依靠-ON-installapp -或-东西样焊接SE-不会工作/ 1248

感谢大家的提示!