Skip to content

Commit c2269ef

Browse files
committed
Make sure our extension does not interfere when bootstrapping is not related to it
HIBERNATE-135
1 parent 585a258 commit c2269ef

18 files changed

+166
-105
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ dependencies {
177177
exclude(group = "org.apache.logging.log4j", module = "log4j-core")
178178
}
179179
integrationTestRuntimeOnly("org.junit.platform:junit-platform-launcher")
180+
integrationTestRuntimeOnly(libs.postgresql)
180181

181182
api(libs.jspecify)
182183

gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ slf4j-api = "2.0.16"
2525
logback-classic = "1.5.16"
2626
mockito = "5.16.0"
2727
checker-qual = "3.49.1"
28+
postgresql = "42.7.8"
2829

2930
plugin-spotless = "7.0.2"
3031
plugin-errorprone = "4.1.0"
@@ -47,6 +48,7 @@ sl4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-api" }
4748
logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback-classic" }
4849
mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" }
4950
checker-qual = { module = "org.checkerframework:checker-qual", version.ref = "checker-qual" }
51+
postgresql = { module = "org.postgresql:postgresql", version.ref = "postgresql" }
5052

5153
[bundles]
5254
test-common = ["junit-jupiter", "assertj", "logback-classic"]

src/integrationTest/java/com/mongodb/hibernate/ExceptionHandlingIntegrationTest.java renamed to src/integrationTest/java/com/mongodb/hibernate/ExceptionHandlingIntegrationTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@
4646

4747
/** @see MongoDialect#buildSQLExceptionConversionDelegate() */
4848
@SessionFactory(exportSchema = false)
49-
@DomainModel(annotatedClasses = {ExceptionHandlingIntegrationTest.Item.class})
49+
@DomainModel(annotatedClasses = {ExceptionHandlingIntegrationTests.Item.class})
5050
@ExtendWith(MongoExtension.class)
51-
class ExceptionHandlingIntegrationTest implements SessionFactoryScopeAware {
51+
class ExceptionHandlingIntegrationTests implements SessionFactoryScopeAware {
5252
private static final String COLLECTION_NAME = "items";
5353
private static final String EXCEPTION_MESSAGE_FAILED_TO_EXECUTE_OPERATION = "Failed to execute operation";
5454
private static final String EXCEPTION_MESSAGE_TIMEOUT = "Timeout while waiting for operation to complete";
@@ -101,7 +101,7 @@ void testTimeoutExceptionThrown() {
101101
@ServiceRegistry(settings = @Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "2"))
102102
@ExtendWith(MongoExtension.class)
103103
@SessionFactory(exportSchema = false)
104-
@DomainModel(annotatedClasses = {ExceptionHandlingIntegrationTest.Item.class})
104+
@DomainModel(annotatedClasses = {ExceptionHandlingIntegrationTests.Item.class})
105105
class Batch implements SessionFactoryScopeAware {
106106
SessionFactoryScope sessionFactoryScope;
107107

src/integrationTest/java/com/mongodb/hibernate/boot/FailedBootstrappingIntegrationTests.java

Lines changed: 0 additions & 83 deletions
This file was deleted.

src/integrationTest/java/com/mongodb/hibernate/boot/JakartaPersistenceBootstrappingIntegrationTests.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.mongodb.hibernate.boot;
1818

19+
import static com.mongodb.hibernate.BasicCrudIntegrationTests.Item.COLLECTION_NAME;
1920
import static org.assertj.core.api.Assertions.assertThat;
2021

2122
import com.mongodb.client.MongoCollection;
@@ -41,18 +42,12 @@
4142
annotatedClasses = JakartaPersistenceBootstrappingIntegrationTests.Item.class)
4243
@ExtendWith(MongoExtension.class)
4344
class JakartaPersistenceBootstrappingIntegrationTests {
44-
private static final String COLLECTION_NAME = "items";
45-
4645
@InjectMongoCollection(COLLECTION_NAME)
4746
private static MongoCollection<BsonDocument> mongoCollection;
4847

4948
@Test
5049
void smoke(EntityManagerFactoryScope scope) {
51-
scope.inTransaction(em -> {
52-
var item = new Item();
53-
item.id = 1;
54-
em.persist(item);
55-
});
50+
scope.inTransaction(em -> em.persist(new Item(1)));
5651
assertThat(mongoCollection.find()).containsExactly(BsonDocument.parse("{_id: 1}"));
5752
}
5853

@@ -61,5 +56,9 @@ void smoke(EntityManagerFactoryScope scope) {
6156
static class Item {
6257
@Id
6358
int id;
59+
60+
Item(int id) {
61+
this.id = id;
62+
}
6463
}
6564
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2024-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.hibernate.boot;
18+
19+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
20+
21+
import com.mongodb.client.MongoClient;
22+
import com.mongodb.hibernate.junit.InjectMongoClient;
23+
import com.mongodb.hibernate.junit.MongoExtension;
24+
import org.bson.BsonDocument;
25+
import org.hibernate.boot.MetadataSources;
26+
import org.junit.jupiter.api.Test;
27+
import org.junit.jupiter.api.extension.ExtendWith;
28+
29+
@ExtendWith(MongoExtension.class)
30+
class NativeBootstrappingIntegrationTests {
31+
@InjectMongoClient
32+
private static MongoClient mongoClient;
33+
34+
@Test
35+
@SuppressWarnings("try")
36+
void testCouldNotInstantiateDialectExceptionMessage() {
37+
assertThatThrownBy(() -> {
38+
BsonDocument failPointCommand = BsonDocument.parse(
39+
"""
40+
{
41+
"configureFailPoint": "failCommand",
42+
"mode": {
43+
"times": 1
44+
},
45+
"data": {
46+
"failCommands": ["buildInfo"],
47+
"errorCode": 1
48+
}
49+
}
50+
""");
51+
mongoClient.getDatabase("admin").runCommand(failPointCommand);
52+
new MetadataSources().buildMetadata();
53+
})
54+
.hasRootCauseMessage(
55+
"Could not instantiate [com.mongodb.hibernate.dialect.MongoDialect], see the earlier exceptions to find out why");
56+
}
57+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2025-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.hibernate.internal.boot;
18+
19+
import static com.mongodb.hibernate.BasicCrudIntegrationTests.Item.COLLECTION_NAME;
20+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
21+
22+
import com.mongodb.hibernate.junit.MongoExtension;
23+
import jakarta.persistence.Embeddable;
24+
import jakarta.persistence.Entity;
25+
import jakarta.persistence.Id;
26+
import jakarta.persistence.Table;
27+
import org.hibernate.InstantiationException;
28+
import org.hibernate.cfg.AvailableSettings;
29+
import org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl;
30+
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
31+
import org.hibernate.testing.orm.junit.Jpa;
32+
import org.hibernate.testing.orm.junit.Setting;
33+
import org.junit.jupiter.api.Test;
34+
import org.junit.jupiter.api.extension.ExtendWith;
35+
36+
@Jpa(
37+
exportSchema = false,
38+
integrationSettings = {
39+
@Setting(name = AvailableSettings.DIALECT, value = "org.hibernate.dialect.PostgreSQLDialect"),
40+
@Setting(name = AvailableSettings.JAKARTA_JDBC_URL, value = "postgresql://"),
41+
@Setting(name = AvailableSettings.JAKARTA_JDBC_DRIVER, value = "org.postgresql.Driver"),
42+
@Setting(name = DriverManagerConnectionProviderImpl.INITIAL_SIZE, value = "0"),
43+
},
44+
annotatedClasses = MongoAdditionalMappingContributorTests.Item.class)
45+
@ExtendWith(MongoExtension.class)
46+
class MongoAdditionalMappingContributorTests {
47+
/**
48+
* Verify that {@link MongoAdditionalMappingContributor} skips its logic when bootstrapping is not related to the
49+
* MongoDB Extension for Hibernate ORM.
50+
*/
51+
@Test
52+
void testMongoAdditionalMappingContributorIsSkipped(EntityManagerFactoryScope scope) {
53+
assertThatThrownBy(() -> scope.inTransaction(em -> em.persist(new Item(null))))
54+
.isInstanceOf(InstantiationException.class)
55+
.hasMessageNotContaining("does not support primary key spanning multiple columns")
56+
.hasMessageMatching("Could not instantiate entity .* due to: null");
57+
}
58+
59+
@Entity
60+
@Table(name = COLLECTION_NAME)
61+
static class Item {
62+
@Id
63+
MultipleColumns id;
64+
65+
Item(MultipleColumns id) {
66+
this.id = id;
67+
}
68+
}
69+
70+
@Embeddable
71+
record MultipleColumns(int a, int b) {}
72+
}
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.mongodb.hibernate.internal.extension;
17+
package com.mongodb.hibernate.internal.boot;
1818

1919
import static com.mongodb.hibernate.internal.MongoAssertions.assertFalse;
2020
import static com.mongodb.hibernate.internal.MongoAssertions.assertInstanceOf;
@@ -23,6 +23,7 @@
2323
import static com.mongodb.hibernate.internal.MongoConstants.MONGO_DBMS_NAME;
2424
import static java.lang.String.format;
2525

26+
import com.mongodb.hibernate.dialect.MongoDialect;
2627
import com.mongodb.hibernate.internal.FeatureNotSupportedException;
2728
import jakarta.persistence.Embeddable;
2829
import java.sql.Time;
@@ -83,6 +84,10 @@ public void contribute(
8384
InFlightMetadataCollector metadata,
8485
ResourceStreamLocator resourceStreamLocator,
8586
MetadataBuildingContext buildingContext) {
87+
if (!(metadata.getDatabase().getDialect() instanceof MongoDialect)) {
88+
// avoid interfering with bootstrapping not related to the MongoDB Extension for Hibernate ORM
89+
return;
90+
}
8691
forbidEmbeddablesWithoutPersistentAttributes(metadata);
8792
metadata.getEntityBindings().forEach(persistentClass -> {
8893
checkPropertyTypes(persistentClass);

src/main/java/com/mongodb/hibernate/internal/extension/package-info.java renamed to src/main/java/com/mongodb/hibernate/internal/boot/package-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616

1717
/** The program elements within this package are not part of the public API and may be removed or changed at any time */
1818
@NullMarked
19-
package com.mongodb.hibernate.internal.extension;
19+
package com.mongodb.hibernate.internal.boot;
2020

2121
import org.jspecify.annotations.NullMarked;
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
package com.mongodb.hibernate.internal.extension.service;
17+
package com.mongodb.hibernate.internal.service;
1818

1919
import static com.mongodb.hibernate.internal.VisibleForTesting.AccessModifier.PRIVATE;
2020
import static java.lang.String.format;
@@ -84,8 +84,7 @@ public StandardServiceRegistryScopedState initiateService(
8484
private MongoConfiguration createMongoConfiguration(
8585
Map<String, Object> configurationValues, ServiceRegistryImplementor serviceRegistry) {
8686
var jdbcUrl = configurationValues.get(JAKARTA_JDBC_URL);
87-
MongoConfigurationContributor mongoConfigurationContributor =
88-
getMongoConfigurationContributor(serviceRegistry);
87+
var mongoConfigurationContributor = getMongoConfigurationContributor(serviceRegistry);
8988
if (jdbcUrl == null && mongoConfigurationContributor == null) {
9089
throw new HibernateException(format(
9190
"Configuration property [%s] is required unless %s is provided",

0 commit comments

Comments
 (0)