Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JBoss EAP 7.1 Spring-Data-JPA CDI Extension

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.

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 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>)

This eventually causes...

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

...to throw:

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)


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

Edit: 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 ;
    }
like image 840
Cary Avatar asked Nov 07 '22 03:11

Cary


1 Answers

The solution to my problem was two small changes:

  • Add @ApplicationScoped to the producer class. Apparently WELD no longer sees @Producer annotations and processes the producer class without this (I think) because the default scope is @Dependent.
  • Remove @PersistenceContext and the parameter from the createEntityManager(...) producer method, referencing entityManagerFactory in it instead. It's odd that this even worked with the earlier version since @PersistenceContext "Expresses a dependency on a container-managed EntityManager..." which the new WELD barked about since the parameter was an EntityManagerFactory.

My producer class:

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() ;
    }
}
like image 123
Cary Avatar answered Nov 12 '22 17:11

Cary