JBoss EAP 7.1 Spring-Data-JPA CDI扩展

JBoss EAP 7.1 Spring-Data-JPA CDI扩展

问题描述:

我们有一个应用程序,该应用程序使用Spring Data JPA存储库注入EJB. Spring的org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension发挥了魔力.

We have an app that uses Spring Data JPA repositories to inject into EJB's. Spring's org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension does the magic.

它将在CDI中查找EntityManager,将其保存以备后用,使用@Repository注释查找Spring Data JPA存储库,并保存其类型以备后用.初始化CDI后,将运行JpaRepositoryExtension::afterBeanDiscovery并进行正确的Bean创建并将其插入CDI.在JBoss EAP 6.2/6.3/6.4下,此功能运行良好.

It looks for an EntityManager in CDI, saves it for later use, looks for Spring Data JPA repositories using the @Repository annotation, and saves their types for later use. When CDI is initialized, JpaRepositoryExtension::afterBeanDiscovery runs and to do the proper bean creation and insertion into CDI. This has worked perfectly under JBoss EAP 6.2/6.3/6.4.

JBoss EAP 7.1是基于WildFly 11构建的,而Hibernate版本现在是5.1. JPA引导程序代码已在JBoss和Hibernate JPA提供程序中进行了重组.由于进行了这种重组,因此运行时EntityManager在CDI中不是:

JBoss EAP 7.1 is built on WildFly 11 and the Hibernate version is now 5.1. The JPA bootstrap code has been restructured in JBoss and the Hibernate JPA provider. Due to this restructuring the EntityManager is not in CDI at the time that this runs:

org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension.processBean(ProcessBean<X>)

这最终会导致...

org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension.createRepositoryBean(Class<?>, Set<Annotation>, BeanManager)

...抛出:

javax.enterprise.inject.UnsatisfiedResolutionException:无法执行 用限定符为"javax.persistence.EntityManager"解析一个bean [@ javax.enterprise.inject.Default(),@ javax.enterprise.inject.Any()]. 在 org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension.createRepositoryBean(JpaRepositoryExtension.java:120) 在 org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension.afterBeanDiscovery(JpaRepositoryExtension.java:96)

javax.enterprise.inject.UnsatisfiedResolutionException: Unable to resolve a bean for 'javax.persistence.EntityManager' with qualifiers [@javax.enterprise.inject.Default(), @javax.enterprise.inject.Any()]. at org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension.createRepositoryBean(JpaRepositoryExtension.java:120) at org.springframework.data.jpa.repository.cdi.JpaRepositoryExtension.afterBeanDiscovery(JpaRepositoryExtension.java:96)


是否有人成功将Spring Data JPA部署到JBoss EAP 7.1或WildFly 11+上,并获得了在CDI中创建的JPA存储库?


Has anyone successfully deployed Spring Data JPA onto JBoss EAP 7.1 or WildFly 11+ and gotten the JPA repositories created in CDI?

我有一个CDI生产者,可以在EAP 6.2/3/4中正常工作:

I have a CDI Producer that works fine in EAP 6.2/3/4:

    @Produces
    @Dependent
    @PersistenceUnit( unitName="** Our PU Name **" )
    private EntityManagerFactory entityManagerFactory;
.
.
.
    @Produces
    @RequestScoped
    @PersistenceContext( type = PersistenceContextType.EXTENDED )
    public EntityManager createEntityManager( EntityManagerFactory emf )
    {
        EntityManager em = emf.createEntityManager();
        return em ;
    }

我的问题的解决方案是两个小的更改:

The solution to my problem was two small changes:

  • 将@ApplicationScoped添加到生产者类.显然,WELD不再看到@Producer批注并在没有此注释的情况下处理生产者类(我认为),因为默认范围是@Dependent.
  • 从createEntityManager(...)生产者方法中删除@PersistenceContext和参数,改为在其中引用EntityManagerFactory.奇怪的是,这甚至可以与早期版本一起使用,因为@PersistenceContext表达了对容器管理的EntityManager的依赖...",由于参数是EntityManagerFactory,新的WELD强烈要求它.

我的制作人班级:

import javax.enterprise.context.ApplicationScoped ;
import javax.enterprise.context.Dependent ;
import javax.enterprise.context.RequestScoped ;
import javax.enterprise.inject.Disposes ;
import javax.enterprise.inject.Produces ;
import javax.persistence.EntityManager ;
import javax.persistence.EntityManagerFactory ;
import javax.persistence.PersistenceUnit ;


@ApplicationScoped
public class CdiConfig
{
    /*
     * Entity Manager Factory
     */
    @Produces
    @Dependent
    @PersistenceUnit(unitName = "stafftrack_data_access")
    private EntityManagerFactory entityManagerFactory ;


    /*
     * Entity Manager
     */
    @Produces
    @RequestScoped
    public EntityManager createEntityManager( )
    {
        EntityManager em = entityManagerFactory.createEntityManager() ;
        return em ;
    }


    public void close( @Disposes EntityManager entityManager )
    {
        entityManager.close() ;
    }
}