diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java index 789778c65e9f6..6d983e6d332f8 100644 --- a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java +++ b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JPATestBootstrapEndpoint.java @@ -1,5 +1,6 @@ package org.jboss.shamrock.example.jpa; +import javax.inject.Inject; import javax.persistence.*; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; @@ -22,6 +23,9 @@ @WebServlet(name = "JPATestBootstrapEndpoint", urlPatterns = "/jpa/testbootstrap") public class JPATestBootstrapEndpoint extends HttpServlet { + @Inject + private EntityManagerFactory entityManagerFactory; + @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { try { @@ -37,12 +41,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO public void testStoreLoadOnJPA() throws Exception { - EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "templatePU" ); - System.out.println( "Hibernate EntityManagerFactory: booted" ); - doStuffWithHibernate( entityManagerFactory ); - - entityManagerFactory.close(); System.out.println( "Hibernate EntityManagerFactory: shut down" ); } diff --git a/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JpaProducer.java b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JpaProducer.java new file mode 100644 index 0000000000000..9efa56f0de8f0 --- /dev/null +++ b/examples/strict/src/main/java/org/jboss/shamrock/example/jpa/JpaProducer.java @@ -0,0 +1,13 @@ +package org.jboss.shamrock.example.jpa; + +import javax.enterprise.inject.Produces; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceUnit; + +public class JpaProducer { + + @Produces + @PersistenceUnit(unitName = "templatePU") + EntityManagerFactory emf; +} diff --git a/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapITCase.java b/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapITCase.java new file mode 100644 index 0000000000000..c4845fb4f4366 --- /dev/null +++ b/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapITCase.java @@ -0,0 +1,10 @@ +package org.jboss.shamrock.example.test; + +import org.jboss.shamrock.junit.GraalTest; +import org.junit.runner.RunWith; + + +@RunWith(GraalTest.class) +public class JPABootstrapITCase extends JPABootstrapTestCase { + +} diff --git a/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapInGraalITCase.java b/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapTestCase.java similarity index 73% rename from examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapInGraalITCase.java rename to examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapTestCase.java index 185ebdfdb2bf7..0573f8bfad26b 100644 --- a/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapInGraalITCase.java +++ b/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPABootstrapTestCase.java @@ -1,22 +1,23 @@ package org.jboss.shamrock.example.test; +import static org.junit.Assert.assertEquals; + import org.jboss.shamrock.example.testutils.URLTester; import org.jboss.shamrock.junit.GraalTest; +import org.jboss.shamrock.junit.ShamrockTest; import org.junit.Test; import org.junit.runner.RunWith; -import static org.junit.Assert.assertEquals; - /** * Test reflection around JPA entities * * @author Emmanuel Bernard emmanuel@hibernate.org */ -@RunWith(GraalTest.class) -public class JPABootstrapInGraalITCase { +@RunWith(ShamrockTest.class) +public class JPABootstrapTestCase { @Test - public void testFieldAndGetterReflectionOnEntityFromServlet() throws Exception { + public void testJpaBootstrap() throws Exception { assertEquals("OK", URLTester.relative("jpa/testbootstrap").invokeURL().asString()); } diff --git a/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPAStoreLoadTestCase.java b/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPAStoreLoadTestCase.java deleted file mode 100644 index 9b7d9b54974e8..0000000000000 --- a/examples/strict/src/test/java/org/jboss/shamrock/example/test/JPAStoreLoadTestCase.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.jboss.shamrock.example.test; - -import java.util.List; -import java.util.UUID; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.EntityTransaction; -import javax.persistence.Persistence; -import javax.persistence.TypedQuery; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Root; - -import org.jboss.shamrock.example.jpa.Person; -import org.jboss.shamrock.example.jpa.SequencedAddress; -import org.jboss.shamrock.junit.ShamrockTest; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * - */ -@RunWith(ShamrockTest.class) -public class JPAStoreLoadTestCase { - - @Test - public void testStoreLoadOnJPA() throws Exception { - EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory( "templatePU" ); - System.out.println( "Hibernate EntityManagerFactory: booted" ); - - doStuffWithHibernate( entityManagerFactory ); - - entityManagerFactory.close(); - System.out.println( "Hibernate EntityManagerFactory: shut down" ); - - } - - - private static void doStuffWithHibernate(EntityManagerFactory entityManagerFactory) { - EntityManager em = entityManagerFactory.createEntityManager(); - EntityTransaction transaction = em.getTransaction(); - transaction.begin(); - - persistNewPerson( em ); - - listExistingPersons( em ); - - transaction.commit(); - em.close(); - } - - private static void listExistingPersons(EntityManager em) { - CriteriaBuilder cb = em.getCriteriaBuilder(); - - CriteriaQuery cq = cb.createQuery( Person.class ); - Root from = cq.from( Person.class ); - cq.select( from ); - TypedQuery q = em.createQuery( cq ); - List allpersons = q.getResultList(); - StringBuilder sb = new StringBuilder( "list of stored Person names:\n\t" ); - for ( Person p : allpersons ) { - p.describeFully( sb ); - sb.append( "\n\t" ); - } - sb.append( "\nList complete.\n" ); - System.out.print( sb ); - } - - private static void persistNewPerson(EntityManager entityManager) { - Person person = new Person(); - person.setName( randomName() ); - person.setAddress( new SequencedAddress( "Street " + randomName() ) ); - entityManager.persist( person ); - } - - private static String randomName() { - return UUID.randomUUID().toString(); - } - - -} diff --git a/jpa/deployment/pom.xml b/jpa/deployment/pom.xml index 37305ea3523fb..41b006a3742ce 100644 --- a/jpa/deployment/pom.xml +++ b/jpa/deployment/pom.xml @@ -19,6 +19,10 @@ org.jboss.shamrock shamrock-jpa-runtime + + org.jboss.shamrock + shamrock-transactions-deployment + junit diff --git a/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/HibernateResourceProcessor.java b/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/HibernateResourceProcessor.java index 5915eb3f985a5..980ea84895c01 100644 --- a/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/HibernateResourceProcessor.java +++ b/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/HibernateResourceProcessor.java @@ -27,6 +27,9 @@ public void process(final ArchiveContext archiveContext, final ProcessorContext //Modify the bytecode of all entities to enable lazy-loading, dirty checking, etc.. enhanceEntities(domainObjects, archiveContext, processorContext); + + + } private void enhanceEntities(final KnownDomainObjects domainObjects, ArchiveContext archiveContext, ProcessorContext processorContext) { diff --git a/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/JpaSetup.java b/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/JpaSetup.java index 5026d444249dd..11b1ce88fb8b2 100644 --- a/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/JpaSetup.java +++ b/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/JpaSetup.java @@ -2,10 +2,12 @@ import org.jboss.shamrock.deployment.SetupContext; import org.jboss.shamrock.deployment.ShamrockSetup; +import org.jboss.shamrock.jpa.cdi.HibernateCdiResourceProcessor; public class JpaSetup implements ShamrockSetup { @Override public void setup(SetupContext context) { context.addResourceProcessor(new HibernateResourceProcessor()); + context.addResourceProcessor(new HibernateCdiResourceProcessor()); } } diff --git a/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/cdi/HibernateCdiResourceProcessor.java b/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/cdi/HibernateCdiResourceProcessor.java new file mode 100644 index 0000000000000..a924f5e0f811e --- /dev/null +++ b/jpa/deployment/src/main/java/org/jboss/shamrock/jpa/cdi/HibernateCdiResourceProcessor.java @@ -0,0 +1,105 @@ +package org.jboss.shamrock.jpa.cdi; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceUnit; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; +import org.jboss.jandex.DotName; +import org.jboss.protean.gizmo.ClassCreator; +import org.jboss.protean.gizmo.ClassOutput; +import org.jboss.protean.gizmo.MethodCreator; +import org.jboss.protean.gizmo.MethodDescriptor; +import org.jboss.protean.gizmo.ResultHandle; +import org.jboss.shamrock.deployment.ArchiveContext; +import org.jboss.shamrock.deployment.BeanDeployment; +import org.jboss.shamrock.deployment.ProcessorContext; +import org.jboss.shamrock.deployment.ResourceProcessor; + +public class HibernateCdiResourceProcessor implements ResourceProcessor { + + private static final DotName PERSISTENCE_CONTEXT = DotName.createSimple(PersistenceContext.class.getName()); + private static final DotName PERSISTENCE_UNIT = DotName.createSimple(PersistenceUnit.class.getName()); + private static final DotName PRODUCES = DotName.createSimple(Produces.class.getName()); + + @Inject + private BeanDeployment beanDeployment; + + @Override + public void process(ArchiveContext archiveContext, ProcessorContext processorContext) throws Exception { + Set knownUnitNames = new HashSet<>(); + Set knownContextNames = new HashSet<>(); + scanForAnnotations(archiveContext, knownUnitNames, PERSISTENCE_UNIT); + scanForAnnotations(archiveContext, knownContextNames, PERSISTENCE_CONTEXT); + knownUnitNames.remove(""); //TODO: support for the default PU + //now create producer beans for all of the above unit names + //this is not great, we really need a better way to do this than generating bytecode + for (String name : knownUnitNames) { + String className = getClass().getName() + "$$EMFProducer-" + name; + AtomicReference bytes = new AtomicReference<>(); + try (ClassCreator creator = new ClassCreator(new ClassOutput() { + @Override + public void write(String name, byte[] data) { + try { + bytes.set(data); + processorContext.addGeneratedClass(true, name, data); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }, className, null, Object.class.getName())) { + + creator.addAnnotation(Dependent.class); + MethodCreator producer = creator.getMethodCreator("producerMethod", EntityManagerFactory.class); + producer.addAnnotation(Produces.class); + producer.addAnnotation(ApplicationScoped.class); + + ResultHandle ret = producer.invokeStaticMethod(MethodDescriptor.ofMethod(Persistence.class, "createEntityManagerFactory", EntityManagerFactory.class, String.class), producer.load(name)); + producer.returnValue(ret); + } + beanDeployment.addGeneratedBean(className, bytes.get()); + } + + + } + + private void scanForAnnotations(ArchiveContext archiveContext, Set knownUnitNames, DotName nm) { + for (AnnotationInstance anno : archiveContext.getCombinedIndex().getAnnotations(nm)) { + if (anno.target().kind() == AnnotationTarget.Kind.METHOD) { + if (anno.target().asMethod().hasAnnotation(PRODUCES)) { + knownUnitNames.add(anno.value("unitName").asString()); + } + } else if (anno.target().kind() == AnnotationTarget.Kind.FIELD) { + for (AnnotationInstance i : anno.target().asField().annotations()) { + if (i.name().equals(PRODUCES)) { + knownUnitNames.add(anno.value("unitName").asString()); + break; + } + } + } else if (anno.target().kind() == AnnotationTarget.Kind.CLASS) { + for (AnnotationInstance i : anno.target().asClass().classAnnotations()) { + if (i.name().equals(PRODUCES)) { + knownUnitNames.add(anno.value("unitName").asString()); + break; + } + } + } + } + } + + @Override + public int getPriority() { + return 0; + } +}