Skip to content

Commit 629b9c3

Browse files
committed
Assign additional classes (e.g. PanacheEntity) explicitly
# Conflicts: # extensions/hibernate-reactive/deployment/src/main/java/io/quarkus/hibernate/reactive/deployment/HibernateReactiveProcessor.java
1 parent daec80b commit 629b9c3

File tree

11 files changed

+150
-20
lines changed

11 files changed

+150
-20
lines changed

extensions/hibernate-envers/deployment/src/main/java/io/quarkus/hibernate/envers/deployment/HibernateEnversProcessor.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.ArrayList;
44
import java.util.Arrays;
55
import java.util.List;
6+
import java.util.Set;
67

78
import io.quarkus.deployment.annotations.BuildProducer;
89
import io.quarkus.deployment.annotations.BuildStep;
@@ -28,10 +29,18 @@ public final class HibernateEnversProcessor {
2829
@BuildStep
2930
List<AdditionalJpaModelBuildItem> addJpaModelClasses() {
3031
return Arrays.asList(
31-
new AdditionalJpaModelBuildItem("org.hibernate.envers.DefaultRevisionEntity"),
32-
new AdditionalJpaModelBuildItem("org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity"),
33-
new AdditionalJpaModelBuildItem("org.hibernate.envers.RevisionMapping"),
34-
new AdditionalJpaModelBuildItem("org.hibernate.envers.TrackingModifiedEntitiesRevisionMapping"));
32+
new AdditionalJpaModelBuildItem("org.hibernate.envers.DefaultRevisionEntity",
33+
// Added to specific PUs at static init using org.hibernate.boot.spi.AdditionalMappingContributor
34+
Set.of()),
35+
new AdditionalJpaModelBuildItem("org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity",
36+
// Added to specific PUs at static init using org.hibernate.boot.spi.AdditionalMappingContributor
37+
Set.of()),
38+
new AdditionalJpaModelBuildItem("org.hibernate.envers.RevisionMapping",
39+
// Added to specific PUs at static init using org.hibernate.boot.spi.AdditionalMappingContributor
40+
Set.of()),
41+
new AdditionalJpaModelBuildItem("org.hibernate.envers.TrackingModifiedEntitiesRevisionMapping",
42+
// Added to specific PUs at static init using org.hibernate.boot.spi.AdditionalMappingContributor
43+
Set.of()));
3544
}
3645

3746
@BuildStep

extensions/hibernate-orm/deployment-spi/src/main/java/io/quarkus/hibernate/orm/deployment/spi/AdditionalJpaModelBuildItem.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.quarkus.hibernate.orm.deployment.spi;
22

33
import java.util.Objects;
4+
import java.util.Set;
45

56
import io.quarkus.builder.item.MultiBuildItem;
67

@@ -12,13 +13,38 @@
1213
public final class AdditionalJpaModelBuildItem extends MultiBuildItem {
1314

1415
private final String className;
16+
private final Set<String> persistenceUnits;
1517

18+
/**
19+
* @deprecated Use {@link AdditionalJpaModelBuildItem#AdditionalJpaModelBuildItem(String, Set)} instead,
20+
* which should fit the use case of JBeret better.
21+
*/
22+
@Deprecated(since = "3.26", forRemoval = true)
1623
public AdditionalJpaModelBuildItem(String className) {
1724
Objects.requireNonNull(className);
1825
this.className = className;
26+
this.persistenceUnits = null;
27+
}
28+
29+
/**
30+
* @param className The name of the additional class.
31+
* @param persistenceUnits The name of persistence units to which this class should be added
32+
* even if the application does not request it explicitly (e.g. using `quarkus.hibernate-orm.packages`).
33+
* Note the class can still be added to a persistence unit at static init through other means --
34+
* for example Hibernate Envers and Hibernate Search use {@link org.hibernate.boot.spi.AdditionalMappingContributor}.
35+
*/
36+
public AdditionalJpaModelBuildItem(String className, Set<String> persistenceUnits) {
37+
Objects.requireNonNull(className);
38+
Objects.requireNonNull(persistenceUnits);
39+
this.className = className;
40+
this.persistenceUnits = persistenceUnits;
1941
}
2042

2143
public String getClassName() {
2244
return className;
2345
}
46+
47+
public Set<String> getPersistenceUnits() {
48+
return persistenceUnits;
49+
}
2450
}

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmProcessor.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ public void configurationDescriptorBuilding(
327327
List<JdbcDataSourceBuildItem> jdbcDataSources,
328328
ApplicationArchivesBuildItem applicationArchivesBuildItem,
329329
LaunchModeBuildItem launchMode,
330+
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
330331
JpaModelBuildItem jpaModel,
331332
Capabilities capabilities,
332333
BuildProducer<SystemPropertyBuildItem> systemProperties,
@@ -383,7 +384,8 @@ public void configurationDescriptorBuilding(
383384

384385
if (impliedPU.shouldGenerateImpliedBlockingPersistenceUnit()) {
385386
handleHibernateORMWithNoPersistenceXml(hibernateOrmConfig, index, persistenceXmlDescriptors,
386-
jdbcDataSources, applicationArchivesBuildItem, launchMode.getLaunchMode(), jpaModel, capabilities,
387+
jdbcDataSources, applicationArchivesBuildItem, launchMode.getLaunchMode(), additionalJpaModelBuildItems,
388+
jpaModel, capabilities,
387389
systemProperties, nativeImageResources, hotDeploymentWatchedFiles, persistenceUnitDescriptors,
388390
reflectiveMethods, unremovableBeans, dbKindMetadataBuildItems);
389391
}
@@ -843,6 +845,7 @@ private void handleHibernateORMWithNoPersistenceXml(
843845
List<JdbcDataSourceBuildItem> jdbcDataSources,
844846
ApplicationArchivesBuildItem applicationArchivesBuildItem,
845847
LaunchMode launchMode,
848+
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
846849
JpaModelBuildItem jpaModel,
847850
Capabilities capabilities,
848851
BuildProducer<SystemPropertyBuildItem> systemProperties,
@@ -891,7 +894,7 @@ private void handleHibernateORMWithNoPersistenceXml(
891894
|| hibernateOrmConfig.defaultPersistenceUnit().isAnyPropertySet();
892895

893896
Map<String, Set<String>> modelClassesAndPackagesPerPersistencesUnits = getModelClassesAndPackagesPerPersistenceUnits(
894-
hibernateOrmConfig, jpaModel, index.getIndex(), enableDefaultPersistenceUnit);
897+
hibernateOrmConfig, additionalJpaModelBuildItems, jpaModel, index.getIndex(), enableDefaultPersistenceUnit);
895898
Set<String> modelClassesAndPackagesForDefaultPersistenceUnit = modelClassesAndPackagesPerPersistencesUnits
896899
.getOrDefault(PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME, Collections.emptySet());
897900

@@ -1135,7 +1138,8 @@ private void enhanceEntities(final JpaModelBuildItem jpaModel,
11351138
}
11361139

11371140
public static Map<String, Set<String>> getModelClassesAndPackagesPerPersistenceUnits(HibernateOrmConfig hibernateOrmConfig,
1138-
JpaModelBuildItem jpaModel, IndexView index, boolean enableDefaultPersistenceUnit) {
1141+
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems, JpaModelBuildItem jpaModel,
1142+
IndexView index, boolean enableDefaultPersistenceUnit) {
11391143
Map<String, Set<String>> modelClassesAndPackagesPerPersistenceUnits = new HashMap<>();
11401144

11411145
boolean hasPackagesInQuarkusConfig = hasPackagesInQuarkusConfig(hibernateOrmConfig);
@@ -1234,14 +1238,28 @@ public static Map<String, Set<String>> getModelClassesAndPackagesPerPersistenceU
12341238
}
12351239
}
12361240

1241+
Set<String> affectedModelClasses = new HashSet<>();
1242+
for (AdditionalJpaModelBuildItem additionalJpaModel : additionalJpaModelBuildItems) {
1243+
var className = additionalJpaModel.getClassName();
1244+
var persistenceUnits = additionalJpaModel.getPersistenceUnits();
1245+
if (persistenceUnits == null) {
1246+
// Legacy behavior -- remove when the deprecated one-argument constructor of AdditionalJpaModelBuildItem gets removed.
1247+
continue;
1248+
}
1249+
affectedModelClasses.add(className); // Even if persistenceUnits is empty, the class is still affected (to nothing)
1250+
for (String persistenceUnitName : persistenceUnits) {
1251+
modelClassesAndPackagesPerPersistenceUnits.putIfAbsent(persistenceUnitName, new HashSet<>());
1252+
modelClassesAndPackagesPerPersistenceUnits.get(persistenceUnitName).add(className);
1253+
}
1254+
}
1255+
12371256
if (!modelClassesWithPersistenceUnitAnnotations.isEmpty()) {
12381257
throw new IllegalStateException(String.format(Locale.ROOT,
12391258
"@PersistenceUnit annotations are not supported at the class level on model classes:\n\t- %s\nUse the `.packages` configuration property or package-level annotations instead.",
12401259
String.join("\n\t- ", modelClassesWithPersistenceUnitAnnotations)));
12411260
}
12421261

1243-
Set<String> affectedModelClasses = modelClassesAndPackagesPerPersistenceUnits.values().stream().flatMap(Set::stream)
1244-
.collect(Collectors.toSet());
1262+
affectedModelClasses.addAll(modelClassesAndPackagesPerPersistenceUnits.values().stream().flatMap(Set::stream).toList());
12451263
Set<String> unaffectedModelClasses = jpaModel.getAllModelClassNames().stream()
12461264
.filter(c -> !affectedModelClasses.contains(c))
12471265
.collect(Collectors.toCollection(TreeSet::new));

extensions/hibernate-reactive/deployment/src/main/java/io/quarkus/hibernate/reactive/deployment/HibernateReactiveProcessor.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import io.quarkus.hibernate.orm.deployment.PersistenceUnitDescriptorBuildItem;
5959
import io.quarkus.hibernate.orm.deployment.PersistenceXmlDescriptorBuildItem;
6060
import io.quarkus.hibernate.orm.deployment.integration.HibernateOrmIntegrationRuntimeConfiguredBuildItem;
61+
import io.quarkus.hibernate.orm.deployment.spi.AdditionalJpaModelBuildItem;
6162
import io.quarkus.hibernate.orm.deployment.spi.DatabaseKindDialectBuildItem;
6263
import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil;
6364
import io.quarkus.hibernate.orm.runtime.boot.QuarkusPersistenceUnitDescriptor;
@@ -114,6 +115,7 @@ public void buildReactivePersistenceUnit(
114115
List<JdbcDataSourceBuildItem> jdbcDataSources,
115116
ApplicationArchivesBuildItem applicationArchivesBuildItem,
116117
LaunchModeBuildItem launchMode,
118+
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
117119
JpaModelBuildItem jpaModel,
118120
Capabilities capabilities,
119121
BuildProducer<SystemPropertyBuildItem> systemProperties,
@@ -157,7 +159,7 @@ public void buildReactivePersistenceUnit(
157159
enableDefaultPersistenceUnit,
158160
reactiveDataSources,
159161
jdbcDataSources,
160-
applicationArchivesBuildItem, jpaModel, launchMode, capabilities,
162+
applicationArchivesBuildItem, additionalJpaModelBuildItems, jpaModel, launchMode, capabilities,
161163
systemProperties, nativeImageResources,
162164
hotDeploymentWatchedFiles, persistenceUnitDescriptors,
163165
unremovableBeans, dbKindDialectBuildItems);
@@ -173,7 +175,7 @@ public void buildReactivePersistenceUnit(
173175

174176
producePersistenceUnitFromConfig(hibernateOrmConfig, namedPersistenceUnitName, persistenceUnitConfig, index,
175177
enableDefaultPersistenceUnit, reactiveDataSources, jdbcDataSources,
176-
applicationArchivesBuildItem, jpaModel, launchMode, capabilities,
178+
applicationArchivesBuildItem, additionalJpaModelBuildItems, jpaModel, launchMode, capabilities,
177179
systemProperties, nativeImageResources,
178180
hotDeploymentWatchedFiles, persistenceUnitDescriptors,
179181
unremovableBeans, dbKindDialectBuildItems);
@@ -186,6 +188,7 @@ private static void producePersistenceUnitFromConfig(HibernateOrmConfig hibernat
186188
List<ReactiveDataSourceBuildItem> reactiveDataSources,
187189
List<JdbcDataSourceBuildItem> jdbcDataSources,
188190
ApplicationArchivesBuildItem applicationArchivesBuildItem,
191+
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
189192
JpaModelBuildItem jpaModel, LaunchModeBuildItem launchMode,
190193
Capabilities capabilities,
191194
BuildProducer<SystemPropertyBuildItem> systemProperties,
@@ -234,7 +237,7 @@ private static void producePersistenceUnitFromConfig(HibernateOrmConfig hibernat
234237
}
235238

236239
QuarkusPersistenceUnitDescriptorWithSupportedDBKind reactivePUWithDBKind = generateReactivePersistenceUnit(
237-
hibernateOrmConfig, persistenceUnitName, index, persistenceUnitConfig, jpaModel,
240+
hibernateOrmConfig, persistenceUnitName, index, persistenceUnitConfig, additionalJpaModelBuildItems, jpaModel,
238241
dbKindOptional, explicitDialect, explicitDbMinVersion, applicationArchivesBuildItem,
239242
launchMode.getLaunchMode(),
240243
systemProperties, nativeImageResources, hotDeploymentWatchedFiles, dbKindDialectBuildItems,
@@ -345,6 +348,7 @@ private static QuarkusPersistenceUnitDescriptorWithSupportedDBKind generateReact
345348
String persistenceUnitName,
346349
CombinedIndexBuildItem index,
347350
HibernateOrmConfigPersistenceUnit persistenceUnitConfig,
351+
List<AdditionalJpaModelBuildItem> additionalJpaModelBuildItems,
348352
JpaModelBuildItem jpaModel,
349353
Optional<String> dbKindOptional,
350354
Optional<String> explicitDialect,
@@ -357,7 +361,8 @@ private static QuarkusPersistenceUnitDescriptorWithSupportedDBKind generateReact
357361
List<DatabaseKindDialectBuildItem> dbKindDialectBuildItems, boolean enableDefaultPersistenceUnit) {
358362

359363
Map<String, Set<String>> modelClassesAndPackagesPerPersistencesUnits = HibernateOrmProcessor
360-
.getModelClassesAndPackagesPerPersistenceUnits(hibernateOrmConfig, jpaModel, index.getIndex(),
364+
.getModelClassesAndPackagesPerPersistenceUnits(hibernateOrmConfig, additionalJpaModelBuildItems, jpaModel,
365+
index.getIndex(),
361366
enableDefaultPersistenceUnit);
362367

363368
Set<String> modelClassesAndPackages = modelClassesAndPackagesPerPersistencesUnits

extensions/hibernate-search-orm-outbox-polling/deployment/src/main/java/io/quarkus/hibernate/search/orm/outboxpolling/deployment/HibernateSearchOutboxPollingProcessor.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.List;
44
import java.util.Optional;
5+
import java.util.Set;
56

67
import org.hibernate.search.mapper.orm.outboxpolling.cfg.HibernateOrmMapperOutboxPollingSettings;
78
import org.hibernate.search.mapper.orm.outboxpolling.mapping.spi.HibernateOrmMapperOutboxPollingClasses;
@@ -37,7 +38,9 @@ void registerInternalModel(BuildProducer<AdditionalIndexedClassesBuildItem> addi
3738
.reason(getClass().getName())
3839
.methods().fields().build());
3940
for (String className : hibernateOrmTypes) {
40-
additionalJpaModel.produce(new AdditionalJpaModelBuildItem(className));
41+
additionalJpaModel.produce(new AdditionalJpaModelBuildItem(className,
42+
// Added to specific PUs at static init using org.hibernate.boot.spi.AdditionalMappingContributor
43+
Set.of()));
4144
}
4245
}
4346

extensions/panache/hibernate-orm-panache-kotlin/deployment/src/main/java/io/quarkus/hibernate/orm/panache/kotlin/deployment/KotlinPanacheResourceProcessor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,9 @@ private void processCompanions(CombinedIndexBuildItem index,
211211
AdditionalJpaModelBuildItem produceModel() {
212212
// only useful for the index resolution: hibernate will register it to be transformed, but BuildMojo
213213
// only transforms classes from the application jar, so we do our own transforming
214-
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.orm.panache.kotlin.PanacheEntity");
214+
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.orm.panache.kotlin.PanacheEntity",
215+
// Only added to persistence units actually using this class, using Jandex-based discovery
216+
Set.of());
215217
}
216218

217219
@BuildStep

extensions/panache/hibernate-orm-panache/deployment/src/main/java/io/quarkus/hibernate/orm/panache/deployment/PanacheHibernateResourceProcessor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ FeatureBuildItem featureBuildItem() {
6565
AdditionalJpaModelBuildItem produceModel() {
6666
// only useful for the index resolution: hibernate will register it to be transformed, but BuildMojo
6767
// only transforms classes from the application jar, so we do our own transforming
68-
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.orm.panache.PanacheEntity");
68+
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.orm.panache.PanacheEntity",
69+
// Only added to persistence units actually using this class, using Jandex-based discovery
70+
Set.of());
6971
}
7072

7173
@BuildStep
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package io.quarkus.hibernate.orm.panache.deployment.test.config.packages;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThatCode;
5+
6+
import java.util.logging.Formatter;
7+
import java.util.logging.Level;
8+
9+
import jakarta.enterprise.context.control.ActivateRequestContext;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.GeneratedValue;
12+
import jakarta.persistence.Id;
13+
14+
import org.jboss.logmanager.formatters.PatternFormatter;
15+
import org.junit.jupiter.api.Test;
16+
import org.junit.jupiter.api.extension.RegisterExtension;
17+
18+
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
19+
import io.quarkus.test.QuarkusUnitTest;
20+
21+
/**
22+
* Reproducer for https://github.com/quarkusio/quarkus/issues/22183
23+
*/
24+
public class ConfigEntityPUAssigmentUsingOnlyPanacheEntityBaseTest {
25+
26+
private static final Formatter LOG_FORMATTER = new PatternFormatter("%s");
27+
28+
@RegisterExtension
29+
static QuarkusUnitTest runner = new QuarkusUnitTest()
30+
.withApplicationRoot((jar) -> jar
31+
.addClasses(EntityExtendingOnlyPanacheEntityBase.class))
32+
// In a real-world scenario, this would be used only if there are multiple PUs,
33+
// but this is simpler and enough to reproduce the issue.
34+
.overrideConfigKey("quarkus.hibernate-orm.packages", EntityExtendingOnlyPanacheEntityBase.class.getPackageName())
35+
.setLogRecordPredicate(record -> record.getLevel().intValue() >= Level.WARNING.intValue())
36+
// We don't expect any warning, in particular not:
37+
// "Could not find a suitable persistence unit for model classes:"
38+
.assertLogRecords(records -> assertThat(records).extracting(LOG_FORMATTER::format).isEmpty());
39+
40+
@Test
41+
@ActivateRequestContext
42+
void smoke() {
43+
// We just want to check the lack of warnings... but let's at least check the entity works correctly.
44+
assertThatCode(() -> EntityExtendingOnlyPanacheEntityBase.count())
45+
.doesNotThrowAnyException();
46+
}
47+
48+
@Entity
49+
public static class EntityExtendingOnlyPanacheEntityBase extends PanacheEntityBase {
50+
@Id
51+
@GeneratedValue
52+
public Long id;
53+
54+
public String name;
55+
}
56+
}

extensions/panache/hibernate-reactive-panache-kotlin/deployment/src/main/java/io/quarkus/hibernate/reactive/panache/kotlin/deployment/HibernateReactivePanacheKotlinProcessor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ public FeatureBuildItem featureBuildItem() {
5353
public AdditionalJpaModelBuildItem produceModel() {
5454
// only useful for the index resolution: hibernate will register it to be transformed, but BuildMojo
5555
// only transforms classes from the application jar, so we do our own transforming
56-
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.reactive.panache.kotlin.PanacheEntity");
56+
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.reactive.panache.kotlin.PanacheEntity",
57+
// Only added to persistence units actually using this class, using Jandex-based discovery
58+
Set.of());
5759
}
5860

5961
@BuildStep

extensions/panache/hibernate-reactive-panache/deployment/src/main/java/io/quarkus/hibernate/reactive/panache/deployment/PanacheHibernateResourceProcessor.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ FeatureBuildItem featureBuildItem() {
6464
AdditionalJpaModelBuildItem produceModel() {
6565
// only useful for the index resolution: hibernate will register it to be transformed, but BuildMojo
6666
// only transforms classes from the application jar, so we do our own transforming
67-
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.reactive.panache.PanacheEntity");
67+
return new AdditionalJpaModelBuildItem("io.quarkus.hibernate.reactive.panache.PanacheEntity",
68+
// Only added to persistence units actually using this class, using Jandex-based discovery
69+
Set.of());
6870
}
6971

7072
@BuildStep

0 commit comments

Comments
 (0)