使用 CDI/Weld 注入通用 Bean

发布于 2024-11-16 13:27:58 字数 2737 浏览 2 评论 0 原文

我刚刚从我美好的 JavaSE/Guice 小世界回来,目前正在探索“容器承载”的路径 - EE6。在使用 Glassfish3.1 遇到一些问题后,我刚刚切换到 JBoss,现在面临着一个不应该出现的问题。

作为基础设施辅助类,我尝试为任何类型的实体创建通用存储库/DAO。以一种非常简单的方式,这可能看起来像这样。

public class Repository<E, K extends Serializable & Comparable<K>> {

    private final Instance<EntityManager> entityManagerInstance;

    protected final Class<E> getDomainObjectClass() {
        return domainObjectClass;
    }

    private final Class<E> domainObjectClass;

    protected final EntityManager getEntityManager() {
            return entityManagerInstance.get();
    }

    @Inject
    public Repository(Instance<EntityManager> entityManageryProvider, Provider<E> domainObjectProvider) {
            //This is a dirty hack, sadly :(
            domainObjectClass = (Class<E>)domainObjectProvider.get().getClass();
            this.entityManagerInstance = entityManageryProvider;
    }

    public final void persist(E domainObject) {
        final EntityManager em = getEntityManager();
        em.persist(domainObject);
    }

    public final Collection<E> getAllEntities() {
            final EntityManager em = getEntityManager();
            final CriteriaBuilder cb = em.getCriteriaBuilder();
            final CriteriaQuery<E> query = cb.createQuery(getDomainObjectClass());

            final List<E> result = em.createQuery(query).getResultList();
            return Collections.unmodifiableList(result);
    }

    public final E find(K id) {
            Preconditions.checkNotNull(id);
            final EntityManager em = getEntityManager();
            return em.find(getDomainObjectClass(), id);
    }

    // [...]
}

现在可能有一个 bean 不需要依赖于实体的查询功能,而只需要某种实体类型的存储库,例如(可能是一个测试用例):

public class DomainObjectARepositoryTest{

    @Inject
    Repository<DomainObjectA, PersistableUUID> domainObjectARepository;


    @Test
    public void testMitarbeitererstellung() {
        for (DomainObjectA a : domainObjectARepository.getAllEntities()) {
            // do cool stuff
        }       
    }
}

不幸的是,Weld 似乎不喜欢这种通用注入。在部署时,我收到以下错误:

state=Create: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Repository<DomainObjectA , PersistableUUID>] with qualifiers [@Default] at injection point [[field] @Inject sompackage.DomainObjectARepositoryTest.domainObjectARepository]

我是否遗漏了某些内容,或者他们只是忘记实现通用注入?据我了解通用的东西,无论如何,它在编译后都会被删除 - 即使到目前为止,这在 guice3 中工作得很好。

亲切的问候,

avi

编辑:发现 garvin king 的评论,该行为在规范中,但未在焊接中实现, (声明于2009年6月)

I just come from my tiny nice JavaSE/Guice world and am currently discovering the path of "carried by the container"-EE6. After having some trouble with Glassfish3.1, I just switched to JBoss and am now facing a problem that shouldnt be one.

As infrastructural assisting class, im trying to create a generic repository/DAO for any kind of entity. In a very simple manner, this might look like this one.

public class Repository<E, K extends Serializable & Comparable<K>> {

    private final Instance<EntityManager> entityManagerInstance;

    protected final Class<E> getDomainObjectClass() {
        return domainObjectClass;
    }

    private final Class<E> domainObjectClass;

    protected final EntityManager getEntityManager() {
            return entityManagerInstance.get();
    }

    @Inject
    public Repository(Instance<EntityManager> entityManageryProvider, Provider<E> domainObjectProvider) {
            //This is a dirty hack, sadly :(
            domainObjectClass = (Class<E>)domainObjectProvider.get().getClass();
            this.entityManagerInstance = entityManageryProvider;
    }

    public final void persist(E domainObject) {
        final EntityManager em = getEntityManager();
        em.persist(domainObject);
    }

    public final Collection<E> getAllEntities() {
            final EntityManager em = getEntityManager();
            final CriteriaBuilder cb = em.getCriteriaBuilder();
            final CriteriaQuery<E> query = cb.createQuery(getDomainObjectClass());

            final List<E> result = em.createQuery(query).getResultList();
            return Collections.unmodifiableList(result);
    }

    public final E find(K id) {
            Preconditions.checkNotNull(id);
            final EntityManager em = getEntityManager();
            return em.find(getDomainObjectClass(), id);
    }

    // [...]
}

Now there may be a bean that does not require entity-dependent query capabilities but just a repository of a certain entity type, like (might be a test case):

public class DomainObjectARepositoryTest{

    @Inject
    Repository<DomainObjectA, PersistableUUID> domainObjectARepository;


    @Test
    public void testMitarbeitererstellung() {
        for (DomainObjectA a : domainObjectARepository.getAllEntities()) {
            // do cool stuff
        }       
    }
}

Unfortunatly Weld does not seem to like this kind of generic injection. At deployment time, I get the following error:

state=Create: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Repository<DomainObjectA , PersistableUUID>] with qualifiers [@Default] at injection point [[field] @Inject sompackage.DomainObjectARepositoryTest.domainObjectARepository]

Am I missing something or did they just forgot to implement generic injects? As far as I understand the generic stuff, it is erasured after compiletime anyway - even this worked so fine in guice3 so far.

Kind regards,

avi

edit: found a comment by garvin king that this behavior is in the spec, but not implemented in weld, (staement was in june 2009)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吻安 2024-11-23 13:27:58

这是一个很长的评论,而不是对你的问题的完整答案,但可能会为你指明正确的方向:

我正在关注 seam-dev & 中的讨论。焊接开发已经有一段时间了,并且不记得曾经出现过类似的事情。所以我的猜测是,自从加文发表评论以来,它就没有被提上议程。

你可以相对容易地验证这个假设:

(a) 获取对 BeanManager 的引用并查询它以获取相关的 bean 类型(或者只是将 Object 放在保存端)您必须在 DomainObjectARepositoryTest 中删除 @Inject 才能启动应用程序。

(b) 注册扩展并监听 ProcessBean 以了解部署期间发生的情况。这将是我建议的方法,您会找到更多信息此处

有了这个结果,您绝对应该能够判断是否有任何 bean 类型 Repository> 徘徊:-)

如果您能在此处报告结果并考虑在负面情况下提交 Jira 问题,那就太好了。

That's rather a long comment than a complete answer to your question, but might point you in the right direction:

I'm following the discussions in seam-dev & weld-dev since quite some time, and do not remember that anything like this ever popped up. So my guess would be that it hasn't been on the agenda ever since Gavin commented about it.

What you can do relatively easy to verify this assumption:

(a) Obtain a reference to the BeanManager and query it for the relevant bean type (or just for Object to be on the save side), of course you will have to remove @Inject in DomainObjectARepositoryTest in order to get the application started.

(b) Register an extension and listen to ProcessBean to what comes up during the deployment. That would be my suggested way to go, you'll find more information here.

With that outcome you should definitely be able to tell if there are any bean types Repository<E, K extends Serializable & Comparable<K>> hanging around :-)

Would be cool if you'd report back here with the results and also considered filing a Jira issue in the negative case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文