Subscribe to Publisher in the NullChannel (#3448)

* Subscribe to Publisher in the NullChannel

If a payload of the message in the flow is a `org.reactivestreams.Publisher`,
it must be subscribed somewhere downstream to initiate reactive processing.
The `NullChannel` just ignores the message altogether and therefore `Publisher`
is lost

* Check the payload of the message in the `NullChannel` for `Publisher` type
and subscribe to it
* Verify in the test and mention this logic in the docs

**Cherry-pick to 5.4.x**

* Apply suggestions from code review

Co-authored-by: Gary Russell <grussell@vmware.com>

Co-authored-by: Gary Russell <grussell@vmware.com>
This commit is contained in:
Artem Bilan
2020-12-22 12:20:12 -05:00
committed by GitHub
parent ad57c6187a
commit c38da2f4ee
3 changed files with 50 additions and 5 deletions

View File

@@ -20,6 +20,9 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.integration.IntegrationPattern;
@@ -35,13 +38,16 @@ import org.springframework.messaging.PollableChannel;
/**
* A channel implementation that essentially behaves like "/dev/null".
* All receive() calls will return <em>null</em>, and all send() calls
* will return <em>true</em> although no action is performed.
* All {@link #receive()} calls will return {@code null},
* and all {@link #send} calls will return {@code true} although no action is performed.
* Unless the payload of a sent message is a {@link Publisher} implementation, in
* which case the {@link Publisher#subscribe(Subscriber)} is called to initiate
* the reactive stream, although the data is discarded by this channel.
* Note however that the invocations are logged at debug-level.
*
* @author Mark Fisher
* @author Gary Russell
* @author Artyem Bilan
* @author Artem Bilan
*/
@IntegrationManagedResource
public class NullChannel implements PollableChannel,
@@ -119,6 +125,31 @@ public class NullChannel implements PollableChannel,
if (this.loggingEnabled && this.logger.isDebugEnabled()) {
this.logger.debug("message sent to null channel: " + message);
}
Object payload = message.getPayload();
if (payload instanceof Publisher<?>) {
((Publisher<?>) payload).subscribe(
new Subscriber<Object>() {
@Override public void onSubscribe(Subscription subscription) {
subscription.request(Long.MAX_VALUE);
}
@Override public void onNext(Object o) {
}
@Override public void onError(Throwable t) {
}
@Override public void onComplete() {
}
});
}
if (this.metricsCaptor != null) {
sendTimer().record(0, TimeUnit.MILLISECONDS);
}