Notes on Spring responsive programming -- C2 basic concepts of Spring responsive programming

Posted by fatbobo on Thu, 14 Oct 2021 06:26:48 +0200


[good book sharing: Spring responsive programming -- JD]

2.2 practice of using RxJava responsive framework

RxJava library is the Java virtual machine implementation of Reactive Extensions, which is similar to the combination of observer mode, iterator mode and functional programming.

2.2.1 responsive flow = observer + iterator

Separate producers and consumers through events.

Iterator pattern: a scenario where the producer is not expected to produce data before the consumer appears.

public interface Iterator<T> {
    T next();
    boolean hasNext();
}

// Combined observer
public interface RxObserver<T> {
    void onNext(T next); // Notify new value
    void onComplete(); // End of notification
    void onError(Exception e); // Notification error
}

RxObserver is similar to the Observer in the Observer mode described earlier.

For subscribed content and subscribers, we can define Observale and Subcriber

  • Observable: similar to the Subject in the observer mode, it is an observable event source. It will emit elements, and there are flow conversion methods and flow initialization factory methods.
  • Subscriber: abstract class, which is used to implement the interface of Observer and consumer element, and is the basis of the implementation class

At the same time, we define subscription to control the runtime relationship between Observable and Subscriber. Subscription can check the subscription status and cancel the subscription if necessary.

The subscription contract between producer and consumer is as follows:

---------| — onNext —> | -----------
| Observable | – onComplete -> | Observer |
--------- | — onError —> |------------

According to the rules in RxJava, the Observable event source can send 0-N elements to indicate the end by declaring success and raising an error.

So the Observable event source calls onNext to the associated Subscriber many times, and finally calls onComplete or onError.

2.2.2 production and consumption flow data

Observable is regarded as an event generator, which will propagate events to subscribers during subscription.

Observable<String> observable = Obervable.create(
	new Observable.OnSubcribe<String>(){
    	@Override
        public void call(Subcriber<? super String> sub){
        	sub.onNext("Hello, reactive world!");
            sub.onCompleted();
        }
    }
);

// call() is triggered immediately when the subscriber appears
// lambda writing
Observable<String> observable = Obervable.create(
    sub -> {
        sub.onNext("Hello, reactive world!");
        sub.onCompleted();
    }
);

Observable is reusable, and each subscriber will receive this message event immediately after subscribing. Starting with RxJava 1.2.7, the creation of observable is discarded because it is unsafe because it may generate too many elements, resulting in excessive load on subscribers. That is, this method does not support back pressure.

The corresponding subscriber code is as follows:

Subcriber<String> subscriber = new Subcriber<String>(){
	@Override
    public void onNext(String s){
    	System.out.println("receive: " + s);
    }

    @Override
    public void onCompleted(){
        System.out.println("Done.");
    }

    @Override
    public void onError(Throwable e){
        System.err.println(e);
    }
}

So now the subscriber subcriber and the message source Observable can work together. Subcriber must implement the Observer observer method, define onNext to respond to new events, onCompleted to respond to flow completion, and onError to respond to errors.

Finally, just add a subscription relationship in Observable to complete the responsive demo program.

observable.subscribe(subcriber);
// output:
// receive: Hello, reactive world!
// Done.

// More simplified lambda writing
Observable<String> observable = Obervable.create(
    sub -> {
        sub.onNext("Hello, reactive world!");
        sub.onCompleted();
    }
);

observable.subscribe(
    s -> System.out.println("receive: " + s),
    () -> System.out.println("Done"),
    System.err::println;

);
// output:
// receive: Hello, reactive world!
// Done.

The Rxjava library is flexible for creating Observable instances of message sources.

Observable.just("1","2","3","4");
Observable.from(new String[]{"A", "B", "C", "D"});
Observable.from(Collections.emptyList());

Observale<String> msg1 = Observable.fromCallable(()->"hello-");
Future<String> future = Executors.newCachedThreadPool().submit(() -> "world");
Observale<String> msg2 = Observable.from(future); 

//Combine multiple streams in order of parameters
Observale<String> msg = Observable.concat(msg1, msg2, Observable.just("."));
msg.forEach(System.out::print);
// output: hello-world.

Although there is an onError signal to handle errors, it seems that there is no need to define a handler for exceptions, the default Subscriber implementation will still throw an rx.exceptions.OnErrorNotImplementedException when an error occurs

Topics: Java Spring reactor