diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java index 69eada880790b..9273f86779d8a 100644 --- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java @@ -164,32 +164,58 @@ List hotDeploymentWatchedFiles(LaunchModeBuil return watchedFiles; } - @SuppressWarnings("unchecked") @BuildStep - @Record(STATIC_INIT) - public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder, - List additionalJpaModelBuildItems, - List nonJpaModelBuildItems, - List ignorableNonIndexedClassesBuildItems, - CombinedIndexBuildItem index, - ArchiveRootBuildItem archiveRoot, - ApplicationArchivesBuildItem applicationArchivesBuildItem, + public void parsePersistenceXmlDescriptors( + BuildProducer persistenceXmlDescriptorBuildItemBuildProducer) { + List explicitDescriptors = QuarkusPersistenceXmlParser.locatePersistenceUnits(); + for (ParsedPersistenceXmlDescriptor desc : explicitDescriptors) { + persistenceXmlDescriptorBuildItemBuildProducer.produce(new PersistenceXmlDescriptorBuildItem(desc)); + } + } + + @BuildStep + public void configurationDescriptorBuilding( List jdbcDataSourcesBuildItem, - BuildProducer feature, - BuildProducer persistenceUnitDescriptorProducer, + List persistenceXmlDescriptors, BuildProducer resourceProducer, + ArchiveRootBuildItem archiveRoot, + ApplicationArchivesBuildItem applicationArchivesBuildItem, + LaunchModeBuildItem launchMode, + JpaEntitiesBuildItem domainObjects, + List nonJpaModelBuildItems, BuildProducer systemPropertyProducer, - BuildProducer reflectiveClass, - BuildProducer domainObjectsProducer, - BuildProducer beanContainerListener, - BuildProducer generatedClassBuildItemBuildProducer, - List integrations, - LaunchModeBuildItem launchMode) throws Exception { + BuildProducer persistenceUnitDescriptorProducer) { - feature.produce(new FeatureBuildItem(FeatureBuildItem.HIBERNATE_ORM)); + final boolean enableORM = hasEntities(domainObjects, nonJpaModelBuildItems); - List explicitDescriptors = QuarkusPersistenceXmlParser.locatePersistenceUnits(); + if (!enableORM) { + // we have to bail out early as we might not have a datasource configuration + return; + } + + // we only support the default datasource for now + Optional defaultJdbcDataSourceBuildItem = jdbcDataSourcesBuildItem.stream() + .filter(i -> i.isDefault()) + .findFirst(); + + // handle the implicit persistence unit + List allDescriptors = new ArrayList<>(persistenceXmlDescriptors.size() + 1); + for (PersistenceXmlDescriptorBuildItem persistenceXmlDescriptorBuildItem : persistenceXmlDescriptors) { + allDescriptors.add(persistenceXmlDescriptorBuildItem.getDescriptor()); + } + handleHibernateORMWithNoPersistenceXml(allDescriptors, resourceProducer, systemPropertyProducer, archiveRoot, + defaultJdbcDataSourceBuildItem, applicationArchivesBuildItem, launchMode.getLaunchMode()); + + for (ParsedPersistenceXmlDescriptor descriptor : allDescriptors) { + persistenceUnitDescriptorProducer.produce(new PersistenceUnitDescriptorBuildItem(descriptor)); + } + } + @BuildStep + public void jpaEntitiesIndexer( + CombinedIndexBuildItem index, + List additionalJpaModelBuildItems, + BuildProducer producer) { // build a composite index with additional jpa model classes Indexer indexer = new Indexer(); Set additionalIndex = new HashSet<>(); @@ -198,6 +224,18 @@ public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder HibernateOrmProcessor.class.getClassLoader()); } CompositeIndex compositeIndex = CompositeIndex.create(index.getIndex(), indexer.complete()); + producer.produce(new JpaModelIndexBuildItem(compositeIndex)); + } + + @BuildStep + public void defineJpaEntities( + JpaModelIndexBuildItem indexBuildItem, + BuildProducer domainObjectsProducer, + List additionalJpaModelBuildItems, + List ignorableNonIndexedClassesBuildItems, + List nonJpaModelBuildItems, + BuildProducer reflectiveClass, + List persistenceXmlDescriptors) throws Exception { Set nonJpaModelClasses = nonJpaModelBuildItems.stream() .map(NonJpaModelBuildItem::getClassName) @@ -211,12 +249,52 @@ public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder } } - JpaJandexScavenger scavenger = new JpaJandexScavenger(reflectiveClass, explicitDescriptors, compositeIndex, + JpaJandexScavenger scavenger = new JpaJandexScavenger(reflectiveClass, persistenceXmlDescriptors, + indexBuildItem.getIndex(), nonJpaModelClasses, ignorableNonIndexedClasses); final JpaEntitiesBuildItem domainObjects = scavenger.discoverModelAndRegisterForReflection(); // remember how to run the enhancers later domainObjectsProducer.produce(domainObjects); + } + + @BuildStep + public void pregenProxies( + JpaEntitiesBuildItem domainObjects, + JpaModelIndexBuildItem indexBuildItem, + List persistenceUnitDescriptorBuildItems, + BuildProducer generatedClassBuildItemBuildProducer, + BuildProducer producer) { + + Set entitiesToGenerateProxiesFor = new HashSet<>(domainObjects.getEntityClassNames()); + + List allDescriptors = new ArrayList<>(); + for (PersistenceUnitDescriptorBuildItem pud : persistenceUnitDescriptorBuildItems) { + allDescriptors.add(pud.getDescriptor()); + } + + for (ParsedPersistenceXmlDescriptor unit : allDescriptors) { + entitiesToGenerateProxiesFor.addAll(unit.getManagedClassNames()); + } + + PreGeneratedProxies proxyDefinitions = generatedProxies(entitiesToGenerateProxiesFor, indexBuildItem.getIndex(), + generatedClassBuildItemBuildProducer); + producer.produce(new ProxyDefinitionsBuildItem(proxyDefinitions)); + } + + @SuppressWarnings("unchecked") + @BuildStep + @Record(STATIC_INIT) + public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder, + JpaEntitiesBuildItem domainObjects, + List nonJpaModelBuildItems, + List persistenceUnitDescriptorBuildItems, + List integrations, + ProxyDefinitionsBuildItem proxyDefinitions, + BuildProducer feature, + BuildProducer beanContainerListener) throws Exception { + + feature.produce(new FeatureBuildItem(FeatureBuildItem.HIBERNATE_ORM)); final boolean enableORM = hasEntities(domainObjects, nonJpaModelBuildItems); recorder.callHibernateFeatureInit(enableORM); @@ -226,21 +304,6 @@ public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder return; } - // we only support the default datasource for now - Optional defaultJdbcDataSourceBuildItem = jdbcDataSourcesBuildItem.stream() - .filter(i -> i.isDefault()) - .findFirst(); - - // handle the implicit persistence unit - List allDescriptors = new ArrayList<>(explicitDescriptors.size() + 1); - allDescriptors.addAll(explicitDescriptors); - handleHibernateORMWithNoPersistenceXml(allDescriptors, resourceProducer, systemPropertyProducer, archiveRoot, - defaultJdbcDataSourceBuildItem, applicationArchivesBuildItem, launchMode.getLaunchMode()); - - for (ParsedPersistenceXmlDescriptor descriptor : allDescriptors) { - persistenceUnitDescriptorProducer.produce(new PersistenceUnitDescriptorBuildItem(descriptor)); - } - for (String className : domainObjects.getEntityClassNames()) { recorder.addEntity(className); } @@ -275,16 +338,15 @@ public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder .add((Class) recorderContext.classProxy(serviceContributorClassName)); } - Set entitiesToGenerateProxiesFor = new HashSet<>(domainObjects.getEntityClassNames()); - for (ParsedPersistenceXmlDescriptor unit : allDescriptors) { - entitiesToGenerateProxiesFor.addAll(unit.getManagedClassNames()); + List allDescriptors = new ArrayList<>(); + for (PersistenceUnitDescriptorBuildItem pud : persistenceUnitDescriptorBuildItems) { + allDescriptors.add(pud.getDescriptor()); } - PreGeneratedProxies proxyDefinitions = generatedProxies(entitiesToGenerateProxiesFor, compositeIndex, - generatedClassBuildItemBuildProducer); + beanContainerListener .produce(new BeanContainerListenerBuildItem( recorder.initMetadata(allDescriptors, scanner, integratorClasses, serviceContributorClasses, - proxyDefinitions))); + proxyDefinitions.getProxies()))); } private PreGeneratedProxies generatedProxies(Set entityClassNames, IndexView combinedIndex, diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaJandexScavenger.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaJandexScavenger.java index 69ea6152bd59c..98c4b55ea3178 100644 --- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaJandexScavenger.java +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaJandexScavenger.java @@ -15,8 +15,6 @@ import javax.persistence.Entity; import javax.persistence.MappedSuperclass; -import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; -import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.ClassInfo; @@ -51,14 +49,14 @@ final class JpaJandexScavenger { private static final DotName ENUM = DotName.createSimple(Enum.class.getName()); - private final List explicitDescriptors; + private final List explicitDescriptors; private final BuildProducer reflectiveClass; private final IndexView indexView; private final Set nonJpaModelClasses; private final Set ignorableNonIndexedClasses; JpaJandexScavenger(BuildProducer reflectiveClass, - List explicitDescriptors, + List explicitDescriptors, IndexView indexView, Set nonJpaModelClasses, Set ignorableNonIndexedClasses) { @@ -86,10 +84,10 @@ public JpaEntitiesBuildItem discoverModelAndRegisterForReflection() throws IOExc enlistEmbeddedsAndElementCollections(indexView, domainObjectCollector, enumTypeCollector, javaTypeCollector, unindexedClasses); - for (PersistenceUnitDescriptor pud : explicitDescriptors) { + for (PersistenceXmlDescriptorBuildItem pud : explicitDescriptors) { + final List managedClassNames = pud.getDescriptor().getManagedClassNames(); enlistExplicitClasses(indexView, domainObjectCollector, enumTypeCollector, javaTypeCollector, - pud.getManagedClassNames(), - unindexedClasses); + managedClassNames, unindexedClasses); } domainObjectCollector.registerAllForReflection(reflectiveClass); diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaModelIndexBuildItem.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaModelIndexBuildItem.java new file mode 100644 index 0000000000000..fce4af7a52c5f --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/JpaModelIndexBuildItem.java @@ -0,0 +1,24 @@ +package io.quarkus.hibernate.orm.deployment; + +import org.jboss.jandex.CompositeIndex; + +import io.quarkus.builder.item.SimpleBuildItem; + +/** + * Provides the Jandex index of the application, combined with the index + * of additional JPA components that might have been generated. + * + * @author Sanne Grinovero + */ +public final class JpaModelIndexBuildItem extends SimpleBuildItem { + + private final CompositeIndex index; + + public JpaModelIndexBuildItem(CompositeIndex index) { + this.index = index; + } + + public CompositeIndex getIndex() { + return index; + } +} diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceUnitDescriptorBuildItem.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceUnitDescriptorBuildItem.java index fdb6fa4939f32..a46ddd6de5a83 100644 --- a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceUnitDescriptorBuildItem.java +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceUnitDescriptorBuildItem.java @@ -4,6 +4,12 @@ import io.quarkus.builder.item.MultiBuildItem; +/** + * Not to be confused with PersistenceXmlDescriptorBuildItem, which holds + * items of the same type. + * This build item represents a later phase, and might include the implicit + * configuration definitions that are automatically defined by Quarkus. + */ public final class PersistenceUnitDescriptorBuildItem extends MultiBuildItem { private final ParsedPersistenceXmlDescriptor descriptor; diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceXmlDescriptorBuildItem.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceXmlDescriptorBuildItem.java new file mode 100644 index 0000000000000..178f0e52bf6d0 --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/PersistenceXmlDescriptorBuildItem.java @@ -0,0 +1,26 @@ +package io.quarkus.hibernate.orm.deployment; + +import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor; + +import io.quarkus.builder.item.MultiBuildItem; + +/** + * Provides instances of {@see ParsedPersistenceXmlDescriptor}, the raw representation + * of a persistence.xml file as it is after being located and parsed. + * Exposed as a possible integration API: other extensions can produce additional + * configuration instances. + * + * @author Sanne Grinovero + */ +public final class PersistenceXmlDescriptorBuildItem extends MultiBuildItem { + + private final ParsedPersistenceXmlDescriptor descriptor; + + public PersistenceXmlDescriptorBuildItem(ParsedPersistenceXmlDescriptor descriptor) { + this.descriptor = descriptor; + } + + protected ParsedPersistenceXmlDescriptor getDescriptor() { + return descriptor; + } +} diff --git a/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/ProxyDefinitionsBuildItem.java b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/ProxyDefinitionsBuildItem.java new file mode 100644 index 0000000000000..44774754cd2f9 --- /dev/null +++ b/extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/ProxyDefinitionsBuildItem.java @@ -0,0 +1,28 @@ +package io.quarkus.hibernate.orm.deployment; + +import java.util.Objects; + +import io.quarkus.builder.item.SimpleBuildItem; +import io.quarkus.hibernate.orm.runtime.proxies.PreGeneratedProxies; + +/** + * Contains the reference to the class definitions of the proxies + * that Hibernate ORM might require at runtime. + * In Quarkus such proxies are built upfront, during the build. + * This needs to be a separate build item from other components so + * to avoid cycles in the rather complex build graph required by + * this extension. + */ +public final class ProxyDefinitionsBuildItem extends SimpleBuildItem { + + private final PreGeneratedProxies proxies; + + public ProxyDefinitionsBuildItem(PreGeneratedProxies proxies) { + Objects.requireNonNull(proxies); + this.proxies = proxies; + } + + public PreGeneratedProxies getProxies() { + return proxies; + } +}