parent
8a2acbeac1
commit
2b750926c3
|
@ -358,14 +358,14 @@ By default, event publication and processing is done synchronously and on the sa
|
|||
This means that during the execution of that task, the ThreadLocals and logging context will be the same as the event publisher.
|
||||
|
||||
If the application configures globally a custom `ApplicationEventMulticaster` with a strategy that schedules event processing on different threads, this is no longer true.
|
||||
All `@EventListener` methods will be processed on a different thread, outstide of the main event publication thread.
|
||||
All `@EventListener` methods will be processed on a different thread, outside of the main event publication thread.
|
||||
In these cases, the https://micrometer.io/docs/contextPropagation[Micrometer Context Propagation library] can help propagating such values and better correlate the processing of the events.
|
||||
The application can configure the chosen `TaskExecutor` to use a `ContextPropagatingTaskDecorator` that decorates tasks and propagates context.
|
||||
For this to work, the `io.micrometer:context-propagation` library must be present on the classpath:
|
||||
|
||||
include-code::./ApplicationEventsConfiguration[]
|
||||
|
||||
Similarly, if that asynchronous choice is made locally for each `@EventListener` annotated method, by adding an `@Async` method to it,
|
||||
Similarly, if that asynchronous choice is made locally for each `@EventListener` annotated method, by adding an `@Async` to it,
|
||||
you can choose a `TaskExecutor` that propagates context by referring to it by its qualifier.
|
||||
Given the following `TaskExecutor` bean definition, configured with the dedicated task decorator:
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ For example, declaring `List<Foo>` in Kotlin is conceptually equivalent to `java
|
|||
`kotlin.collections.List` is declared as
|
||||
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/[`interface List<out E> : kotlin.collections.Collection<E>`].
|
||||
|
||||
This needs to be taken in account by using the `out` Kotlin keyword on generic types when using Java classes,
|
||||
This needs to be taken into account by using the `out` Kotlin keyword on generic types when using Java classes,
|
||||
for example when writing a `org.springframework.core.convert.converter.Converter` from a Kotlin type to a Java type.
|
||||
|
||||
[source,kotlin,indent=0]
|
||||
|
|
|
@ -287,7 +287,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
|||
assertThat(actual.getPropertyValues().get("spring")).isEqualTo("framework");
|
||||
});
|
||||
assertHasMethodInvokeHints(PropertyValuesBean.class, "setTest", "setSpring");
|
||||
assertHasDecalredFieldsHint(PropertyValuesBean.class);
|
||||
assertHasDeclaredFieldsHint(PropertyValuesBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -300,8 +300,8 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
|||
assertThat(actual.getPropertyValues().get("spring")).isEqualTo("framework");
|
||||
});
|
||||
assertHasMethodInvokeHints(PropertyValuesBean.class, "setTest", "setSpring");
|
||||
assertHasDecalredFieldsHint(ExtendedPropertyValuesBean.class);
|
||||
assertHasDecalredFieldsHint(PropertyValuesBean.class);
|
||||
assertHasDeclaredFieldsHint(ExtendedPropertyValuesBean.class);
|
||||
assertHasDeclaredFieldsHint(PropertyValuesBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -362,7 +362,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
|||
assertThat(actual.getPropertyValues().get("name")).isEqualTo("World");
|
||||
});
|
||||
assertHasMethodInvokeHints(PropertyValuesFactoryBean.class, "setPrefix", "setName" );
|
||||
assertHasDecalredFieldsHint(PropertyValuesFactoryBean.class);
|
||||
assertHasDeclaredFieldsHint(PropertyValuesFactoryBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -516,7 +516,7 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
|||
.test(this.generationContext.getRuntimeHints()));
|
||||
}
|
||||
|
||||
private void assertHasDecalredFieldsHint(Class<?> beanType) {
|
||||
private void assertHasDeclaredFieldsHint(Class<?> beanType) {
|
||||
assertThat(RuntimeHintsPredicates.reflection()
|
||||
.onType(beanType).withMemberCategory(MemberCategory.DECLARED_FIELDS))
|
||||
.accepts(this.generationContext.getRuntimeHints());
|
||||
|
|
|
@ -511,7 +511,7 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
|
|||
logger.warn("Cannot enhance @Configuration bean definition '" + beanName +
|
||||
"' since its singleton instance has been created too early. The typical cause " +
|
||||
"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +
|
||||
"return type: Consider declaring such methods as 'static' and/or mark the " +
|
||||
"return type: Consider declaring such methods as 'static' and/or marking the " +
|
||||
"containing configuration class as 'proxyBeanMethods=false'.");
|
||||
}
|
||||
configBeanDefs.put(beanName, abd);
|
||||
|
|
|
@ -240,7 +240,7 @@ public class MethodValidationInterceptor implements MethodInterceptor {
|
|||
ReactiveAdapterRegistry.getSharedInstance();
|
||||
|
||||
|
||||
public static Object[] insertAsyncValidation(
|
||||
static Object[] insertAsyncValidation(
|
||||
Supplier<SpringValidatorAdapter> validatorAdapterSupplier, boolean adaptViolations,
|
||||
Object target, Method method, Object[] arguments) {
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ class InstantFormatterTests {
|
|||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(RandomEpochMillisProvider.class)
|
||||
void should_parse_into_an_Instant_from_epoch_mili(Instant input) throws ParseException {
|
||||
void should_parse_into_an_Instant_from_epoch_milli(Instant input) throws ParseException {
|
||||
Instant expected = input;
|
||||
|
||||
Instant actual = instantFormatter.parse(Long.toString(input.toEpochMilli()), null);
|
||||
|
|
|
@ -44,7 +44,7 @@ class FormattingConversionServiceRuntimeHintsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void montearyAmountHasHints() {
|
||||
void monetaryAmountHasHints() {
|
||||
assertThat(RuntimeHintsPredicates.reflection().onType(javax.money.MonetaryAmount.class)).accepts(this.hints);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,9 +36,11 @@ import org.springframework.validation.method.ParameterErrors;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for method validation proxy with reactor.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class MethodValidationProxyReactorTests {
|
||||
class MethodValidationProxyReactorTests {
|
||||
|
||||
@Test
|
||||
void validMonoArgument() {
|
||||
|
|
|
@ -62,7 +62,7 @@ public class CompositePropertySourceBenchmark {
|
|||
CompositePropertySource composite;
|
||||
|
||||
@Param({ "2", "5", "10" })
|
||||
int numberOfPropertySource;
|
||||
int numberOfPropertySources;
|
||||
|
||||
@Param({ "10", "100", "1000" })
|
||||
int numberOfPropertyNamesPerSource;
|
||||
|
@ -70,7 +70,7 @@ public class CompositePropertySourceBenchmark {
|
|||
@Setup(Level.Trial)
|
||||
public void setUp() {
|
||||
this.composite = new CompositePropertySource("benchmark");
|
||||
for (int i = 0; i < this.numberOfPropertySource; i++) {
|
||||
for (int i = 0; i < this.numberOfPropertySources; i++) {
|
||||
Map<String, Object> map = new HashMap<>(this.numberOfPropertyNamesPerSource);
|
||||
for (int j = 0; j < this.numberOfPropertyNamesPerSource; j++) {
|
||||
map.put(ID_GENERATOR.generateId().toString(), VALUE);
|
||||
|
|
|
@ -54,7 +54,7 @@ final class OutputStreamPublisher implements Publisher<DataBuffer> {
|
|||
private final int chunkSize;
|
||||
|
||||
|
||||
public OutputStreamPublisher(Consumer<OutputStream> outputStreamConsumer, DataBufferFactory bufferFactory,
|
||||
OutputStreamPublisher(Consumer<OutputStream> outputStreamConsumer, DataBufferFactory bufferFactory,
|
||||
Executor executor, int chunkSize) {
|
||||
|
||||
this.outputStreamConsumer = outputStreamConsumer;
|
||||
|
@ -99,7 +99,7 @@ final class OutputStreamPublisher implements Publisher<DataBuffer> {
|
|||
private long produced;
|
||||
|
||||
|
||||
public OutputStreamSubscription(Subscriber<? super DataBuffer> actual,
|
||||
OutputStreamSubscription(Subscriber<? super DataBuffer> actual,
|
||||
Consumer<OutputStream> outputStreamConsumer, DataBufferFactory bufferFactory, int chunkSize) {
|
||||
|
||||
this.actual = actual;
|
||||
|
|
|
@ -22,7 +22,7 @@ import io.micrometer.context.ContextSnapshotFactory;
|
|||
import org.springframework.core.task.TaskDecorator;
|
||||
|
||||
/**
|
||||
* {@link TaskDecorator} that {@link ContextSnapshot#wrap(Runnable) wrap the execution} of
|
||||
* {@link TaskDecorator} that {@link ContextSnapshot#wrap(Runnable) wraps the execution} of
|
||||
* tasks, assisting with context propagation.
|
||||
* <p>This operation is only useful when the task execution is scheduled on a different
|
||||
* thread than the original call stack; this depends on the choice of
|
||||
|
|
|
@ -49,7 +49,7 @@ public class SingletonSupplier<T> implements Supplier<T> {
|
|||
private volatile T singletonInstance;
|
||||
|
||||
/**
|
||||
* Guards access to write operations on the response.
|
||||
* Guards access to write operations on the {@code singletonInstance} field.
|
||||
*/
|
||||
private final Lock writeLock = new ReentrantLock();
|
||||
|
||||
|
|
|
@ -52,15 +52,15 @@ class ContextPropagatingTaskDecoratorTests {
|
|||
|
||||
private static final ThreadLocal<String> holder = new ThreadLocal<>();
|
||||
|
||||
public static void setValue(String value) {
|
||||
static void setValue(String value) {
|
||||
holder.set(value);
|
||||
}
|
||||
|
||||
public static String getValue() {
|
||||
static String getValue() {
|
||||
return holder.get();
|
||||
}
|
||||
|
||||
public static void reset() {
|
||||
static void reset() {
|
||||
holder.remove();
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ class ContextPropagatingTaskDecoratorTests {
|
|||
|
||||
static class TestThreadLocalAccessor implements ThreadLocalAccessor<String> {
|
||||
|
||||
public static final String KEY = "test.threadlocal";
|
||||
static final String KEY = "test.threadlocal";
|
||||
|
||||
@Override
|
||||
public Object key() {
|
||||
|
|
|
@ -716,7 +716,7 @@ public class DefaultPersistenceUnitManager
|
|||
*/
|
||||
private static class BeanValidationDelegate {
|
||||
|
||||
public static boolean isValidationProviderPresent() {
|
||||
static boolean isValidationProviderPresent() {
|
||||
try {
|
||||
Validation.byDefaultProvider().configure();
|
||||
return true;
|
||||
|
|
|
@ -115,7 +115,7 @@ public class ServerHttpObservationFilter implements WebFilter {
|
|||
|
||||
private final AtomicBoolean observationRecorded = new AtomicBoolean();
|
||||
|
||||
public ObservationSignalListener(ServerRequestObservationContext observationContext) {
|
||||
ObservationSignalListener(ServerRequestObservationContext observationContext) {
|
||||
this.observationContext = observationContext;
|
||||
this.observation = ServerHttpObservationDocumentation.HTTP_REACTIVE_SERVER_REQUESTS.observation(observationConvention,
|
||||
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry);
|
||||
|
|
|
@ -367,7 +367,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
|
|||
|
||||
private final AtomicBoolean observationRecorded = new AtomicBoolean();
|
||||
|
||||
public ObservationSignalListener(ServerRequestObservationContext observationContext) {
|
||||
ObservationSignalListener(ServerRequestObservationContext observationContext) {
|
||||
this.observationContext = observationContext;
|
||||
this.observation = ServerHttpObservationDocumentation.HTTP_REACTIVE_SERVER_REQUESTS.observation(observationConvention,
|
||||
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry);
|
||||
|
|
|
@ -28,7 +28,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
/**
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
public class ReactorClientHttpConnectorTests {
|
||||
class ReactorClientHttpConnectorTests {
|
||||
|
||||
@Test
|
||||
void restartWithDefaultConstructor() {
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.springframework.web.server.ServerWebExchange;
|
|||
* from asynchronous return values, and to response rendering.
|
||||
* <li>Implemented by a {@link HandlerAdapter} in order to handle exceptions that
|
||||
* occur before a request is mapped to a handler, or for unhandled errors from a
|
||||
* handler..
|
||||
* handler.
|
||||
* </ul>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
|
|
|
@ -628,7 +628,7 @@ class CoRouterFunctionDsl internal constructor (private val init: (CoRouterFunct
|
|||
*/
|
||||
fun context(provider: suspend (ServerRequest) -> CoroutineContext) {
|
||||
if (this.contextProvider != null) {
|
||||
throw IllegalStateException("The Coroutine context provider should be defined not more than once")
|
||||
throw IllegalStateException("The Coroutine context provider should not be defined more than once")
|
||||
}
|
||||
this.contextProvider = provider
|
||||
}
|
||||
|
|
|
@ -1049,7 +1049,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
|||
|
||||
private static boolean taskExecutorWarning = true;
|
||||
|
||||
public MvcSimpleAsyncTaskExecutor() {
|
||||
MvcSimpleAsyncTaskExecutor() {
|
||||
super("MvcAsync");
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue