Skip to content

Commit

Permalink
Refactor the HibernateOrmProcessor to decompose the build steps into …
Browse files Browse the repository at this point in the history
…smaller items

This is necessary to avoid cycles in upcoming fixes
  • Loading branch information
Sanne committed May 15, 2020
1 parent 49de311 commit f8a4415
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -164,32 +164,58 @@ List<HotDeploymentWatchedFileBuildItem> hotDeploymentWatchedFiles(LaunchModeBuil
return watchedFiles;
}

@SuppressWarnings("unchecked")
@BuildStep
@Record(STATIC_INIT)
public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder,
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
List<NonJpaModelBuildItem> nonJpaModelBuildItems,
List<IgnorableNonIndexedClasses> ignorableNonIndexedClassesBuildItems,
CombinedIndexBuildItem index,
ArchiveRootBuildItem archiveRoot,
ApplicationArchivesBuildItem applicationArchivesBuildItem,
public void parsePersistenceXmlDescriptors(
BuildProducer<PersistenceXmlDescriptorBuildItem> persistenceXmlDescriptorBuildItemBuildProducer) {
List<ParsedPersistenceXmlDescriptor> explicitDescriptors = QuarkusPersistenceXmlParser.locatePersistenceUnits();
for (ParsedPersistenceXmlDescriptor desc : explicitDescriptors) {
persistenceXmlDescriptorBuildItemBuildProducer.produce(new PersistenceXmlDescriptorBuildItem(desc));
}
}

@BuildStep
public void configurationDescriptorBuilding(
List<JdbcDataSourceBuildItem> jdbcDataSourcesBuildItem,
BuildProducer<FeatureBuildItem> feature,
BuildProducer<PersistenceUnitDescriptorBuildItem> persistenceUnitDescriptorProducer,
List<PersistenceXmlDescriptorBuildItem> persistenceXmlDescriptors,
BuildProducer<NativeImageResourceBuildItem> resourceProducer,
ArchiveRootBuildItem archiveRoot,
ApplicationArchivesBuildItem applicationArchivesBuildItem,
LaunchModeBuildItem launchMode,
JpaEntitiesBuildItem domainObjects,
List<NonJpaModelBuildItem> nonJpaModelBuildItems,
BuildProducer<SystemPropertyBuildItem> systemPropertyProducer,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
BuildProducer<JpaEntitiesBuildItem> domainObjectsProducer,
BuildProducer<BeanContainerListenerBuildItem> beanContainerListener,
BuildProducer<GeneratedClassBuildItem> generatedClassBuildItemBuildProducer,
List<HibernateOrmIntegrationBuildItem> integrations,
LaunchModeBuildItem launchMode) throws Exception {
BuildProducer<PersistenceUnitDescriptorBuildItem> persistenceUnitDescriptorProducer) {

feature.produce(new FeatureBuildItem(FeatureBuildItem.HIBERNATE_ORM));
final boolean enableORM = hasEntities(domainObjects, nonJpaModelBuildItems);

List<ParsedPersistenceXmlDescriptor> 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<JdbcDataSourceBuildItem> defaultJdbcDataSourceBuildItem = jdbcDataSourcesBuildItem.stream()
.filter(i -> i.isDefault())
.findFirst();

// handle the implicit persistence unit
List<ParsedPersistenceXmlDescriptor> 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<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
BuildProducer<JpaModelIndexBuildItem> producer) {
// build a composite index with additional jpa model classes
Indexer indexer = new Indexer();
Set<DotName> additionalIndex = new HashSet<>();
Expand All @@ -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<JpaEntitiesBuildItem> domainObjectsProducer,
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
List<IgnorableNonIndexedClasses> ignorableNonIndexedClassesBuildItems,
List<NonJpaModelBuildItem> nonJpaModelBuildItems,
BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
List<PersistenceXmlDescriptorBuildItem> persistenceXmlDescriptors) throws Exception {

Set<String> nonJpaModelClasses = nonJpaModelBuildItems.stream()
.map(NonJpaModelBuildItem::getClassName)
Expand All @@ -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<PersistenceUnitDescriptorBuildItem> persistenceUnitDescriptorBuildItems,
BuildProducer<GeneratedClassBuildItem> generatedClassBuildItemBuildProducer,
BuildProducer<ProxyDefinitionsBuildItem> producer) {

Set<String> entitiesToGenerateProxiesFor = new HashSet<>(domainObjects.getEntityClassNames());

List<ParsedPersistenceXmlDescriptor> 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<NonJpaModelBuildItem> nonJpaModelBuildItems,
List<PersistenceUnitDescriptorBuildItem> persistenceUnitDescriptorBuildItems,
List<HibernateOrmIntegrationBuildItem> integrations,
ProxyDefinitionsBuildItem proxyDefinitions,
BuildProducer<FeatureBuildItem> feature,
BuildProducer<BeanContainerListenerBuildItem> beanContainerListener) throws Exception {

feature.produce(new FeatureBuildItem(FeatureBuildItem.HIBERNATE_ORM));

final boolean enableORM = hasEntities(domainObjects, nonJpaModelBuildItems);
recorder.callHibernateFeatureInit(enableORM);
Expand All @@ -226,21 +304,6 @@ public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder
return;
}

// we only support the default datasource for now
Optional<JdbcDataSourceBuildItem> defaultJdbcDataSourceBuildItem = jdbcDataSourcesBuildItem.stream()
.filter(i -> i.isDefault())
.findFirst();

// handle the implicit persistence unit
List<ParsedPersistenceXmlDescriptor> 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);
}
Expand Down Expand Up @@ -275,16 +338,15 @@ public void build(RecorderContext recorderContext, HibernateOrmRecorder recorder
.add((Class<? extends ServiceContributor>) recorderContext.classProxy(serviceContributorClassName));
}

Set<String> entitiesToGenerateProxiesFor = new HashSet<>(domainObjects.getEntityClassNames());
for (ParsedPersistenceXmlDescriptor unit : allDescriptors) {
entitiesToGenerateProxiesFor.addAll(unit.getManagedClassNames());
List<ParsedPersistenceXmlDescriptor> 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<String> entityClassNames, IndexView combinedIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -51,14 +49,14 @@ final class JpaJandexScavenger {

private static final DotName ENUM = DotName.createSimple(Enum.class.getName());

private final List<ParsedPersistenceXmlDescriptor> explicitDescriptors;
private final List<PersistenceXmlDescriptorBuildItem> explicitDescriptors;
private final BuildProducer<ReflectiveClassBuildItem> reflectiveClass;
private final IndexView indexView;
private final Set<String> nonJpaModelClasses;
private final Set<String> ignorableNonIndexedClasses;

JpaJandexScavenger(BuildProducer<ReflectiveClassBuildItem> reflectiveClass,
List<ParsedPersistenceXmlDescriptor> explicitDescriptors,
List<PersistenceXmlDescriptorBuildItem> explicitDescriptors,
IndexView indexView,
Set<String> nonJpaModelClasses,
Set<String> ignorableNonIndexedClasses) {
Expand Down Expand Up @@ -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<String> managedClassNames = pud.getDescriptor().getManagedClassNames();
enlistExplicitClasses(indexView, domainObjectCollector, enumTypeCollector, javaTypeCollector,
pud.getManagedClassNames(),
unindexedClasses);
managedClassNames, unindexedClasses);
}

domainObjectCollector.registerAllForReflection(reflectiveClass);
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*/
public final class JpaModelIndexBuildItem extends SimpleBuildItem {

private final CompositeIndex index;

public JpaModelIndexBuildItem(CompositeIndex index) {
this.index = index;
}

public CompositeIndex getIndex() {
return index;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*/
public final class PersistenceXmlDescriptorBuildItem extends MultiBuildItem {

private final ParsedPersistenceXmlDescriptor descriptor;

public PersistenceXmlDescriptorBuildItem(ParsedPersistenceXmlDescriptor descriptor) {
this.descriptor = descriptor;
}

protected ParsedPersistenceXmlDescriptor getDescriptor() {
return descriptor;
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}

0 comments on commit f8a4415

Please sign in to comment.