Polish "Lazily resolve JPA fallback bootstrap executor"

See gh-50801
This commit is contained in:
Stéphane Nicoll
2026-07-14 17:45:54 +02:00
parent 8c519369ec
commit d4d20787c1
3 changed files with 15 additions and 18 deletions
@@ -104,6 +104,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.SQLExceptionTranslator;
@@ -304,11 +305,11 @@ class HibernateJpaAutoConfigurationTests {
}
@Test
void whenAsyncTaskExecutorIsDefinedInJpaDependentConfigurationDoesNotTriggerABeanCurrentlyInCreationException() {
this.contextRunner.withUserConfiguration(AsyncTaskExecutorDependingOnEntityManagerFactoryConfiguration.class)
void whenAsyncTaskExecutorIsDefinedInJpaDependentConfigurationDoesNotFail() {
this.contextRunner.withUserConfiguration(TaskExecutorDependingOnEntityManagerFactoryConfiguration.class)
.run((context) -> {
assertThat(context).hasNotFailed();
assertThat(context).hasSingleBean(EntityManagerFactory.class);
assertThat(context).hasSingleBean(EntityManagerFactory.class).hasSingleBean(AsyncTaskExecutor.class);
});
}
@@ -1484,9 +1485,9 @@ class HibernateJpaAutoConfigurationTests {
}
@Configuration(proxyBeanMethods = false)
static class AsyncTaskExecutorDependingOnEntityManagerFactoryConfiguration {
static class TaskExecutorDependingOnEntityManagerFactoryConfiguration {
AsyncTaskExecutorDependingOnEntityManagerFactoryConfiguration(EntityManagerFactory entityManagerFactory) {
TaskExecutorDependingOnEntityManagerFactoryConfiguration(EntityManagerFactory entityManagerFactory) {
}
@Bean
@@ -121,7 +121,10 @@ public class EntityManagerFactoryBuilder {
* @param fallbackBootstrapExecutor the fallback executor to use when background
* bootstrapping is required but no explicit executor has been set
* @since 4.1.0
* @deprecated since 4.1.1 for removal in 4.3.0 in favor of
* {@link #EntityManagerFactoryBuilder(JpaVendorAdapter, Function, PersistenceUnitManager, URL, Supplier)}
*/
@Deprecated(since = "4.1.1", forRemoval = true)
public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
Function<DataSource, Map<String, ?>> jpaPropertiesFactory,
@Nullable PersistenceUnitManager persistenceUnitManager, @Nullable URL persistenceUnitRootLocation,
@@ -141,8 +144,7 @@ public class EntityManagerFactoryBuilder {
* @param persistenceUnitRootLocation the persistence unit root location to use as a
* fallback or {@code null}
* @param fallbackBootstrapExecutor a supplier of the fallback executor to use when
* background bootstrapping is required but no explicit executor has been set. The
* supplier is only invoked when background bootstrapping is actually required.
* background bootstrapping is required, but no explicit executor has been set.
* @since 4.1.1
*/
public EntityManagerFactoryBuilder(JpaVendorAdapter jpaVendorAdapter,
@@ -104,7 +104,7 @@ class EntityManagerFactoryBuilderTests {
@Test
void requireBootstrapExecutorWhenFallbackExecutorProvidesExecutorDoesNotThrow() {
EntityManagerFactoryBuilder builder = createEmptyBuilder(new SimpleAsyncTaskExecutor());
EntityManagerFactoryBuilder builder = createEmptyBuilder(SimpleAsyncTaskExecutor::new);
builder.requireBootstrapExecutor(() -> new IllegalStateException("BAD"));
DataSource dataSource = mock();
assertThatNoException().isThrownBy(builder.dataSource(dataSource)::build);
@@ -129,7 +129,7 @@ class EntityManagerFactoryBuilderTests {
@Test
void requireBootstrapExecutorWhenFallbackExecutorSupplierProvidesExecutorDoesNotThrow() {
EntityManagerFactoryBuilder builder = createEmptyBuilderWithFallbackSupplier(SimpleAsyncTaskExecutor::new);
EntityManagerFactoryBuilder builder = createEmptyBuilder(SimpleAsyncTaskExecutor::new);
builder.requireBootstrapExecutor(() -> new IllegalStateException("BAD"));
DataSource dataSource = mock();
assertThatNoException().isThrownBy(builder.dataSource(dataSource)::build);
@@ -138,7 +138,7 @@ class EntityManagerFactoryBuilderTests {
@Test
void fallbackExecutorSupplierIsNotInvokedWhenBootstrapExecutorNotRequired() {
AtomicBoolean invoked = new AtomicBoolean();
EntityManagerFactoryBuilder builder = createEmptyBuilderWithFallbackSupplier(() -> {
EntityManagerFactoryBuilder builder = createEmptyBuilder(() -> {
invoked.set(true);
return new SimpleAsyncTaskExecutor();
});
@@ -148,16 +148,10 @@ class EntityManagerFactoryBuilderTests {
}
private EntityManagerFactoryBuilder createEmptyBuilder() {
return createEmptyBuilder(null);
return createEmptyBuilder(() -> null);
}
private EntityManagerFactoryBuilder createEmptyBuilder(@Nullable AsyncTaskExecutor fallbackBootstrapExecutor) {
Function<DataSource, Map<String, ?>> jpaPropertiesFactory = (dataSource) -> Collections.emptyMap();
return new EntityManagerFactoryBuilder(new TestJpaVendorAdapter(), jpaPropertiesFactory, null, null,
fallbackBootstrapExecutor);
}
private EntityManagerFactoryBuilder createEmptyBuilderWithFallbackSupplier(
private EntityManagerFactoryBuilder createEmptyBuilder(
Supplier<? extends @Nullable AsyncTaskExecutor> fallbackBootstrapExecutorSupplier) {
Function<DataSource, Map<String, ?>> jpaPropertiesFactory = (dataSource) -> Collections.emptyMap();
return new EntityManagerFactoryBuilder(new TestJpaVendorAdapter(), jpaPropertiesFactory, null, null,