diff --git a/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java b/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java index a97f980c65937..147d23a5dc576 100644 --- a/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java +++ b/core/deployment/src/main/java/org/jboss/shamrock/deployment/RuntimePriority.java @@ -19,4 +19,5 @@ public class RuntimePriority { public static final int BEAN_VALIDATION_DEPLOYMENT = 600; public static final int TRANSACTIONS_DEPLOYMENT = 700; public static final int DATASOURCE_DEPLOYMENT = 700; + public static final int BOOTSTRAP_EMF = 800; } 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 index 511ec8c5ebf95..9f8f491028f24 100644 --- 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 @@ -35,6 +35,9 @@ import org.jboss.shamrock.deployment.BeanDeployment; import org.jboss.shamrock.deployment.ProcessorContext; import org.jboss.shamrock.deployment.ResourceProcessor; +import org.jboss.shamrock.deployment.RuntimePriority; +import org.jboss.shamrock.deployment.codegen.BytecodeRecorder; +import org.jboss.shamrock.jpa.runtime.JPADeploymentTemplate; import org.jboss.shamrock.jpa.runtime.cdi.SystemEntityManager; import org.jboss.shamrock.jpa.runtime.cdi.TransactionScopedEntityManager; @@ -88,82 +91,91 @@ public void process(ArchiveContext archiveContext, ProcessorContext processorCon } - for (String name : knownContextNames) { - String className = getClass().getName() + "$$EMProducer-" + name; - AtomicReference bytes = new AtomicReference<>(); + try(BytecodeRecorder recorder = processorContext.addDeploymentTask(RuntimePriority.BOOTSTRAP_EMF)) { + JPADeploymentTemplate template = recorder.getRecordingProxy(JPADeploymentTemplate.class); - //we need to know if transactions are present or not - //TODO: this should be based on if a PU is JTA enabled or not - if (processorContext.isCapabilityPresent("transactions")) { - try (ClassCreator creator = new ClassCreator(new InMemoryClassOutput(bytes, processorContext), className, null, Object.class.getName())) { + for (String name : knownContextNames) { + String className = getClass().getName() + "$$EMProducer-" + name; + AtomicReference bytes = new AtomicReference<>(); - creator.addAnnotation(Dependent.class); + //we need to know if transactions are present or not + //TODO: this should be based on if a PU is JTA enabled or not + if (processorContext.isCapabilityPresent("transactions")) { + boolean system = false; + try (ClassCreator creator = new ClassCreator(new InMemoryClassOutput(bytes, processorContext), className, null, Object.class.getName())) { - FieldCreator emfField = creator.getFieldCreator("emf", EntityManagerFactory.class); - emfField.addAnnotation(Inject.class); - if (!knownUnitNames.contains(name)) { - emfField.addAnnotation(SystemEntityManager.class); - } - FieldDescriptor emf = emfField.getFieldDescriptor(); + creator.addAnnotation(Dependent.class); + FieldCreator emfField = creator.getFieldCreator("emf", EntityManagerFactory.class); + emfField.addAnnotation(Inject.class); + if (!knownUnitNames.contains(name)) { + emfField.addAnnotation(SystemEntityManager.class); + system = true; + } + FieldDescriptor emf = emfField.getFieldDescriptor(); - FieldCreator tsrField = creator.getFieldCreator("tsr", TransactionSynchronizationRegistry.class); - tsrField.addAnnotation(Inject.class); - FieldDescriptor tsr = tsrField.getFieldDescriptor(); + FieldCreator tsrField = creator.getFieldCreator("tsr", TransactionSynchronizationRegistry.class); + tsrField.addAnnotation(Inject.class); + FieldDescriptor tsr = tsrField.getFieldDescriptor(); - FieldCreator tmField = creator.getFieldCreator("tm", TransactionManager.class); - tmField.addAnnotation(Inject.class); - FieldDescriptor tm = tmField.getFieldDescriptor(); - MethodCreator producer = creator.getMethodCreator("producerMethod", EntityManager.class); - producer.addAnnotation(Produces.class); - producer.addAnnotation(RequestScoped.class); + FieldCreator tmField = creator.getFieldCreator("tm", TransactionManager.class); + tmField.addAnnotation(Inject.class); + FieldDescriptor tm = tmField.getFieldDescriptor(); - ResultHandle emfRh = producer.readInstanceField(emf, producer.getThis()); - ResultHandle tsrRh = producer.readInstanceField(tsr, producer.getThis()); - ResultHandle tmRh = producer.readInstanceField(tm, producer.getThis()); + MethodCreator producer = creator.getMethodCreator("producerMethod", EntityManager.class); + producer.addAnnotation(Produces.class); + producer.addAnnotation(RequestScoped.class); - producer.returnValue(producer.newInstance(MethodDescriptor.ofConstructor(TransactionScopedEntityManager.class, TransactionManager.class, TransactionSynchronizationRegistry.class, EntityManagerFactory.class), tmRh, tsrRh, emfRh)); + ResultHandle emfRh = producer.readInstanceField(emf, producer.getThis()); + ResultHandle tsrRh = producer.readInstanceField(tsr, producer.getThis()); + ResultHandle tmRh = producer.readInstanceField(tm, producer.getThis()); + producer.returnValue(producer.newInstance(MethodDescriptor.ofConstructor(TransactionScopedEntityManager.class, TransactionManager.class, TransactionSynchronizationRegistry.class, EntityManagerFactory.class), tmRh, tsrRh, emfRh)); - MethodCreator disposer = creator.getMethodCreator("disposerMethod", void.class, EntityManager.class); - disposer.getParameterAnnotations(0).addAnnotation(Disposes.class); - disposer.invokeVirtualMethod(MethodDescriptor.ofMethod(TransactionScopedEntityManager.class, "requestDone", void.class), disposer.getMethodParam(0)); - disposer.returnValue(null); + MethodCreator disposer = creator.getMethodCreator("disposerMethod", void.class, EntityManager.class); + disposer.getParameterAnnotations(0).addAnnotation(Disposes.class); + disposer.invokeVirtualMethod(MethodDescriptor.ofMethod(TransactionScopedEntityManager.class, "requestDone", void.class), disposer.getMethodParam(0)); + disposer.returnValue(null); - } - beanDeployment.addGeneratedBean(className, bytes.get()); - } else { - //if there is no TX support then we just use a super simple approach, and produce a normal EM - try (ClassCreator creator = new ClassCreator(new InMemoryClassOutput(bytes, processorContext), className, null, Object.class.getName())) { + } + beanDeployment.addGeneratedBean(className, bytes.get()); + template.boostrapPu(null, system); + } else { + boolean system = false; + //if there is no TX support then we just use a super simple approach, and produce a normal EM + try (ClassCreator creator = new ClassCreator(new InMemoryClassOutput(bytes, processorContext), className, null, Object.class.getName())) { - creator.addAnnotation(Dependent.class); + creator.addAnnotation(Dependent.class); - FieldCreator emfField = creator.getFieldCreator("emf", EntityManagerFactory.class); - emfField.addAnnotation(Inject.class); - if (!knownUnitNames.contains(name)) { - emfField.addAnnotation(SystemEntityManager.class); - } - FieldDescriptor emf = emfField.getFieldDescriptor(); + FieldCreator emfField = creator.getFieldCreator("emf", EntityManagerFactory.class); + emfField.addAnnotation(Inject.class); + if (!knownUnitNames.contains(name)) { + emfField.addAnnotation(SystemEntityManager.class); + system = true; + } + FieldDescriptor emf = emfField.getFieldDescriptor(); - MethodCreator producer = creator.getMethodCreator("producerMethod", EntityManager.class); - producer.addAnnotation(Produces.class); - producer.addAnnotation(Dependent.class); + MethodCreator producer = creator.getMethodCreator("producerMethod", EntityManager.class); + producer.addAnnotation(Produces.class); + producer.addAnnotation(Dependent.class); - ResultHandle factory = producer.readInstanceField(emf, producer.getThis()); - producer.returnValue(producer.invokeInterfaceMethod(MethodDescriptor.ofMethod(EntityManagerFactory.class, "createEntityManager", EntityManager.class), factory)); + ResultHandle factory = producer.readInstanceField(emf, producer.getThis()); + producer.returnValue(producer.invokeInterfaceMethod(MethodDescriptor.ofMethod(EntityManagerFactory.class, "createEntityManager", EntityManager.class), factory)); - MethodCreator disposer = creator.getMethodCreator("disposerMethod", void.class, EntityManager.class); - disposer.getParameterAnnotations(0).addAnnotation(Disposes.class); - disposer.invokeInterfaceMethod(MethodDescriptor.ofMethod(EntityManager.class, "close", void.class), disposer.getMethodParam(0)); - disposer.returnValue(null); + MethodCreator disposer = creator.getMethodCreator("disposerMethod", void.class, EntityManager.class); + disposer.getParameterAnnotations(0).addAnnotation(Disposes.class); + disposer.invokeInterfaceMethod(MethodDescriptor.ofMethod(EntityManager.class, "close", void.class), disposer.getMethodParam(0)); + disposer.returnValue(null); + } + beanDeployment.addGeneratedBean(className, bytes.get()); + template.boostrapPu(null, system); } - beanDeployment.addGeneratedBean(className, bytes.get()); } } diff --git a/jpa/runtime/src/main/java/org/jboss/shamrock/jpa/runtime/JPADeploymentTemplate.java b/jpa/runtime/src/main/java/org/jboss/shamrock/jpa/runtime/JPADeploymentTemplate.java index fecbfa9040384..f57fbcfe96108 100644 --- a/jpa/runtime/src/main/java/org/jboss/shamrock/jpa/runtime/JPADeploymentTemplate.java +++ b/jpa/runtime/src/main/java/org/jboss/shamrock/jpa/runtime/JPADeploymentTemplate.java @@ -1,10 +1,17 @@ package org.jboss.shamrock.jpa.runtime; import org.hibernate.protean.Hibernate; +import org.jboss.shamrock.jpa.runtime.cdi.SystemEntityManager; +import org.jboss.shamrock.runtime.BeanContainer; +import org.jboss.shamrock.runtime.ContextObject; +import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; +import javax.enterprise.util.AnnotationLiteral; +import javax.persistence.EntityManagerFactory; + /** * @author Emmanuel Bernard emmanuel@hibernate.org */ @@ -22,4 +29,20 @@ public void enlistPersistenceUnit() { public void callHibernateFeatureInit() { Hibernate.featureInit(); } + + public void boostrapPu(@ContextObject("bean.container") BeanContainer beanContainer, boolean synthetic) { + //TODO: we need to take qualifiers into account, at the moment we can only have one EM, but this is probably fine for the PoC + if(synthetic) { + beanContainer.instance(EntityManagerFactory.class, new AnnotationLiteral() { + + @Override + public Class annotationType() { + return SystemEntityManager.class; + } + }).getProperties(); + } else { + beanContainer.instance(EntityManagerFactory.class).getProperties(); + } + } + }