diff --git a/reactor-core/build.gradle b/reactor-core/build.gradle index 78ea04252c..ff06e9f31b 100644 --- a/reactor-core/build.gradle +++ b/reactor-core/build.gradle @@ -162,7 +162,12 @@ task japicmp(type: JapicmpTask) { // TODO after a .0 release, bump the gradle.properties baseline // TODO after a .0 release, remove the reactor-core exclusions below if any classExcludes = [ ] - methodExcludes = [ 'reactor.core.publisher.Sinks$EmitFailureHandler#busyLooping(java.time.Duration)' ] + methodExcludes = [ + 'reactor.core.publisher.Sinks$EmitFailureHandler#busyLooping(java.time.Duration)', + 'reactor.core.publisher.FluxSink#contextView()', + 'reactor.core.publisher.MonoSink#contextView()', + 'reactor.core.publisher.SynchronousSink#contextView()' + ] } gradle.taskGraph.afterTask { task, state -> diff --git a/reactor-core/src/main/java/reactor/core/publisher/FluxSink.java b/reactor-core/src/main/java/reactor/core/publisher/FluxSink.java index ca70fcfe34..4d334eb28d 100644 --- a/reactor-core/src/main/java/reactor/core/publisher/FluxSink.java +++ b/reactor-core/src/main/java/reactor/core/publisher/FluxSink.java @@ -83,7 +83,9 @@ public interface FluxSink { * * @return the current subscriber {@link ContextView}. */ - ContextView contextView(); + default ContextView contextView() { + return currentContext(); + } /** diff --git a/reactor-core/src/main/java/reactor/core/publisher/MonoSink.java b/reactor-core/src/main/java/reactor/core/publisher/MonoSink.java index 40360bd5ea..ea4f1e12d4 100644 --- a/reactor-core/src/main/java/reactor/core/publisher/MonoSink.java +++ b/reactor-core/src/main/java/reactor/core/publisher/MonoSink.java @@ -83,7 +83,9 @@ public interface MonoSink { * * @return the current subscriber {@link ContextView}. */ - ContextView contextView(); + default ContextView contextView() { + return this.currentContext(); + } /** * Attaches a {@link LongConsumer} to this {@link MonoSink} that will be notified of diff --git a/reactor-core/src/main/java/reactor/core/publisher/SynchronousSink.java b/reactor-core/src/main/java/reactor/core/publisher/SynchronousSink.java index b25f0f52fb..702800dabe 100644 --- a/reactor-core/src/main/java/reactor/core/publisher/SynchronousSink.java +++ b/reactor-core/src/main/java/reactor/core/publisher/SynchronousSink.java @@ -65,7 +65,9 @@ public interface SynchronousSink { * * @return the current subscriber {@link ContextView}. */ - ContextView contextView(); + default ContextView contextView() { + return currentContext(); + } /** * @param e the exception to signal, not null diff --git a/reactor-core/src/test/java/reactor/core/CurrentContextArchTest.java b/reactor-core/src/test/java/reactor/core/ContextBestPracticesArchTest.java similarity index 73% rename from reactor-core/src/test/java/reactor/core/CurrentContextArchTest.java rename to reactor-core/src/test/java/reactor/core/ContextBestPracticesArchTest.java index 9f94677c80..8cc11c93f1 100644 --- a/reactor-core/src/test/java/reactor/core/CurrentContextArchTest.java +++ b/reactor-core/src/test/java/reactor/core/ContextBestPracticesArchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021 VMware Inc. or its affiliates, All Rights Reserved. + * Copyright (c) 2019-2022 VMware Inc. or its affiliates, All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,10 +27,15 @@ import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; +import reactor.core.publisher.FluxSink; +import reactor.core.publisher.MonoSink; +import reactor.core.publisher.SynchronousSink; + import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; import static org.assertj.core.api.Assertions.assertThat; -public class CurrentContextArchTest { +class ContextBestPracticesArchTest { static JavaClasses CORE_SUBSCRIBER_CLASSES = new ClassFileImporter() .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) @@ -50,7 +55,7 @@ void smokeTestWhereClassesLoaded() { } @Test - public void corePublishersShouldNotUseDefaultCurrentContext() { + void corePublishersShouldNotUseDefaultCurrentContext() { classes() .that().implement(CoreSubscriber.class) .and().doNotHaveModifier(JavaModifier.ABSTRACT) @@ -78,7 +83,7 @@ public void check(JavaClass item, ConditionEvents events) { @Test // This is ok as this class tests the deprecated FluxProcessor. Will be removed with it in 3.5. @SuppressWarnings("deprecation") - public void fluxProcessorsShouldNotUseDefaultCurrentContext() { + void fluxProcessorsShouldNotUseDefaultCurrentContext() { classes() .that().areAssignableTo(reactor.core.publisher.FluxProcessor.class) .and().doNotHaveModifier(JavaModifier.ABSTRACT) @@ -105,4 +110,35 @@ public void check(JavaClass item, ConditionEvents events) { }) .check(FLUXPROCESSOR_CLASSES); } + + @Test + void oldSinksShouldNotUseDefaultCurrentContext() { + classes() + .that().implement(SynchronousSink.class) + .or().implement(FluxSink.class) + .or().implement(MonoSink.class) + .and().doNotHaveModifier(JavaModifier.ABSTRACT) + .should(new ArchCondition("not use the default contextView()") { + @Override + public void check(JavaClass item, ConditionEvents events) { + boolean overridesMethod = item + .getAllMethods() + .stream() + .filter(it -> "contextView".equals(it.getName())) + .filter(it -> it.getRawParameterTypes().isEmpty()) + .anyMatch(it -> !it.getOwner().isEquivalentTo(SynchronousSink.class) + && !it.getOwner().isEquivalentTo(FluxSink.class) + && !it.getOwner().isEquivalentTo(MonoSink.class) + ); + + if (!overridesMethod) { + events.add(SimpleConditionEvent.violated( + item, + item.getFullName() + item.getSourceCodeLocation() + ": contextView() is not overridden" + )); + } + } + }) + .check(CORE_SUBSCRIBER_CLASSES); + } }