Can a Subscriber act as a Publisher?

核能气质少年 提交于 2019-12-08 08:47:19

问题


In terms of Reactive Streams, there is a Publisher and it could have as many Subscribers.

But suppose, a subscriber gets a message from Publisher. Now this Subscriber(say Subs1) changes/modifies the message and passes it to some other Subscriber(say Subs2), which consumes the modified message.

So can this Subs1 subscriber can act as a Publisher which can pass on message to new Subs2 subscriber?

I am not sure if it possible or not, but the scenario is possible i think.

If its possible, please suggest a possible way to do this.


回答1:


If we want to transform incoming message and pass it further to the next Subscriber, we need to implement the Processor interface. This acts both as a Subscriber because it receives messages, and as the Publisher because it processes those messages and sends them for further processing.

Here is the complete implementation to do this:

  1. Create a MyTransformer class which implements Processor and extends SubmissionPublisher, as it will act both as Subscriber and Publisher:

    import java.util.concurrent.Flow;
    import java.util.concurrent.Flow.Subscription;
    import java.util.concurrent.SubmissionPublisher;
    import java.util.function.Function;
    
    public class MyTransformer<T, R> extends SubmissionPublisher<R> implements Flow.Processor<T, R> {
    
    private Function<T, R> function;
    private Flow.Subscription subscription;
    
    public MyTransformer(Function<T, R> function) {
        super();
        this.function = function;
    }
    
    @Override
    public void onComplete() {
        System.out.println("Transformer Completed");
    }
    
    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
    }
    
    @Override
    public void onNext(T item) {
        System.out.println("Transformer Got : "+item);
        submit(function.apply(item));
        subscription.request(1);
    
    }
    
    @Override
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }
    
    
    
    }
    
  2. Create an TestSubscriber class which implements the Subscriber interface and implement the required methods:

The onSubscribe() method is called before processing starts. The instance of the Subscription is passed as the argument. It is a class that is used to control the flow of messages between Subscriber and the Publisher.

The main method here is onNext() – this is called whenever the Publisher publishes a new message.

We are using the SubmissionPublisher class which implements the Publisher interface.

We’re going to be submitting N elements to the Publisher – which our TestSubscriber will be receiving.

Note, that we’re calling the close() method on the instance of the TestSubscriber. It will invoke onComplete() callback underneath on every Subscriber of the given Publisher.

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Flow.Subscriber;
import java.util.concurrent.Flow.Subscription;

public class TestSubscriber<T> implements Subscriber<T> {

    private Subscription subscription;

    public List<T> consumed = new LinkedList<>();

    @Override
    public void onComplete() {
        System.out.println("Subsciber Completed");
    }

    @Override
    public void onError(Throwable arg0) {
        arg0.printStackTrace();
    }

    @Override
    public void onNext(T item) {
        System.out.println("In Subscriber Got : "+item);
        subscription.request(1);

    }

    @Override
    public void onSubscribe(Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }

}
  1. Here is processing flow in which the Publisher is publishing String elements.

MyTransformer is parsing the String as Integer – which means a conversion needs to happening here.

import java.util.List;
import java.util.concurrent.SubmissionPublisher;;

public class TestTransformer {

    public static void main(String... args) {
        SubmissionPublisher<String> publisher = new SubmissionPublisher<>();
        MyTransformer<String, Integer> transformProcessor = new MyTransformer<>(Integer::parseInt);

        TestSubscriber<Integer> subscriber = new TestSubscriber<>();
        List<String> items = List.of("1", "2", "3");

        List<Integer> expectedResult = List.of(1, 2, 3);

        publisher.subscribe(transformProcessor);
        transformProcessor.subscribe(subscriber);
        items.forEach(publisher::submit);
        publisher.close();

    }
}


来源:https://stackoverflow.com/questions/47936868/can-a-subscriber-act-as-a-publisher

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!