|
42 | 42 | import org.springframework.boot.context.event.ApplicationStartedEvent; |
43 | 43 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
44 | 44 | import org.springframework.boot.flyway.autoconfigure.FlywayMigrationStrategy; |
| 45 | +import org.springframework.boot.system.JavaVersion; |
45 | 46 | import org.springframework.context.ApplicationContext; |
46 | 47 | import org.springframework.context.ApplicationListener; |
47 | 48 | import org.springframework.context.annotation.Bean; |
48 | 49 | import org.springframework.context.annotation.Lazy; |
49 | 50 | import org.springframework.context.annotation.Role; |
50 | 51 | import org.springframework.core.io.Resource; |
51 | 52 | import org.springframework.core.io.support.SpringFactoriesLoader; |
| 53 | +import org.springframework.core.task.SimpleAsyncTaskExecutor; |
52 | 54 | import org.springframework.modulith.ApplicationModuleInitializer; |
53 | 55 | import org.springframework.modulith.core.ApplicationModule; |
54 | 56 | import org.springframework.modulith.core.ApplicationModuleIdentifier; |
@@ -200,14 +202,35 @@ static class ApplicationModulesBootstrap { |
200 | 202 | Supplier<ApplicationModules> supplier = () -> initializeApplicationModules(applicationMainClass); |
201 | 203 |
|
202 | 204 | this.modules = executor == null |
203 | | - ? CompletableFuture.supplyAsync(supplier) |
| 205 | + ? withFallbackExecutor(supplier) |
204 | 206 | : CompletableFuture.supplyAsync(supplier, executor); |
| 207 | + |
205 | 208 | } |
206 | 209 |
|
207 | 210 | CompletableFuture<ApplicationModules> getApplicationModules() { |
208 | 211 | return modules; |
209 | 212 | } |
210 | 213 |
|
| 214 | + /** |
| 215 | + * We didn't get an {@link Executor} instance handed in, so asynchronously execute the supplier through a Spring |
| 216 | + * {@link SimpleAsyncTaskExecutor} to make sure we see the right {@link ClassLoader} during the execution. |
| 217 | + * |
| 218 | + * @param <T> |
| 219 | + * @param supplier |
| 220 | + * @return |
| 221 | + */ |
| 222 | + private static <T> CompletableFuture<T> withFallbackExecutor(Supplier<T> supplier) { |
| 223 | + |
| 224 | + var fallback = new SimpleAsyncTaskExecutor(); |
| 225 | + |
| 226 | + if (JavaVersion.getJavaVersion().isEqualOrNewerThan(JavaVersion.TWENTY_ONE)) { |
| 227 | + fallback.setVirtualThreads(true); |
| 228 | + } |
| 229 | + |
| 230 | + return fallback.submitCompletable(supplier::get) |
| 231 | + .whenComplete((m, t) -> fallback.close()); |
| 232 | + } |
| 233 | + |
211 | 234 | static ApplicationModules initializeApplicationModules(Class<?> applicationMainClass) { |
212 | 235 |
|
213 | 236 | LOGGER.debug("Obtaining Spring Modulith application modules…"); |
|
0 commit comments