mirror of
https://github.com/jlengrand/quarkus.git
synced 2026-03-10 08:41:22 +00:00
Merge pull request #25 from stuartwdouglas/emi
Entity Manager injection support
This commit is contained in:
@@ -74,6 +74,7 @@ public class BuildTimeGenerator {
|
||||
private final List<Function<String, Function<ClassVisitor, ClassVisitor>>> bytecodeTransformers = new ArrayList<>();
|
||||
private final Set<String> applicationArchiveMarkers;
|
||||
private final ArchiveContextBuilder archiveContextBuilder;
|
||||
private final Set<String> capabilities;
|
||||
|
||||
public BuildTimeGenerator(ClassOutput classOutput, ClassLoader cl, boolean useStaticInit, ArchiveContextBuilder contextBuilder) {
|
||||
this.useStaticInit = useStaticInit;
|
||||
@@ -91,6 +92,7 @@ public class BuildTimeGenerator {
|
||||
this.classLoader = cl;
|
||||
this.applicationArchiveMarkers = new HashSet<>(setupContext.applicationArchiveMarkers);
|
||||
this.archiveContextBuilder = contextBuilder;
|
||||
this.capabilities = new HashSet<>(setupContext.capabilities);
|
||||
}
|
||||
|
||||
public List<Function<String, Function<ClassVisitor, ClassVisitor>>> getBytecodeTransformers() {
|
||||
@@ -294,6 +296,11 @@ public class BuildTimeGenerator {
|
||||
this.proxyClasses.add(Arrays.asList(proxyClasses));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCapabilityPresent(String capability) {
|
||||
return capabilities.contains(capability);
|
||||
}
|
||||
|
||||
|
||||
void writeMainClass() throws IOException {
|
||||
|
||||
|
||||
@@ -108,4 +108,11 @@ public interface ProcessorContext {
|
||||
* @param proxyClasses The interface names that this proxy will implement
|
||||
*/
|
||||
void addProxyDefinition(String ... proxyClasses);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param capability
|
||||
* @return
|
||||
*/
|
||||
boolean isCapabilityPresent(String capability);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ public class RuntimePriority {
|
||||
public static final int JAXRS_DEPLOYMENT = 350;
|
||||
public static final int ARC_DEPLOYMENT = 300;
|
||||
public static final int UNDERTOW_DEPLOY = 400;
|
||||
public static final int UNDERTOW_START = 500;
|
||||
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;
|
||||
public static final int UNDERTOW_START = 900;
|
||||
}
|
||||
|
||||
@@ -24,4 +24,10 @@ public interface SetupContext {
|
||||
* @param file The file location
|
||||
*/
|
||||
void addApplicationArchiveMarker(String file);
|
||||
|
||||
/**
|
||||
* Registers a capability name as being present, this can be queried via {@link ProcessorContext#isCapabilityPresent(String)}
|
||||
* @param name The capability name
|
||||
*/
|
||||
void addCapability(String name);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package org.jboss.shamrock.deployment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
class SetupContextImpl implements SetupContext {
|
||||
|
||||
final List<ResourceProcessor> resourceProcessors = new ArrayList<>();
|
||||
final List<InjectionProvider> injectionProviders = new ArrayList<>();
|
||||
final List<String> applicationArchiveMarkers = new ArrayList<>();
|
||||
final Set<String> capabilities = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void addResourceProcessor(ResourceProcessor resourceProcessor) {
|
||||
@@ -23,4 +26,8 @@ class SetupContextImpl implements SetupContext {
|
||||
public void addApplicationArchiveMarker(String file) {
|
||||
applicationArchiveMarkers.add(file);
|
||||
}
|
||||
|
||||
public void addCapability(String name) {
|
||||
capabilities.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,14 @@ public class RuntimeClassLoader extends ClassLoader implements ClassOutput, Cons
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
public Enumeration<URL> getResources(String nm) throws IOException {
|
||||
String name;
|
||||
if(nm.startsWith("/")) {
|
||||
name = nm.substring(1);
|
||||
} else {
|
||||
name = nm;
|
||||
}
|
||||
|
||||
// TODO some superugly hack for bean provider
|
||||
byte[] data = resources.get(name);
|
||||
if (data != null) {
|
||||
@@ -77,6 +84,28 @@ public class RuntimeClassLoader extends ClassLoader implements ClassOutput, Cons
|
||||
return super.getResources(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(String nm) {
|
||||
String name;
|
||||
if(nm.startsWith("/")) {
|
||||
name = nm.substring(1);
|
||||
} else {
|
||||
name = nm;
|
||||
}
|
||||
return super.getResource(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String nm) {
|
||||
String name;
|
||||
if(nm.startsWith("/")) {
|
||||
name = nm.substring(1);
|
||||
} else {
|
||||
name = nm;
|
||||
}
|
||||
return super.getResourceAsStream(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
Class<?> ex = findLoadedClass(name);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
|
||||
version="2.1">
|
||||
|
||||
<persistence-unit name="templatePU" transaction-type="RESOURCE_LOCAL">
|
||||
<persistence-unit name="templatePU" transaction-type="JTA">
|
||||
|
||||
<description>Hibernate test case template Persistence Unit</description>
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package org.jboss.shamrock.example.jpa;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityTransaction;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
/**
|
||||
* Various tests for the JPA integration.
|
||||
*/
|
||||
@WebServlet(urlPatterns = "/jpa/testjpaeminjection")
|
||||
public class JPATestEMInjectionEndpoint extends HttpServlet {
|
||||
|
||||
@Inject
|
||||
private EntityManager em;
|
||||
|
||||
@Inject
|
||||
private UserTransaction transaction;
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
try {
|
||||
testStoreLoadOnJPA();
|
||||
} catch (Exception e) {
|
||||
reportException("Oops, shit happened, No boot for you!", e, resp);
|
||||
}
|
||||
resp.getWriter().write("OK");
|
||||
}
|
||||
|
||||
|
||||
public void testStoreLoadOnJPA() throws Exception {
|
||||
doStuffWithHibernate();
|
||||
System.out.println("Hibernate EntityManagerFactory: shut down");
|
||||
|
||||
}
|
||||
|
||||
private void doStuffWithHibernate() throws Exception {
|
||||
transaction.begin();
|
||||
|
||||
persistNewPerson(em);
|
||||
|
||||
listExistingPersons(em);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
private static void listExistingPersons(EntityManager em) {
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
|
||||
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
|
||||
Root<Person> from = cq.from(Person.class);
|
||||
cq.select(from);
|
||||
TypedQuery<Person> q = em.createQuery(cq);
|
||||
List<Person> 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();
|
||||
}
|
||||
|
||||
private void reportException(final Exception e, final HttpServletResponse resp) throws IOException {
|
||||
reportException(null, e, resp);
|
||||
}
|
||||
|
||||
private void reportException(String errorMessage, final Exception e, final HttpServletResponse resp) throws IOException {
|
||||
final PrintWriter writer = resp.getWriter();
|
||||
if (errorMessage != null) {
|
||||
writer.write(errorMessage);
|
||||
writer.write(" ");
|
||||
}
|
||||
writer.write(e.toString());
|
||||
writer.append("\n\t");
|
||||
e.printStackTrace(writer);
|
||||
writer.append("\n\t");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jboss.shamrock.example.jpa;
|
||||
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceUnit;
|
||||
@@ -10,4 +11,8 @@ public class JpaProducer {
|
||||
@Produces
|
||||
@PersistenceUnit(unitName = "templatePU")
|
||||
EntityManagerFactory emf;
|
||||
|
||||
@Produces
|
||||
@PersistenceContext(unitName = "templatePU")
|
||||
EntityManager em;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
|
||||
version="2.1">
|
||||
|
||||
<persistence-unit name="templatePU" transaction-type="RESOURCE_LOCAL">
|
||||
<persistence-unit name="templatePU" transaction-type="JTA">
|
||||
|
||||
<description>Hibernate test case template Persistence Unit</description>
|
||||
|
||||
|
||||
@@ -0,0 +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.ShamrockTest;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Test reflection around JPA entities
|
||||
*
|
||||
* @author Emmanuel Bernard emmanuel@hibernate.org
|
||||
*/
|
||||
@RunWith(ShamrockTest.class)
|
||||
public class JPAEntityManagerInjectionTestCase {
|
||||
|
||||
@Test
|
||||
public void testJpaEntityManagerInjection() throws Exception {
|
||||
assertEquals("OK", URLTester.relative("jpa/testjpaeminjection").invokeURL().asString());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,9 @@ public interface AnnotatedElement {
|
||||
|
||||
AnnotationCreator addAnnotation(String annotationType);
|
||||
|
||||
AnnotationCreator addAnnotation(Class<?> annotationType);
|
||||
default AnnotationCreator addAnnotation(Class<?> annotationType) {
|
||||
return addAnnotation(annotationType.getName());
|
||||
}
|
||||
|
||||
default void addAnnotation(AnnotationInstance annotation) {
|
||||
AnnotationCreator ac = addAnnotation(annotation.name().toString());
|
||||
|
||||
@@ -150,11 +150,6 @@ public class ClassCreator implements AutoCloseable, AnnotatedElement {
|
||||
return ac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationCreator addAnnotation(Class<?> annotationType) {
|
||||
return addAnnotation(annotationType.getName());
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private ClassOutput classOutput;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.jboss.protean.gizmo;
|
||||
|
||||
|
||||
public interface FieldCreator extends MemberCreator<FieldCreator> {
|
||||
public interface FieldCreator extends MemberCreator<FieldCreator>,AnnotatedElement {
|
||||
|
||||
FieldDescriptor getFieldDescriptor();
|
||||
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
package org.jboss.protean.gizmo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
class FieldCreatorImpl implements FieldCreator {
|
||||
|
||||
private final FieldDescriptor fieldDescriptor;
|
||||
private final List<AnnotationCreatorImpl> annotations = new ArrayList<>();
|
||||
|
||||
private int modifiers;
|
||||
|
||||
@@ -32,7 +39,21 @@ class FieldCreatorImpl implements FieldCreator {
|
||||
|
||||
@Override
|
||||
public void write(ClassWriter file) {
|
||||
file.visitField(modifiers, fieldDescriptor.getName(), fieldDescriptor.getType(), null, null);
|
||||
FieldVisitor fieldVisitor = file.visitField(modifiers, fieldDescriptor.getName(), fieldDescriptor.getType(), null, null);
|
||||
for(AnnotationCreatorImpl annotation : annotations) {
|
||||
AnnotationVisitor av = fieldVisitor.visitAnnotation(DescriptorUtils.extToInt(annotation.getAnnotationType()), true);
|
||||
for(Map.Entry<String, Object> e : annotation.getValues().entrySet()) {
|
||||
av.visit(e.getKey(), e.getValue());
|
||||
}
|
||||
av.visitEnd();
|
||||
}
|
||||
fieldVisitor.visitEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationCreator addAnnotation(String annotationType) {
|
||||
AnnotationCreatorImpl ac = new AnnotationCreatorImpl(annotationType);
|
||||
annotations.add(ac);
|
||||
return ac;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,4 +39,6 @@ public interface MethodCreator extends MemberCreator<MethodCreator>, BytecodeCre
|
||||
*/
|
||||
MethodDescriptor getMethodDescriptor();
|
||||
|
||||
AnnotatedElement getParameterAnnotations(int param);
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package org.jboss.protean.gizmo;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
@@ -17,6 +17,7 @@ class MethodCreatorImpl extends BytecodeCreatorImpl implements MethodCreator {
|
||||
private int modifiers = Opcodes.ACC_PUBLIC;
|
||||
private final List<String> exceptions = new ArrayList<>();
|
||||
private final List<AnnotationCreatorImpl> annotations = new ArrayList<>();
|
||||
private final Map<Integer, AnnotationParameters> parameterAnnotations = new HashMap<>();
|
||||
|
||||
MethodCreatorImpl(MethodDescriptor methodDescriptor, String declaringClassName, ClassOutput classOutput, ClassCreator classCreator) {
|
||||
super(methodDescriptor, declaringClassName, classOutput, classCreator);
|
||||
@@ -38,6 +39,16 @@ class MethodCreatorImpl extends BytecodeCreatorImpl implements MethodCreator {
|
||||
return methodDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotatedElement getParameterAnnotations(int param) {
|
||||
if(parameterAnnotations.containsKey(param)) {
|
||||
return parameterAnnotations.get(param);
|
||||
}
|
||||
AnnotationParameters p = new AnnotationParameters();
|
||||
parameterAnnotations.put(param, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getModifiers() {
|
||||
return modifiers;
|
||||
@@ -53,6 +64,8 @@ class MethodCreatorImpl extends BytecodeCreatorImpl implements MethodCreator {
|
||||
public void write(ClassWriter file) {
|
||||
MethodVisitor visitor = file.visitMethod(modifiers, methodDescriptor.getName(), methodDescriptor.getDescriptor(), null, exceptions.toArray(new String[0]));
|
||||
|
||||
|
||||
|
||||
int localVarCount = Modifier.isStatic(modifiers) ? 0 : 1;
|
||||
for (int i = 0; i < methodDescriptor.getParameterTypes().length; ++i) {
|
||||
String s = methodDescriptor.getParameterTypes()[i];
|
||||
@@ -73,6 +86,15 @@ class MethodCreatorImpl extends BytecodeCreatorImpl implements MethodCreator {
|
||||
}
|
||||
av.visitEnd();
|
||||
}
|
||||
for(Map.Entry<Integer, AnnotationParameters> entry : parameterAnnotations.entrySet()) {
|
||||
for(AnnotationCreatorImpl annotation : entry.getValue().annotations) {
|
||||
AnnotationVisitor av = visitor.visitParameterAnnotation(entry.getKey(), DescriptorUtils.extToInt(annotation.getAnnotationType()), true);
|
||||
for(Map.Entry<String, Object> e : annotation.getValues().entrySet()) {
|
||||
av.visit(e.getKey(), e.getValue());
|
||||
}
|
||||
av.visitEnd();
|
||||
}
|
||||
}
|
||||
visitor.visitEnd();
|
||||
}
|
||||
|
||||
@@ -88,8 +110,17 @@ class MethodCreatorImpl extends BytecodeCreatorImpl implements MethodCreator {
|
||||
return ac;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationCreator addAnnotation(Class<?> annotationType) {
|
||||
return addAnnotation(annotationType.getName());
|
||||
|
||||
private static class AnnotationParameters implements AnnotatedElement {
|
||||
|
||||
final List<AnnotationCreatorImpl> annotations = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public AnnotationCreator addAnnotation(String annotationType) {
|
||||
AnnotationCreatorImpl ret = new AnnotationCreatorImpl(annotationType);
|
||||
annotations.add(ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hibernate-orm-protean-example</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>hibernate-orm-protean</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.cfg.beanvalidation.BeanValidationIntegrator;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformResolver;
|
||||
import org.hibernate.id.factory.spi.MutableIdentifierGeneratorFactory;
|
||||
@@ -268,8 +269,9 @@ class FastBootMetadataBuilder {
|
||||
}
|
||||
|
||||
private JtaPlatform extractJtaPlatform() {
|
||||
JtaPlatformResolver service = standardServiceRegistry.getService( JtaPlatformResolver.class );
|
||||
return service.resolveJtaPlatform( this.configurationValues, (ServiceRegistryImplementor) standardServiceRegistry );
|
||||
return new JBossStandAloneJtaPlatform();
|
||||
// JtaPlatformResolver service = standardServiceRegistry.getService( JtaPlatformResolver.class );
|
||||
// return service.resolveJtaPlatform( this.configurationValues, (ServiceRegistryImplementor) standardServiceRegistry );
|
||||
}
|
||||
|
||||
private Dialect extractDialect() {
|
||||
@@ -416,9 +418,11 @@ class FastBootMetadataBuilder {
|
||||
else {
|
||||
if ( txnType == PersistenceUnitTransactionType.JTA ) {
|
||||
ssrBuilder.applySetting( TRANSACTION_COORDINATOR_STRATEGY, JtaTransactionCoordinatorBuilderImpl.class );
|
||||
configurationValues.put(TRANSACTION_COORDINATOR_STRATEGY, JtaTransactionCoordinatorBuilderImpl.class);
|
||||
}
|
||||
else if ( txnType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
|
||||
ssrBuilder.applySetting( TRANSACTION_COORDINATOR_STRATEGY, JdbcResourceLocalTransactionCoordinatorBuilderImpl.class );
|
||||
configurationValues.put(TRANSACTION_COORDINATOR_STRATEGY, JdbcResourceLocalTransactionCoordinatorBuilderImpl.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package org.hibernate.protean.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
@@ -29,7 +32,7 @@ public class FlatClassLoaderService implements ClassLoaderService {
|
||||
@Override
|
||||
public <T> Class<T> classForName(String className) {
|
||||
try {
|
||||
return (Class<T>) Class.forName( className, false, Thread.currentThread().getContextClassLoader() );
|
||||
return (Class<T>) Class.forName( className, false, getClassLoader() );
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
log.errorf( "Could not load class '%s' using Class.forName(String)", className );
|
||||
@@ -39,7 +42,7 @@ public class FlatClassLoaderService implements ClassLoaderService {
|
||||
|
||||
@Override
|
||||
public URL locateResource(String name) {
|
||||
URL resource = FlatClassLoaderService.class.getResource( name );
|
||||
URL resource = getClassLoader().getResource( name );
|
||||
if ( resource == null ) {
|
||||
log.warnf( "Loading of resource '%s' failed. Maybe that's ok, maybe you forgot to include this resource in the binary image? -H:IncludeResources=", name );
|
||||
}
|
||||
@@ -51,7 +54,7 @@ public class FlatClassLoaderService implements ClassLoaderService {
|
||||
|
||||
@Override
|
||||
public InputStream locateResourceStream(String name) {
|
||||
InputStream resourceAsStream = FlatClassLoaderService.class.getResourceAsStream( name );
|
||||
InputStream resourceAsStream = getClassLoader().getResourceAsStream( name );
|
||||
if ( resourceAsStream == null ) {
|
||||
log.warnf( "Loading of resource '%s' failed. Maybe that's ok, maybe you forgot to include this resource in the binary image? -H:IncludeResources=", name );
|
||||
}
|
||||
@@ -64,12 +67,21 @@ public class FlatClassLoaderService implements ClassLoaderService {
|
||||
@Override
|
||||
public List<URL> locateResources(String name) {
|
||||
log.debugf( "locateResources (plural form) was invoked for resource '%s'. Is there a real need for this plural form?", name );
|
||||
return Collections.singletonList( locateResource( name ) );
|
||||
try {
|
||||
Enumeration<URL> resources = getClassLoader().getResources(name);
|
||||
List<URL> resource = new ArrayList<>();
|
||||
while (resources.hasMoreElements()) {
|
||||
resource.add(resources.nextElement());
|
||||
}
|
||||
return resource;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S> Collection<S> loadJavaServices(Class<S> serviceContract) {
|
||||
ServiceLoader<S> serviceLoader = ServiceLoader.load( serviceContract );
|
||||
ServiceLoader<S> serviceLoader = ServiceLoader.load( serviceContract , getClassLoader());
|
||||
final LinkedHashSet<S> services = new LinkedHashSet<S>();
|
||||
for ( S service : serviceLoader ) {
|
||||
services.add( service );
|
||||
@@ -85,7 +97,7 @@ public class FlatClassLoaderService implements ClassLoaderService {
|
||||
|
||||
@Override
|
||||
public <T> T workWithClassLoader(Work<T> work) {
|
||||
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
|
||||
ClassLoader systemClassLoader = getClassLoader();
|
||||
return work.doWork( systemClassLoader );
|
||||
}
|
||||
|
||||
@@ -94,4 +106,12 @@ public class FlatClassLoaderService implements ClassLoaderService {
|
||||
//easy!
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader() {
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
if(cl == null) {
|
||||
return FlatClassLoaderService.class.getClassLoader();
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ import org.hibernate.engine.jdbc.connections.internal.MultiTenantConnectionProvi
|
||||
import org.hibernate.engine.jdbc.cursor.internal.RefCursorSupportInitiator;
|
||||
import org.hibernate.engine.jdbc.internal.JdbcServicesInitiator;
|
||||
import org.hibernate.engine.jndi.internal.JndiServiceInitiator;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JBossStandAloneJtaPlatform;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator;
|
||||
import org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformResolverInitiator;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.hql.internal.QueryTranslatorFactoryInitiator;
|
||||
import org.hibernate.id.factory.internal.MutableIdentifierGeneratorFactoryInitiator;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
@@ -39,6 +41,7 @@ import org.hibernate.resource.transaction.internal.TransactionCoordinatorBuilder
|
||||
import org.hibernate.service.Service;
|
||||
import org.hibernate.service.internal.ProvidedService;
|
||||
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator;
|
||||
import org.hibernate.tool.schema.internal.SchemaManagementToolInitiator;
|
||||
|
||||
@@ -182,6 +185,12 @@ public class PreconfiguredServiceRegistryBuilder {
|
||||
|
||||
//Replaces JtaPlatformResolverInitiator.INSTANCE );
|
||||
serviceInitiators.add( new ProteanJtaPlatformResolver( rs.getJtaPlatform() ) );
|
||||
serviceInitiators.add(new JtaPlatformInitiator() {
|
||||
@Override
|
||||
protected JtaPlatform getFallbackProvider(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||
return new JBossStandAloneJtaPlatform();
|
||||
}
|
||||
});
|
||||
//Disabled:
|
||||
//serviceInitiators.add( JtaPlatformInitiator.INSTANCE );
|
||||
|
||||
|
||||
@@ -91,6 +91,20 @@
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
|
||||
@@ -27,7 +27,13 @@ public final class HibernateEntityEnhancer implements Function<String, Function<
|
||||
Objects.requireNonNull(classnameWhitelist);
|
||||
this.classnameWhitelist = classnameWhitelist;
|
||||
BytecodeProvider provider = new org.hibernate.bytecode.internal.bytebuddy.BytecodeProviderImpl();
|
||||
this.enhancer = provider.getEnhancer(new DefaultEnhancementContext());
|
||||
DefaultEnhancementContext enhancementContext = new DefaultEnhancementContext() {
|
||||
@Override
|
||||
public ClassLoader getLoadingClassLoader() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
};
|
||||
this.enhancer = provider.getEnhancer(enhancementContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,20 +35,69 @@ final class HibernateReflectiveNeeds {
|
||||
simpleConstructor(org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl.class);
|
||||
simpleConstructor(org.hibernate.id.enhanced.SequenceStyleGenerator.class);
|
||||
simpleConstructor(org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl.class);
|
||||
simpleConstructor(org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl.class);
|
||||
processorContext.addReflectiveClass(true, false, com.arjuna.ats.jta.UserTransaction.class.getName());
|
||||
processorContext.addReflectiveClass(true, false, com.arjuna.ats.jta.TransactionManager.class.getName());
|
||||
|
||||
//FIXME following is not Hibernate specific?
|
||||
simpleConstructor("com.sun.xml.internal.stream.events.XMLEventFactoryImpl");
|
||||
//ANTLR tokens:
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.HqlToken.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.Node.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.QueryNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SqlNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.FromClause.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.DotNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.IdentNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.FromElement.class);
|
||||
|
||||
|
||||
//ANTLR tokens:
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SelectClause.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.HqlSqlWalkerNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.MethodNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.AbstractStatement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.EntityJoinFromElement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.UnaryLogicOperatorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.NullNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.IntoClause.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.AbstractRestrictableStatement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.UpdateStatement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SelectExpressionImpl.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.CastFunctionNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.MapKeyEntityFromElement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.DeleteStatement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SqlNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SearchedCaseNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.FromElement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.JavaConstantNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SelectExpressionList.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SqlFragment.class);
|
||||
///TODO ... several mode ANTLR tokens will be needed. Above will do for an hello world demo.
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.MapKeyNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.ImpliedFromElement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.IsNotNullLogicOperatorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.InsertStatement.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.UnaryArithmeticNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.CollectionFunction.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.BinaryLogicOperatorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.CountNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.IsNullLogicOperatorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.IdentNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.ComponentJoin.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.ParameterNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.AbstractSelectExpression.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.MapEntryNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.MapValueNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.InLogicOperatorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.IndexNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.AbstractNullnessCheckNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.DotNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.ResultVariableRefNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.BetweenOperatorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.AggregateNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.QueryNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.BooleanLiteralNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.SimpleCaseNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.AbstractMapComponentNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.FromReferenceNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.OrderByClause.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.FromClause.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.ConstructorNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.LiteralNode.class);
|
||||
simpleConstructor(org.hibernate.hql.internal.ast.tree.BinaryArithmeticOperatorNode.class);
|
||||
|
||||
//PostgreSQL specific (move to its own home?) FIXME
|
||||
simpleConstructor(org.hibernate.dialect.PostgreSQL95Dialect.class);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jboss.shamrock.jpa;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -22,6 +23,7 @@ import org.jboss.jandex.IndexView;
|
||||
import org.jboss.shamrock.deployment.ArchiveContext;
|
||||
import org.jboss.shamrock.deployment.ProcessorContext;
|
||||
import org.jboss.shamrock.deployment.codegen.BytecodeRecorder;
|
||||
import org.jboss.shamrock.jpa.runtime.JPADeploymentTemplate;
|
||||
|
||||
/**
|
||||
* Scan the Jandex index to find JPA entities (and embeddables supporting entity models).
|
||||
@@ -144,7 +146,7 @@ final class JpaJandexScavenger {
|
||||
}
|
||||
ClassInfo classInfo = index.getClassByName(className);
|
||||
if (classInfo == null) {
|
||||
if (className == ClassType.OBJECT_TYPE.name()) {
|
||||
if (className == ClassType.OBJECT_TYPE.name() || className.toString().equals(Serializable.class.getName())) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -7,25 +7,39 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
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.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.Persistence;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceUnit;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.TransactionSynchronizationRegistry;
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.jandex.AnnotationTarget;
|
||||
import org.jboss.jandex.AnnotationValue;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.protean.gizmo.ClassCreator;
|
||||
import org.jboss.protean.gizmo.ClassOutput;
|
||||
import org.jboss.protean.gizmo.FieldCreator;
|
||||
import org.jboss.protean.gizmo.FieldDescriptor;
|
||||
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.BeanArchiveIndex;
|
||||
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;
|
||||
|
||||
public class HibernateCdiResourceProcessor implements ResourceProcessor {
|
||||
|
||||
@@ -36,8 +50,12 @@ public class HibernateCdiResourceProcessor implements ResourceProcessor {
|
||||
@Inject
|
||||
private BeanDeployment beanDeployment;
|
||||
|
||||
@Inject
|
||||
BeanArchiveIndex beanArchiveIndex;
|
||||
|
||||
@Override
|
||||
public void process(ArchiveContext archiveContext, ProcessorContext processorContext) throws Exception {
|
||||
|
||||
Set<String> knownUnitNames = new HashSet<>();
|
||||
Set<String> knownContextNames = new HashSet<>();
|
||||
scanForAnnotations(archiveContext, knownUnitNames, PERSISTENCE_UNIT);
|
||||
@@ -45,25 +63,26 @@ public class HibernateCdiResourceProcessor implements ResourceProcessor {
|
||||
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) {
|
||||
|
||||
|
||||
Set<String> allKnownNames = new HashSet<>(knownUnitNames);
|
||||
allKnownNames.addAll(knownContextNames);
|
||||
|
||||
for (String name : allKnownNames) {
|
||||
String className = getClass().getName() + "$$EMFProducer-" + name;
|
||||
AtomicReference<byte[]> 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())) {
|
||||
try (ClassCreator creator = new ClassCreator(new InMemoryClassOutput(bytes, processorContext), className, null, Object.class.getName())) {
|
||||
|
||||
creator.addAnnotation(Dependent.class);
|
||||
MethodCreator producer = creator.getMethodCreator("producerMethod", EntityManagerFactory.class);
|
||||
producer.addAnnotation(Produces.class);
|
||||
producer.addAnnotation(ApplicationScoped.class);
|
||||
if (!knownUnitNames.contains(name)) {
|
||||
//there was no @PersistenceUnit producer with this name
|
||||
//this means that we still need it, but the user would not be expecting a bean to be registered
|
||||
//we register an artificial qualifier that we will use for the managed persistence contexts
|
||||
producer.addAnnotation(SystemEntityManager.class);
|
||||
}
|
||||
|
||||
ResultHandle ret = producer.invokeStaticMethod(MethodDescriptor.ofMethod(Persistence.class, "createEntityManagerFactory", EntityManagerFactory.class, String.class), producer.load(name));
|
||||
producer.returnValue(ret);
|
||||
@@ -72,25 +91,117 @@ public class HibernateCdiResourceProcessor implements ResourceProcessor {
|
||||
}
|
||||
|
||||
|
||||
try(BytecodeRecorder recorder = processorContext.addDeploymentTask(RuntimePriority.BOOTSTRAP_EMF)) {
|
||||
JPADeploymentTemplate template = recorder.getRecordingProxy(JPADeploymentTemplate.class);
|
||||
|
||||
for (String name : knownContextNames) {
|
||||
String className = getClass().getName() + "$$EMProducer-" + name;
|
||||
AtomicReference<byte[]> bytes = new AtomicReference<>();
|
||||
|
||||
//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())) {
|
||||
|
||||
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 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);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
beanDeployment.addGeneratedBean(className, bytes.get());
|
||||
template.boostrapPu(null, system);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void scanForAnnotations(ArchiveContext archiveContext, Set<String> knownUnitNames, DotName nm) {
|
||||
for (AnnotationInstance anno : archiveContext.getCombinedIndex().getAnnotations(nm)) {
|
||||
AnnotationValue unitName = anno.value("unitName");
|
||||
if(unitName == null) {
|
||||
continue;
|
||||
}
|
||||
if (anno.target().kind() == AnnotationTarget.Kind.METHOD) {
|
||||
if (anno.target().asMethod().hasAnnotation(PRODUCES)) {
|
||||
knownUnitNames.add(anno.value("unitName").asString());
|
||||
knownUnitNames.add(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());
|
||||
knownUnitNames.add(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());
|
||||
knownUnitNames.add(unitName.asString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -100,6 +211,26 @@ public class HibernateCdiResourceProcessor implements ResourceProcessor {
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 0;
|
||||
return 100;
|
||||
}
|
||||
|
||||
private static class InMemoryClassOutput implements ClassOutput {
|
||||
private final AtomicReference<byte[]> bytes;
|
||||
private final ProcessorContext processorContext;
|
||||
|
||||
public InMemoryClassOutput(AtomicReference<byte[]> bytes, ProcessorContext processorContext) {
|
||||
this.bytes = bytes;
|
||||
this.processorContext = processorContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(String name, byte[] data) {
|
||||
try {
|
||||
bytes.set(data);
|
||||
processorContext.addGeneratedClass(true, name, data);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.jboss.shamrock.jpa;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.net.URL;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import org.hibernate.hql.internal.ast.tree.Node;
|
||||
import org.jboss.jandex.ClassInfo;
|
||||
import org.jboss.jandex.DotName;
|
||||
import org.jboss.jandex.Index;
|
||||
import org.jboss.jandex.Indexer;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
//not a real test, but you can use to to
|
||||
//get all not implementation that need to be added for reflection
|
||||
@Ignore
|
||||
public class HqlNodeScannerTestCase {
|
||||
|
||||
@Test
|
||||
public void generateAllNodes() throws Exception {
|
||||
URL url = Node.class.getResource("Node.class");
|
||||
String jar = url.getPath().substring(5, url.getPath().lastIndexOf("!"));
|
||||
System.out.println(jar);
|
||||
Indexer indexer = new Indexer();
|
||||
try (ZipInputStream in = new ZipInputStream(new FileInputStream(jar))) {
|
||||
ZipEntry e = in.getNextEntry();
|
||||
while (e != null) {
|
||||
if (e.getName().endsWith(".class")) {
|
||||
indexer.index(in);
|
||||
}
|
||||
e = in.getNextEntry();
|
||||
}
|
||||
}
|
||||
Index index = indexer.complete();
|
||||
for (ClassInfo i : index.getAllKnownSubclasses(DotName.createSimple(Node.class.getName()))) {
|
||||
System.out.println("simpleConstructor(" + i.name() + ".class);");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.jboss.shamrock.jpa;
|
||||
|
||||
import org.hibernate.protean.Hibernate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Emmanuel Bernard emmanuel@hibernate.org
|
||||
*/
|
||||
public class JPADeploymentTemplate {
|
||||
private List<String> entities = new ArrayList<>();
|
||||
|
||||
public void addEntity(String entityClass) {
|
||||
entities.add(entityClass);
|
||||
}
|
||||
|
||||
public void enlistPersistenceUnit() {
|
||||
System.out.println("List of entities found by Shamrock deployment \n" + entities.toString());
|
||||
}
|
||||
|
||||
public void callHibernateFeatureInit() {
|
||||
Hibernate.featureInit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
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
|
||||
*/
|
||||
public class JPADeploymentTemplate {
|
||||
private List<String> entities = new ArrayList<>();
|
||||
|
||||
public void addEntity(String entityClass) {
|
||||
entities.add(entityClass);
|
||||
}
|
||||
|
||||
public void enlistPersistenceUnit() {
|
||||
System.out.println("List of entities found by Shamrock deployment \n" + entities.toString());
|
||||
}
|
||||
|
||||
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,0 +1,11 @@
|
||||
package org.jboss.shamrock.jpa.runtime.cdi;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
@Qualifier
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface SystemEntityManager {
|
||||
}
|
||||
@@ -0,0 +1,460 @@
|
||||
package org.jboss.shamrock.jpa.runtime.cdi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.EntityGraph;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.EntityTransaction;
|
||||
import javax.persistence.FlushModeType;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.StoredProcedureQuery;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaDelete;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.CriteriaUpdate;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.TransactionSynchronizationRegistry;
|
||||
|
||||
public class TransactionScopedEntityManager implements EntityManager {
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
private final TransactionSynchronizationRegistry tsr;
|
||||
private final EntityManagerFactory emf;
|
||||
private static final Object transactionKey = new Object();
|
||||
private EntityManager fallbackEntityManager;
|
||||
|
||||
public TransactionScopedEntityManager(TransactionManager transactionManager, TransactionSynchronizationRegistry tsr, EntityManagerFactory emf) {
|
||||
this.transactionManager = transactionManager;
|
||||
this.tsr = tsr;
|
||||
this.emf = emf;
|
||||
}
|
||||
|
||||
public void requestDone() {
|
||||
if(fallbackEntityManager != null) {
|
||||
fallbackEntityManager.close();
|
||||
}
|
||||
}
|
||||
|
||||
EntityManagerResult getEntityManager() {
|
||||
if (isInTransaction()) {
|
||||
EntityManager em = (EntityManager) tsr.getResource(transactionKey);
|
||||
if (em != null) {
|
||||
return new EntityManagerResult(em, false);
|
||||
}
|
||||
EntityManager newEm = emf.createEntityManager();
|
||||
tsr.putResource(transactionKey, newEm);
|
||||
tsr.registerInterposedSynchronization(new Synchronization() {
|
||||
@Override
|
||||
public void beforeCompletion() {
|
||||
newEm.flush();
|
||||
newEm.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(int i) {
|
||||
|
||||
}
|
||||
});
|
||||
return new EntityManagerResult(newEm, false);
|
||||
} else {
|
||||
if(fallbackEntityManager == null) {
|
||||
fallbackEntityManager = emf.createEntityManager();
|
||||
}
|
||||
return new EntityManagerResult(emf.createEntityManager(), false);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInTransaction() {
|
||||
try {
|
||||
switch (transactionManager.getStatus()) {
|
||||
case Status.STATUS_ACTIVE:
|
||||
case Status.STATUS_COMMITTING:
|
||||
case Status.STATUS_MARKED_ROLLBACK:
|
||||
case Status.STATUS_PREPARED:
|
||||
case Status.STATUS_PREPARING:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persist(Object entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.persist(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T merge(T entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.merge(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Object entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> entityClass, Object primaryKey) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.find(entityClass, primaryKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.find(entityClass, primaryKey, properties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.find(entityClass, primaryKey, lockMode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> entityClass, Object primaryKey, LockModeType lockMode, Map<String, Object> properties) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.find(entityClass, primaryKey, lockMode, properties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getReference(Class<T> entityClass, Object primaryKey) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getReference(entityClass, primaryKey);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushMode(FlushModeType flushMode) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.setFlushMode(flushMode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FlushModeType getFlushMode() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getFlushMode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock(Object entity, LockModeType lockMode) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.lock(entity, lockMode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lock(Object entity, LockModeType lockMode, Map<String, Object> properties) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.lock(entity, lockMode, properties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(Object entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.refresh(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(Object entity, Map<String, Object> properties) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.refresh(entity, properties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(Object entity, LockModeType lockMode) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.refresh(entity, lockMode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(Object entity, LockModeType lockMode, Map<String, Object> properties) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.refresh(entity, lockMode, properties);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach(Object entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.detach(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.contains(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockModeType getLockMode(Object entity) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getLockMode(entity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String propertyName, Object value) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.setProperty(propertyName, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getProperties() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getProperties();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createQuery(String qlString) {
|
||||
//TODO: this needs some thought for how it works outside a tx
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createQuery(qlString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createQuery(criteriaQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createQuery(CriteriaUpdate updateQuery) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createQuery(updateQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createQuery(CriteriaDelete deleteQuery) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createQuery(deleteQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createQuery(qlString, resultClass);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createNamedQuery(String name) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createNamedQuery(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createNamedQuery(name, resultClass);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createNativeQuery(String sqlString) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createNativeQuery(sqlString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createNativeQuery(String sqlString, Class resultClass) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createNativeQuery(sqlString, resultClass);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query createNativeQuery(String sqlString, String resultSetMapping) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createNativeQuery(sqlString, resultSetMapping);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createNamedStoredProcedureQuery(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createStoredProcedureQuery(procedureName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createStoredProcedureQuery(procedureName, resultClasses);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createStoredProcedureQuery(procedureName, resultSetMappings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinTransaction() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
emr.em.joinTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJoinedToTransaction() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.isJoinedToTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> cls) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.unwrap(cls);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getDelegate() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getDelegate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
throw new IllegalStateException("Not supported for transaction scoped entity managers");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOpen() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityTransaction getTransaction() {
|
||||
throw new IllegalStateException("Not supported for JTA entity managers");
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityManagerFactory getEntityManagerFactory() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getEntityManagerFactory();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CriteriaBuilder getCriteriaBuilder() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getCriteriaBuilder();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metamodel getMetamodel() {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getMetamodel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> EntityGraph<T> createEntityGraph(Class<T> rootType) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createEntityGraph(rootType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGraph<?> createEntityGraph(String graphName) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.createEntityGraph(graphName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityGraph<?> getEntityGraph(String graphName) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getEntityGraph(graphName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
|
||||
try (EntityManagerResult emr = getEntityManager()) {
|
||||
return emr.em.getEntityGraphs(entityClass);
|
||||
}
|
||||
}
|
||||
|
||||
static class EntityManagerResult implements AutoCloseable {
|
||||
|
||||
private final EntityManager em;
|
||||
private final boolean closeOnEnd;
|
||||
|
||||
EntityManagerResult(EntityManager em, boolean closeOnEnd) {
|
||||
this.em = em;
|
||||
this.closeOnEnd = closeOnEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (closeOnEnd) {
|
||||
em.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ public class ShamrockTest extends BlockJUnit4ClassRunner {
|
||||
|
||||
private static boolean first = true;
|
||||
private static boolean started = false;
|
||||
private static boolean failed = false;
|
||||
|
||||
/**
|
||||
* Creates a BlockJUnit4ClassRunner to run {@code klass}
|
||||
@@ -42,19 +43,29 @@ public class ShamrockTest extends BlockJUnit4ClassRunner {
|
||||
try {
|
||||
notifier.addListener(new RunListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void testStarted(Description description) {
|
||||
if (failed) {
|
||||
notifier.fireTestFailure(new Failure(description, new AssertionError("Startup failed")));
|
||||
return;
|
||||
}
|
||||
if (!started) {
|
||||
started = true;
|
||||
//TODO: so much hacks...
|
||||
Class<?> theClass = description.getTestClass();
|
||||
String classFileName = theClass.getName().replace(".", "/") + ".class";
|
||||
URL resource = theClass.getClassLoader().getResource(classFileName);
|
||||
String testClassLocation = resource.getPath().substring(0, resource.getPath().length() - classFileName.length());
|
||||
String appClassLocation = testClassLocation.replace("test-classes", "classes");
|
||||
Path appRoot = Paths.get(appClassLocation);
|
||||
RuntimeRunner runtimeRunner = new RuntimeRunner(getClass().getClassLoader(), appRoot, Paths.get(testClassLocation), new ArchiveContextBuilder());
|
||||
runtimeRunner.run();
|
||||
try {
|
||||
Class<?> theClass = description.getTestClass();
|
||||
String classFileName = theClass.getName().replace(".", "/") + ".class";
|
||||
URL resource = theClass.getClassLoader().getResource(classFileName);
|
||||
String testClassLocation = resource.getPath().substring(0, resource.getPath().length() - classFileName.length());
|
||||
String appClassLocation = testClassLocation.replace("test-classes", "classes");
|
||||
Path appRoot = Paths.get(appClassLocation);
|
||||
RuntimeRunner runtimeRunner = new RuntimeRunner(getClass().getClassLoader(), appRoot, Paths.get(testClassLocation), new ArchiveContextBuilder());
|
||||
runtimeRunner.run();
|
||||
} catch (RuntimeException e) {
|
||||
failed = true;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.jboss.shamrock.deployment.ShamrockSetup;
|
||||
public class TransactionsSetup implements ShamrockSetup {
|
||||
@Override
|
||||
public void setup(SetupContext context) {
|
||||
context.addCapability("transactions");
|
||||
context.addResourceProcessor(new TransactionsProcessor());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user