当前位置: 首页 > 知识库问答 >
问题:

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

宿景曜
2023-03-14

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

基于在Hibernate文档中找到的公共HibernateUtil帮助器类,我转向了JPA接口,并添加了@production注释以提供生产者方法(我还添加了一个空的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();
        }
    }
}

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

线程“main”org.jboss.weld.exceptions.unsatisfiedresolutionexception:weld-001308:无法解析类型:class app.demoapplication的任何bean;限定符:[@javax.enterprise.inject.any()],位于org.jboss.weld.bean.builtin.instanceimpl.get(instanceimpl.java:101),位于app.main.main(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();
        }
    }
}

我是不是漏了一个明显的地方?我如何让Weld发现用于注入我的依赖项的生产者方法?

我做了一个最小的项目,在GitHub上重现我的问题。谢谢您的建议!:)

更新2015-05-18:

好像我误解了错误信息。事实上,Weld甚至不解析demoapplicationbean,这使我相信bean发现过程出了问题。在将我的weld-se依赖项更新到最新发布的3.0.0.alpha8版本(请参阅链接的Github repo)后,我可以通过在main.java中手动告诉Weld我的bean来使应用程序正常工作:

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

尽管如此,对于为什么bean没有被自动发现的任何建议,我们还是非常赞赏的,尽管存在空的meta-inf/beans.xml

更新2015-05-19:

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

共有1个答案

陈高寒
2023-03-14

在这样一个问题上花了很多时间,我终于找到了问题的根源。它既不与Weld也不与Jandex相关,而是与Gradle构造其输出目录的方式相关:

:build任务为实际编译结果和其他资源(build/build/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

类似的问题已经在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

感谢大家的提示!

 类似资料:
  • 我正在尝试通过gradle构建我的应用程序,在运行: 知道吗?

  • 所以我使用IntelliJ,并使用JavaFX构建了我的应用程序。但当我开始我的主要工作时: 我得到以下错误,我不知道这些错误来自哪里。。。在我切换github上的分支并重新设置所有配置之前,一切都很正常。。。 我得到的错误:

  • Spring Framework 4.0本身支持beans{}“DSL”(从Grails借用),您可以使用相同的格式在bean的Groovy应用程序脚本中嵌入bean定义。 这有时是包含中间件声明等外部功能的好方法,如以下示例所示: @Configuration class Application implements CommandLineRunner { @Autowired Share

  • 问题内容: 我创建了一个简单的java“ echo”应用程序,该应用程序接收用户的输入并将其显示给他们以演示该问题。我可以使用IntelliJ的内部“运行”命令运行该应用程序,并且在执行产生的已编译Java文件时也可以正常运行。但是,如果尝试使用执行应用程序,则会从扫描仪抛出NoSuchElementException异常。 我认为gradle或应用程序插件正在对系统IO做一些奇怪的事情。 应用

  • 我使用Weld SE创建了一个简单的JavaSE应用程序。我尝试用gradle run运行它会引发异常: 据我所知,它找不到豆子。xml文件。但它存在于src/main/resources/META-INF/bean中。xml: 我的主要课程是: 构建梯度文件是:

  • 我一直在研究如何开发一个可以加载插件的应用程序。到目前为止,我已经看到,这可以通过定义一个接口并让插件实现来实现。 然而,我目前的问题是当插件被打包在罐子里时如何加载它们。有“最好”的方法吗? 我现在考虑的逻辑是让每个插件在它们的Jar中寻找实现接口的类。但我不知道怎么做这样的查找。我认为这个逻辑可能不是一个好的逻辑,但我找不到任何关于这个特定主题的有用信息。 **编辑1:**添加更多信息:预期的