/*
* 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.transport;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.IClientConfig;
import com.netflix.ribbon.transport.netty.RibbonTransport;
import com.netflix.ribbon.transport.netty.http.LoadBalancingHttpClient;
import com.netflix.ribbon.examples.rx.AbstractRxMovieClient;
import com.netflix.ribbon.examples.rx.RxMovieServer;
import com.netflix.ribbon.examples.rx.common.Movie;
import com.netflix.ribbon.examples.rx.common.RxMovieTransformer;
import io.netty.buffer.ByteBuf;
import io.reactivex.netty.channel.StringTransformer;
import io.reactivex.netty.protocol.http.client.HttpClientRequest;
import io.reactivex.netty.protocol.http.client.HttpClientResponse;
import rx.Observable;
import rx.functions.Func1;
import static java.lang.String.*;
/**
* Run {@link com.netflix.ribbon.examples.rx.RxMovieServer} prior to runnng this example!
*
* @author Tomasz Bak
*/
public class RxMovieTransportExample extends AbstractRxMovieClient {
private final LoadBalancingHttpClient<ByteBuf, ByteBuf> client;
public RxMovieTransportExample(int port) {
IClientConfig clientConfig = IClientConfig.Builder.newBuilder("movieServiceClient").build();
clientConfig.set(CommonClientConfigKey.ListOfServers, "localhost:" + port);
client = RibbonTransport.newHttpClient(clientConfig);
}
@SuppressWarnings("unchecked")
@Override
protected Observable<ByteBuf>[] triggerMoviesRegistration() {
return new Observable[]{
registerMovie(Movie.ORANGE_IS_THE_NEW_BLACK),
registerMovie(Movie.BREAKING_BAD),
registerMovie(Movie.HOUSE_OF_CARDS)
};
}
private Observable<Void> registerMovie(Movie movie) {
HttpClientRequest<ByteBuf> httpRequest = HttpClientRequest.createPost("/movies")
.withHeader("X-Platform-Version", "xyz")
.withHeader("X-Auth-Token", "abc")
.withRawContentSource(Observable.just(movie), new RxMovieTransformer());
return client.submit(httpRequest).flatMap(new Func1<HttpClientResponse<ByteBuf>, Observable<Void>>() {
@Override
public Observable<Void> call(HttpClientResponse<ByteBuf> httpClientResponse) {
if (httpClientResponse.getStatus().code() / 100 != 2) {
return Observable.error(new RuntimeException(
format("HTTP request failed (status code=%s)", httpClientResponse.getStatus())));
}
return Observable.empty();
}
});
}
@SuppressWarnings("unchecked")
@Override
protected Observable<ByteBuf>[] triggerRecommendationsUpdate() {
return new Observable[]{
updateRecommendation(TEST_USER, Movie.ORANGE_IS_THE_NEW_BLACK),
updateRecommendation(TEST_USER, Movie.BREAKING_BAD)
};
}
private Observable<Void> updateRecommendation(String user, Movie movie) {
HttpClientRequest<ByteBuf> httpRequest = HttpClientRequest.createPost(format("/users/%s/recommendations", user))
.withHeader("X-Platform-Version", "xyz")
.withHeader("X-Auth-Token", "abc")
.withRawContentSource(Observable.just(movie.getId()), new StringTransformer());
return client.submit(httpRequest).flatMap(new Func1<HttpClientResponse<ByteBuf>, Observable<Void>>() {
@Override
public Observable<Void> call(HttpClientResponse<ByteBuf> httpClientResponse) {
if (httpClientResponse.getStatus().code() / 100 != 2) {
return Observable.error(new RuntimeException(
format("HTTP request failed (status code=%s)", httpClientResponse.getStatus())));
}
return Observable.empty();
}
});
}
@SuppressWarnings("unchecked")
@Override
protected Observable<ByteBuf>[] triggerRecommendationsSearch() {
HttpClientRequest<ByteBuf> httpRequest = HttpClientRequest.createGet(format("/users/%s/recommendations", TEST_USER))
.withHeader("X-Platform-Version", "xyz")
.withHeader("X-Auth-Token", "abc");
Observable<ByteBuf> searchByUserObservable = client.submit(httpRequest).flatMap(new Func1<HttpClientResponse<ByteBuf>, Observable<ByteBuf>>() {
@Override
public Observable<ByteBuf> call(HttpClientResponse<ByteBuf> httpClientResponse) {
if (httpClientResponse.getStatus().code() / 100 != 2) {
return Observable.error(new RuntimeException(
format("HTTP request failed (status code=%s)", httpClientResponse.getStatus())));
}
return httpClientResponse.getContent();
}
});
httpRequest = HttpClientRequest.createGet("/recommendations?category=Drama&ageGroup=Adults")
.withHeader("X-Platform-Version", "xyz")
.withHeader("X-Auth-Token", "abc");
Observable<ByteBuf> searchByCriteriaObservable = client.submit(httpRequest).flatMap(new Func1<HttpClientResponse<ByteBuf>, Observable<ByteBuf>>() {
@Override
public Observable<ByteBuf> call(HttpClientResponse<ByteBuf> httpClientResponse) {
if (httpClientResponse.getStatus().code() / 100 != 2) {
return Observable.error(new RuntimeException(
format("HTTP request failed (status code=%s)", httpClientResponse.getStatus())));
}
return httpClientResponse.getContent();
}
});
return new Observable[]{searchByUserObservable, searchByCriteriaObservable};
}
public static void main(String[] args) {
System.out.println("Starting transport based movie service...");
new RxMovieTransportExample(RxMovieServer.DEFAULT_PORT).runExample();
}
}