com.netflix.ribbon.examples.rx.AbstractRxMovieClient.java Source code

Java tutorial

Introduction

Here is the source code for com.netflix.ribbon.examples.rx.AbstractRxMovieClient.java

Source

/*
 * Copyright 2014 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.netflix.ribbon.examples.rx;

import com.netflix.hystrix.util.HystrixTimer;
import com.netflix.ribbon.examples.rx.common.Movie;
import io.netty.buffer.ByteBuf;
import rx.Notification;
import rx.Observable;
import rx.functions.Func1;
import rx.functions.Func2;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;

import static java.lang.String.*;

/**
 * Base class for the transport/template and proxy examples. It orchestrates application flow, and
 * handles result(s) from the server. The request execution is implemented in the derived classes, in a way
 * specific for each API abstration. This separation of concerns makes it is easy to compare complexity of different APIs.
 *
 * @author Tomasz Bak
 */
public abstract class AbstractRxMovieClient {
    protected static final String TEST_USER = "user1";
    protected static final Pattern NEW_LINE_SPLIT_RE = Pattern.compile("\n");

    protected abstract Observable<ByteBuf>[] triggerMoviesRegistration();

    protected abstract Observable<ByteBuf>[] triggerRecommendationsUpdate();

    protected abstract Observable<ByteBuf>[] triggerRecommendationsSearch();

    protected Observable<ByteBuf> registerMovies() {
        return Observable.concat(Observable.from(triggerMoviesRegistration()));
    }

    protected Observable<ByteBuf> updateRecommendations() {
        return Observable.concat(Observable.from(triggerRecommendationsUpdate()));
    }

    protected Observable<Void> searchCatalog() {
        List<String> searches = new ArrayList<String>(2);
        Collections.addAll(searches, "findById", "findRawMovieById", "findMovie(name, category)");

        return Observable.concat(Observable.from(triggerRecommendationsSearch()))
                .flatMap(new Func1<ByteBuf, Observable<List<Movie>>>() {
                    @Override
                    public Observable<List<Movie>> call(ByteBuf byteBuf) {
                        List<Movie> movies = new ArrayList<Movie>();
                        String lines = byteBuf.toString(Charset.defaultCharset());
                        for (String line : NEW_LINE_SPLIT_RE.split(lines)) {
                            movies.add(Movie.from(line));
                        }
                        return Observable.just(movies);
                    }
                }).zipWith(searches, new Func2<List<Movie>, String, Void>() {
                    @Override
                    public Void call(List<Movie> movies, String query) {
                        System.out.println(format("    %s=%s", query, movies));
                        return null;
                    }
                });
    }

    public boolean runExample() {
        boolean allGood = true;
        try {
            System.out.println("Registering movies...");

            Notification<Void> result = executeServerCalls();
            allGood = !result.isOnError();
            if (allGood) {
                System.out.println("Application finished");
            } else {
                System.err.println("ERROR: execution failure");
                result.getThrowable().printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
            allGood = false;
        } finally {
            shutdown();
        }
        return allGood;
    }

    Notification<Void> executeServerCalls() {
        Observable<Void> resultObservable = registerMovies().materialize()
                .flatMap(new Func1<Notification<ByteBuf>, Observable<Void>>() {
                    @Override
                    public Observable<Void> call(Notification<ByteBuf> notif) {
                        if (!verifyStatus(notif)) {
                            return Observable.error(notif.getThrowable());
                        }
                        System.out.print("Updating user recommendations...");
                        return updateRecommendations().materialize()
                                .flatMap(new Func1<Notification<ByteBuf>, Observable<Void>>() {
                                    @Override
                                    public Observable<Void> call(Notification<ByteBuf> notif) {
                                        if (!verifyStatus(notif)) {
                                            return Observable.error(notif.getThrowable());
                                        }
                                        System.out.println("Searching through the movie catalog...");
                                        return searchCatalog();
                                    }
                                });
                    }
                });
        return resultObservable.materialize().toBlocking().last();
    }

    protected void shutdown() {
        HystrixTimer.reset();
    }

    private static boolean verifyStatus(Notification<ByteBuf> notif) {
        if (notif.isOnError()) {
            System.out.println("ERROR");
            return false;
        }
        System.out.println("DONE");
        return true;
    }
}