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;
                }
            });
    }
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
ribbon-examples/src/main/java/com/netflix/ribbon/examples/rx/AbstractRxMovieClient.java