|
19 | 19 | import java.io.IOException;
|
20 | 20 | import java.net.URL;
|
21 | 21 | import java.net.URLClassLoader;
|
| 22 | +import java.util.ArrayList; |
22 | 23 | import java.util.Arrays;
|
23 | 24 | import java.util.Collections;
|
24 | 25 | import java.util.Enumeration;
|
|
46 | 47 | import org.springframework.boot.autoconfigure.AutoConfigurations;
|
47 | 48 | import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
48 | 49 | import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
| 50 | +import org.springframework.boot.autoconfigure.jdbc.DataSourceSchemaCreatedEvent; |
49 | 51 | import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
50 | 52 | import org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration;
|
51 | 53 | import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
| 54 | +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurationTests.JpaUsingApplicationListenerConfiguration.EventCapturingApplicationListener; |
52 | 55 | import org.springframework.boot.autoconfigure.orm.jpa.mapping.NonAnnotatedEntity;
|
53 | 56 | import org.springframework.boot.autoconfigure.orm.jpa.test.City;
|
54 | 57 | import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
|
|
57 | 60 | import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
|
58 | 61 | import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
|
59 | 62 | import org.springframework.boot.test.context.runner.ContextConsumer;
|
| 63 | +import org.springframework.context.ApplicationEvent; |
| 64 | +import org.springframework.context.ApplicationListener; |
60 | 65 | import org.springframework.context.annotation.Bean;
|
61 | 66 | import org.springframework.context.annotation.Configuration;
|
62 | 67 | import org.springframework.orm.jpa.JpaTransactionManager;
|
63 | 68 | import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
| 69 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
64 | 70 |
|
65 | 71 | import static org.assertj.core.api.Assertions.assertThat;
|
66 | 72 | import static org.assertj.core.api.Assertions.entry;
|
@@ -383,6 +389,52 @@ public void hibernatePropertiesCustomizerCanDisableBeanContainer() {
|
383 | 389 | .run((context) -> assertThat(context).doesNotHaveBean(City.class));
|
384 | 390 | }
|
385 | 391 |
|
| 392 | + @Test |
| 393 | + public void withSyncBootstrappingAnApplicationListenerThatUsesJpaDoesNotTriggerABeanCurrentlyInCreationException() { |
| 394 | + contextRunner() |
| 395 | + .withUserConfiguration(JpaUsingApplicationListenerConfiguration.class) |
| 396 | + .withPropertyValues("spring.datasource.initialization-mode=never") |
| 397 | + .run((context) -> { |
| 398 | + assertThat(context).hasNotFailed(); |
| 399 | + assertThat(context |
| 400 | + .getBean(EventCapturingApplicationListener.class).events |
| 401 | + .stream() |
| 402 | + .filter(DataSourceSchemaCreatedEvent.class::isInstance)) |
| 403 | + .hasSize(1); |
| 404 | + }); |
| 405 | + } |
| 406 | + |
| 407 | + @Test |
| 408 | + public void withAsyncBootstrappingAnApplicationListenerThatUsesJpaDoesNotTriggerABeanCurrentlyInCreationException() { |
| 409 | + contextRunner() |
| 410 | + .withUserConfiguration(AsyncBootstrappingConfiguration.class, |
| 411 | + JpaUsingApplicationListenerConfiguration.class) |
| 412 | + .withPropertyValues("spring.datasource.initialization-mode=never") |
| 413 | + .run((context) -> { |
| 414 | + assertThat(context).hasNotFailed(); |
| 415 | + EventCapturingApplicationListener listener = context |
| 416 | + .getBean(EventCapturingApplicationListener.class); |
| 417 | + long end = System.currentTimeMillis() + 30000; |
| 418 | + while ((System.currentTimeMillis() < end) |
| 419 | + && !dataSourceSchemaCreatedEventReceived(listener)) { |
| 420 | + Thread.sleep(100); |
| 421 | + } |
| 422 | + assertThat(listener.events.stream() |
| 423 | + .filter(DataSourceSchemaCreatedEvent.class::isInstance)) |
| 424 | + .hasSize(1); |
| 425 | + }); |
| 426 | + } |
| 427 | + |
| 428 | + private boolean dataSourceSchemaCreatedEventReceived( |
| 429 | + EventCapturingApplicationListener listener) { |
| 430 | + for (ApplicationEvent event : listener.events) { |
| 431 | + if (event instanceof DataSourceSchemaCreatedEvent) { |
| 432 | + return true; |
| 433 | + } |
| 434 | + } |
| 435 | + return false; |
| 436 | + } |
| 437 | + |
386 | 438 | @Configuration
|
387 | 439 | @TestAutoConfigurationPackage(City.class)
|
388 | 440 | static class TestInitializedJpaConfiguration {
|
@@ -506,4 +558,45 @@ public Enumeration<URL> getResources(String name) throws IOException {
|
506 | 558 |
|
507 | 559 | }
|
508 | 560 |
|
| 561 | + @org.springframework.context.annotation.Configuration |
| 562 | + static class JpaUsingApplicationListenerConfiguration { |
| 563 | + |
| 564 | + @Bean |
| 565 | + public EventCapturingApplicationListener jpaUsingApplicationListener( |
| 566 | + EntityManagerFactory emf) { |
| 567 | + return new EventCapturingApplicationListener(); |
| 568 | + } |
| 569 | + |
| 570 | + static class EventCapturingApplicationListener |
| 571 | + implements ApplicationListener<ApplicationEvent> { |
| 572 | + |
| 573 | + private final List<ApplicationEvent> events = new ArrayList<>(); |
| 574 | + |
| 575 | + @Override |
| 576 | + public void onApplicationEvent(ApplicationEvent event) { |
| 577 | + this.events.add(event); |
| 578 | + } |
| 579 | + |
| 580 | + } |
| 581 | + |
| 582 | + } |
| 583 | + |
| 584 | + @Configuration |
| 585 | + static class AsyncBootstrappingConfiguration { |
| 586 | + |
| 587 | + @Bean |
| 588 | + ThreadPoolTaskExecutor ThreadPoolTaskExecutor() { |
| 589 | + return new ThreadPoolTaskExecutor(); |
| 590 | + } |
| 591 | + |
| 592 | + @Bean |
| 593 | + public EntityManagerFactoryBuilderCustomizer asyncBoostrappingCustomizer( |
| 594 | + ThreadPoolTaskExecutor executor) { |
| 595 | + return (builder) -> { |
| 596 | + builder.setBootstrapExecutor(executor); |
| 597 | + }; |
| 598 | + } |
| 599 | + |
| 600 | + } |
| 601 | + |
509 | 602 | }
|
0 commit comments