Skip to content

Commit

Permalink
Start EMF eagerly to get early feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Sep 20, 2018
1 parent ddc2a09 commit a70061f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -88,82 +91,91 @@ public void process(ArchiveContext archiveContext, ProcessorContext processorCon
}


for (String name : knownContextNames) {
String className = getClass().getName() + "$$EMProducer-" + name;
AtomicReference<byte[]> 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<byte[]> 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());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 [email protected]
*/
Expand All @@ -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<SystemEntityManager>() {

@Override
public Class<? extends Annotation> annotationType() {
return SystemEntityManager.class;
}
}).getProperties();
} else {
beanContainer.instance(EntityManagerFactory.class).getProperties();
}
}

}

0 comments on commit a70061f

Please sign in to comment.