From 18e72d5c0162b5b381b2d5a28d7bf004ecbb368f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 1 Aug 2023 23:52:33 +0200 Subject: [PATCH 1/3] Always use given fallback producer in case of TypeBootstrapContext Closes gh-30924 --- .../orm/hibernate5/SpringBeanContainer.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java index 6e73747a59..2a4ac9e084 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate5/SpringBeanContainer.java @@ -24,6 +24,7 @@ import org.apache.commons.logging.LogFactory; import org.hibernate.resource.beans.container.spi.BeanContainer; import org.hibernate.resource.beans.container.spi.ContainedBean; import org.hibernate.resource.beans.spi.BeanInstanceProducer; +import org.hibernate.type.spi.TypeBootstrapContext; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanCreationException; @@ -180,14 +181,28 @@ public final class SpringBeanContainer implements BeanContainer { try { if (lifecycleOptions.useJpaCompliantCreation()) { + Object bean = null; + if (fallbackProducer instanceof TypeBootstrapContext) { + // Special Hibernate type construction rules, including TypeBootstrapContext resolution. + bean = fallbackProducer.produceBeanInstance(name, beanType); + } if (this.beanFactory.containsBean(name)) { - Object bean = this.beanFactory.autowire(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false); + if (bean == null) { + bean = this.beanFactory.autowire(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false); + } this.beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false); this.beanFactory.applyBeanPropertyValues(bean, name); bean = this.beanFactory.initializeBean(bean, name); return new SpringContainedBean<>(bean, beanInstance -> this.beanFactory.destroyBean(name, beanInstance)); } + else if (bean != null) { + // No bean found by name but constructed with TypeBootstrapContext rules + this.beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false); + bean = this.beanFactory.initializeBean(bean, name); + return new SpringContainedBean<>(bean, this.beanFactory::destroyBean); + } else { + // No bean found by name -> construct by type using createBean return new SpringContainedBean<>( // to be replaced with plain createBean(Class) this.beanFactory.createBean(beanType, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false), this.beanFactory::destroyBean); From ae279eaced82cf7fe69235556b48befd65290966 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 1 Aug 2023 23:52:48 +0200 Subject: [PATCH 2/3] Polishing --- spring-context/spring-context.gradle | 2 +- .../connection/ConnectionFactoryUtils.java | 10 ++++----- spring-test/spring-test.gradle | 16 +++++++------- .../reactive/TransactionContextManager.java | 8 +++---- .../TransactionSynchronizationManager.java | 16 ++++++++------ spring-web/spring-web.gradle | 6 ++--- spring-webflux/spring-webflux.gradle | 4 ++-- spring-webmvc/spring-webmvc.gradle | 22 +++++++++---------- .../servlet/handler/MappedInterceptor.java | 4 ++-- 9 files changed, 45 insertions(+), 43 deletions(-) diff --git a/spring-context/spring-context.gradle b/spring-context/spring-context.gradle index 2fc2d2005d..081a7e12ba 100644 --- a/spring-context/spring-context.gradle +++ b/spring-context/spring-context.gradle @@ -20,9 +20,9 @@ dependencies { optional("jakarta.validation:jakarta.validation-api") optional("javax.annotation:javax.annotation-api") optional("javax.money:money-api") - optional("org.aspectj:aspectjweaver") optional("org.apache.groovy:groovy") optional("org.apache-extras.beanshell:bsh") + optional("org.aspectj:aspectjweaver") optional("org.hibernate:hibernate-validator") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") diff --git a/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/ConnectionFactoryUtils.java b/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/ConnectionFactoryUtils.java index 3b176a2084..c128a16790 100644 --- a/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/ConnectionFactoryUtils.java +++ b/spring-r2dbc/src/main/java/org/springframework/r2dbc/connection/ConnectionFactoryUtils.java @@ -126,8 +126,8 @@ public abstract class ConnectionFactoryUtils { holderToUse.setConnection(conn); } holderToUse.requested(); - synchronizationManager - .registerSynchronization(new ConnectionSynchronization(holderToUse, connectionFactory)); + synchronizationManager.registerSynchronization( + new ConnectionSynchronization(holderToUse, connectionFactory)); holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != conHolder) { synchronizationManager.bindResource(connectionFactory, holderToUse); @@ -173,8 +173,7 @@ public abstract class ConnectionFactoryUtils { * @see #doGetConnection */ public static Mono doReleaseConnection(Connection connection, ConnectionFactory connectionFactory) { - return TransactionSynchronizationManager.forCurrentTransaction() - .flatMap(synchronizationManager -> { + return TransactionSynchronizationManager.forCurrentTransaction().flatMap(synchronizationManager -> { ConnectionHolder conHolder = (ConnectionHolder) synchronizationManager.getResource(connectionFactory); if (conHolder != null && connectionEquals(conHolder, connection)) { // It's the transactional Connection: Don't close it. @@ -289,7 +288,8 @@ public abstract class ConnectionFactoryUtils { Connection heldCon = conHolder.getConnection(); // Explicitly check for identity too: for Connection handles that do not implement // "equals" properly). - return (heldCon == passedInCon || heldCon.equals(passedInCon) || getTargetConnection(heldCon).equals(passedInCon)); + return (heldCon == passedInCon || heldCon.equals(passedInCon) || + getTargetConnection(heldCon).equals(passedInCon)); } /** diff --git a/spring-test/spring-test.gradle b/spring-test/spring-test.gradle index 303698e542..fd54a7a795 100644 --- a/spring-test/spring-test.gradle +++ b/spring-test/spring-test.gradle @@ -14,7 +14,11 @@ dependencies { optional(project(":spring-webflux")) optional(project(":spring-webmvc")) optional(project(":spring-websocket")) - optional('info.picocli:picocli') + optional("com.jayway.jsonpath:json-path") + optional("info.picocli:picocli") + optional("io.micrometer:context-propagation") + optional("io.micrometer:micrometer-observation") + optional("io.projectreactor:reactor-test") optional("jakarta.activation:jakarta.activation-api") optional("jakarta.el:jakarta.el-api") optional("jakarta.inject:jakarta.inject-api") @@ -44,14 +48,10 @@ dependencies { } optional("org.xmlunit:xmlunit-matchers") optional("org.skyscreamer:jsonassert") - optional("com.jayway.jsonpath:json-path") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") - optional("io.projectreactor:reactor-test") optional("org.jetbrains.kotlinx:kotlinx-coroutines-core") optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - optional('io.micrometer:context-propagation') - optional('io.micrometer:micrometer-observation') testImplementation(project(":spring-core-test")) testImplementation(project(":spring-context-support")) testImplementation(project(":spring-oxm")) @@ -60,14 +60,15 @@ dependencies { testImplementation(testFixtures(project(":spring-core"))) testImplementation(testFixtures(project(":spring-tx"))) testImplementation(testFixtures(project(":spring-web"))) + testImplementation("de.bechte.junit:junit-hierarchicalcontextrunner") testImplementation("jakarta.annotation:jakarta.annotation-api") - testImplementation("javax.cache:cache-api") testImplementation("jakarta.ejb:jakarta.ejb-api") testImplementation("jakarta.interceptor:jakarta.interceptor-api") testImplementation("jakarta.mail:jakarta.mail-api") + testImplementation("jakarta.validation:jakarta.validation-api") + testImplementation("javax.cache:cache-api") testImplementation("org.hibernate:hibernate-core-jakarta") testImplementation("org.hibernate:hibernate-validator") - testImplementation("jakarta.validation:jakarta.validation-api") testImplementation("org.junit.platform:junit-platform-testkit") testImplementation("com.fasterxml.jackson.core:jackson-databind") testImplementation("com.thoughtworks.xstream:xstream") @@ -77,7 +78,6 @@ dependencies { exclude group: "commons-logging", module: "commons-logging" } testImplementation("io.projectreactor.netty:reactor-netty-http") - testImplementation("de.bechte.junit:junit-hierarchicalcontextrunner") testRuntimeOnly("org.junit.vintage:junit-vintage-engine") { exclude group: "junit", module: "junit" } diff --git a/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionContextManager.java b/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionContextManager.java index db6f4fb414..cac1f04133 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionContextManager.java +++ b/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionContextManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,10 +46,10 @@ public abstract class TransactionContextManager { * transactional context holder. Context retrieval fails with NoTransactionException * if no context or context holder is registered. * @return the current {@link TransactionContext} - * @throws NoTransactionException if no TransactionContext was found in the subscriber context - * or no context found in a holder + * @throws NoTransactionException if no TransactionContext was found in the + * subscriber context or no context found in a holder */ - public static Mono currentContext() throws NoTransactionException { + public static Mono currentContext() { return Mono.deferContextual(ctx -> { if (ctx.hasKey(TransactionContext.class)) { return Mono.just(ctx.get(TransactionContext.class)); diff --git a/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionSynchronizationManager.java b/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionSynchronizationManager.java index 54f7cd17a0..27ed7f4173 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionSynchronizationManager.java +++ b/spring-tx/src/main/java/org/springframework/transaction/reactive/TransactionSynchronizationManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,8 +32,8 @@ import org.springframework.util.Assert; /** * Central delegate that manages resources and transaction synchronizations per - * subscriber context. - * To be used by resource management code but not by typical application code. + * subscriber context. To be used by resource management code but not by typical + * application code. * *

Supports one resource per key without overwriting, that is, a resource needs * to be removed before a new one can be set for the same key. @@ -73,6 +73,7 @@ public class TransactionSynchronizationManager { public TransactionSynchronizationManager(TransactionContext transactionContext) { + Assert.notNull(transactionContext, "TransactionContext must not be null"); this.transactionContext = transactionContext; } @@ -88,10 +89,11 @@ public class TransactionSynchronizationManager { return TransactionContextManager.currentContext().map(TransactionSynchronizationManager::new); } + /** - * Check if there is a resource for the given key bound to the current thread. + * Check if there is a resource for the given key bound to the current context. * @param key the key to check (usually the resource factory) - * @return if there is a value bound to the current thread + * @return if there is a value bound to the current context */ public boolean hasResource(Object key) { Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key); @@ -100,9 +102,9 @@ public class TransactionSynchronizationManager { } /** - * Retrieve a resource for the given key that is bound to the current thread. + * Retrieve a resource for the given key that is bound to the current context. * @param key the key to check (usually the resource factory) - * @return a value bound to the current thread (usually the active + * @return a value bound to the current context (usually the active * resource object), or {@code null} if none */ @Nullable diff --git a/spring-web/spring-web.gradle b/spring-web/spring-web.gradle index d915e22bfc..50b88bd1f0 100644 --- a/spring-web/spring-web.gradle +++ b/spring-web/spring-web.gradle @@ -30,7 +30,10 @@ dependencies { optional("io.projectreactor.netty:reactor-netty-http") optional("io.projectreactor.netty:reactor-netty5-http") optional("io.undertow:undertow-core") + optional("org.apache.httpcomponents.client5:httpclient5") + optional("org.apache.httpcomponents.core5:httpcore5-reactive") optional("org.apache.tomcat.embed:tomcat-embed-core") + optional("org.eclipse.jetty:jetty-reactive-httpclient") optional("org.eclipse.jetty:jetty-server") { exclude group: "jakarta.servlet", module: "jakarta.servlet-api" } @@ -44,9 +47,6 @@ dependencies { exclude group: "org.eclipse.jetty", module: "jetty-server" exclude group: "org.eclipse.jetty", module: "jetty-servlet" } - optional("org.eclipse.jetty:jetty-reactive-httpclient") - optional('org.apache.httpcomponents.client5:httpclient5') - optional('org.apache.httpcomponents.core5:httpcore5-reactive') optional("com.squareup.okhttp3:okhttp") optional("com.fasterxml.woodstox:woodstox-core") optional("com.fasterxml:aalto-xml") diff --git a/spring-webflux/spring-webflux.gradle b/spring-webflux/spring-webflux.gradle index 7a09ba8559..77cbf81f29 100644 --- a/spring-webflux/spring-webflux.gradle +++ b/spring-webflux/spring-webflux.gradle @@ -43,13 +43,13 @@ dependencies { testImplementation("io.projectreactor:reactor-test") testImplementation("io.micrometer:micrometer-observation-test") testImplementation("io.undertow:undertow-core") + testImplementation("org.apache.httpcomponents.client5:httpclient5") + testImplementation("org.apache.httpcomponents.core5:httpcore5-reactive") testImplementation("org.apache.tomcat.embed:tomcat-embed-core") testImplementation("org.apache.tomcat:tomcat-util") testImplementation("org.eclipse.jetty:jetty-server") testImplementation("org.eclipse.jetty:jetty-servlet") testImplementation("org.eclipse.jetty:jetty-reactive-httpclient") - testImplementation('org.apache.httpcomponents.client5:httpclient5') - testImplementation('org.apache.httpcomponents.core5:httpcore5-reactive') testImplementation("com.squareup.okhttp3:mockwebserver") testImplementation("org.jetbrains.kotlin:kotlin-script-runtime") testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json") diff --git a/spring-webmvc/spring-webmvc.gradle b/spring-webmvc/spring-webmvc.gradle index 96ea41bc76..3e751d2e5b 100644 --- a/spring-webmvc/spring-webmvc.gradle +++ b/spring-webmvc/spring-webmvc.gradle @@ -15,28 +15,28 @@ dependencies { } optional(project(":spring-context-support")) // for FreeMarker support optional(project(":spring-oxm")) + optional("com.fasterxml.jackson.core:jackson-databind") + optional("com.fasterxml.jackson.dataformat:jackson-dataformat-cbor") + optional("com.fasterxml.jackson.dataformat:jackson-dataformat-smile") + optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml") + optional("com.github.librepdf:openpdf") + optional("com.rometools:rome") + optional("io.micrometer:context-propagation") + optional("jakarta.el:jakarta.el-api") optional("jakarta.servlet.jsp:jakarta.servlet.jsp-api") optional("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api") - optional("jakarta.el:jakarta.el-api") optional("jakarta.xml.bind:jakarta.xml.bind-api") - optional('io.micrometer:context-propagation') - optional("org.webjars:webjars-locator-core") - optional("com.rometools:rome") - optional("com.github.librepdf:openpdf") + optional("org.apache.groovy:groovy-templates") optional("org.apache.poi:poi-ooxml") optional("org.freemarker:freemarker") - optional("com.fasterxml.jackson.core:jackson-databind") - optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml") - optional("com.fasterxml.jackson.dataformat:jackson-dataformat-smile") - optional("com.fasterxml.jackson.dataformat:jackson-dataformat-cbor") - optional("org.apache.groovy:groovy-templates") optional("org.jetbrains.kotlin:kotlin-reflect") optional("org.jetbrains.kotlin:kotlin-stdlib") + optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") optional("org.jetbrains.kotlinx:kotlinx-serialization-cbor") optional("org.jetbrains.kotlinx:kotlinx-serialization-json") optional("org.jetbrains.kotlinx:kotlinx-serialization-protobuf") optional("org.reactivestreams:reactive-streams") - optional("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") + optional("org.webjars:webjars-locator-core") testImplementation(testFixtures(project(":spring-beans"))) testImplementation(testFixtures(project(":spring-core"))) testImplementation(testFixtures(project(":spring-context"))) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/MappedInterceptor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/MappedInterceptor.java index ebac18eeda..4ae283377f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/MappedInterceptor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/MappedInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,7 +61,7 @@ import org.springframework.web.util.pattern.PatternParseException; */ public final class MappedInterceptor implements HandlerInterceptor { - private static PathMatcher defaultPathMatcher = new AntPathMatcher(); + private static final PathMatcher defaultPathMatcher = new AntPathMatcher(); @Nullable From 52176edcbf5942782b7ee94d57cb7dc9baac8b8d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 2 Aug 2023 00:06:49 +0200 Subject: [PATCH 3/3] Polishing --- .../event/SimpleApplicationEventMulticaster.java | 10 ++++++---- .../annotation/EnableSchedulingTests.java | 16 ++++++++-------- .../event/TransactionalEventListenerTests.java | 11 +++-------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java b/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java index daf6cd1e89..e670adb419 100644 --- a/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java +++ b/spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java @@ -79,10 +79,11 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM * to invoke each listener with. *

Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor}, * executing all listeners synchronously in the calling thread. - *

Consider specifying an asynchronous task executor here to not block the - * caller until all listeners have been executed. However, note that asynchronous - * execution will not participate in the caller's thread context (class loader, - * transaction association) unless the TaskExecutor explicitly supports this. + *

Consider specifying an asynchronous task executor here to not block the caller + * until all listeners have been executed. However, note that asynchronous execution + * will not participate in the caller's thread context (class loader, transaction context) + * unless the TaskExecutor explicitly supports this. + * @since 2.0 * @see org.springframework.core.task.SyncTaskExecutor * @see org.springframework.core.task.SimpleAsyncTaskExecutor */ @@ -92,6 +93,7 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM /** * Return the current task executor for this multicaster. + * @since 2.0 */ @Nullable protected Executor getTaskExecutor() { diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java index 08a44180af..11854b11e3 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableSchedulingTests.java @@ -65,7 +65,7 @@ public class EnableSchedulingTests { ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfig.class); assertThat(ctx.getBean(ScheduledTaskHolder.class).getScheduledTasks()).hasSize(2); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThanOrEqualTo(10); } @@ -75,7 +75,7 @@ public class EnableSchedulingTests { ctx = new AnnotationConfigApplicationContext(FixedRateTaskConfigSubclass.class); assertThat(ctx.getBean(ScheduledTaskHolder.class).getScheduledTasks()).hasSize(2); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThanOrEqualTo(10); } @@ -85,7 +85,7 @@ public class EnableSchedulingTests { ctx = new AnnotationConfigApplicationContext(ExplicitSchedulerConfig.class); assertThat(ctx.getBean(ScheduledTaskHolder.class).getScheduledTasks()).hasSize(1); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThanOrEqualTo(10); assertThat(ctx.getBean(ExplicitSchedulerConfig.class).threadName).startsWith("explicitScheduler-"); assertThat(Arrays.asList(ctx.getDefaultListableBeanFactory().getDependentBeans("myTaskScheduler")).contains( @@ -104,7 +104,7 @@ public class EnableSchedulingTests { ctx = new AnnotationConfigApplicationContext(ExplicitScheduledTaskRegistrarConfig.class); assertThat(ctx.getBean(ScheduledTaskHolder.class).getScheduledTasks()).hasSize(1); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThanOrEqualTo(10); assertThat(ctx.getBean(ExplicitScheduledTaskRegistrarConfig.class).threadName).startsWith("explicitScheduler1"); } @@ -126,7 +126,7 @@ public class EnableSchedulingTests { ctx = new AnnotationConfigApplicationContext( SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedByScheduledTaskRegistrar.class); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread).startsWith("explicitScheduler2-"); } @@ -136,7 +136,7 @@ public class EnableSchedulingTests { ctx = new AnnotationConfigApplicationContext( SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask_disambiguatedBySchedulerNameAttribute.class); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread).startsWith("explicitScheduler2-"); } @@ -145,7 +145,7 @@ public class EnableSchedulingTests { public void withTaskAddedVia_configureTasks() throws InterruptedException { ctx = new AnnotationConfigApplicationContext(SchedulingEnabled_withTaskAddedVia_configureTasks.class); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(ThreadAwareWorker.class).executedByThread).startsWith("taskScheduler-"); } @@ -154,7 +154,7 @@ public class EnableSchedulingTests { public void withTriggerTask() throws InterruptedException { ctx = new AnnotationConfigApplicationContext(TriggerTaskConfig.class); - Thread.sleep(100); + Thread.sleep(110); assertThat(ctx.getBean(AtomicInteger.class).get()).isGreaterThan(1); } diff --git a/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java b/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java index 22ed99a2b9..ff215f0513 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/event/TransactionalEventListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,7 @@ import static org.springframework.transaction.event.TransactionPhase.BEFORE_COMM /** * Integration tests for {@link TransactionalEventListener} support + * with thread-bound transactions. * * @author Stephane Nicoll * @author Sam Brannen @@ -87,7 +88,6 @@ public class TransactionalEventListenerTests { getEventCollector().assertEvents(EventCollector.IMMEDIATELY, "test"); getEventCollector().assertTotalEventsCount(1); return null; - }); getEventCollector().assertEvents(EventCollector.IMMEDIATELY, "test"); getEventCollector().assertTotalEventsCount(1); @@ -115,7 +115,6 @@ public class TransactionalEventListenerTests { getContext().publishEvent("test"); getEventCollector().assertNoEventReceived(); return null; - }); getEventCollector().assertEvents(EventCollector.AFTER_COMPLETION, "test"); getEventCollector().assertTotalEventsCount(1); // After rollback not invoked @@ -129,7 +128,6 @@ public class TransactionalEventListenerTests { getEventCollector().assertNoEventReceived(); status.setRollbackOnly(); return null; - }); getEventCollector().assertEvents(EventCollector.AFTER_COMPLETION, "test"); getEventCollector().assertTotalEventsCount(1); // After rollback not invoked @@ -142,7 +140,6 @@ public class TransactionalEventListenerTests { getContext().publishEvent("test"); getEventCollector().assertNoEventReceived(); return null; - }); getEventCollector().assertEvents(EventCollector.AFTER_COMMIT, "test"); getEventCollector().assertTotalEventsCount(1); // After rollback not invoked @@ -307,13 +304,12 @@ public class TransactionalEventListenerTests { } @Test - public void afterCommitMetaAnnotation() throws Exception { + public void afterCommitMetaAnnotation() { load(AfterCommitMetaAnnotationTestListener.class); this.transactionTemplate.execute(status -> { getContext().publishEvent("test"); getEventCollector().assertNoEventReceived(); return null; - }); getEventCollector().assertEvents(EventCollector.AFTER_COMMIT, "test"); getEventCollector().assertTotalEventsCount(1); @@ -326,7 +322,6 @@ public class TransactionalEventListenerTests { getContext().publishEvent("SKIP"); getEventCollector().assertNoEventReceived(); return null; - }); getEventCollector().assertNoEventReceived(); }