io.wcm.caravan.pipeline.impl.operators.ResponseHandlingOperator.java Source code

Java tutorial

Introduction

Here is the source code for io.wcm.caravan.pipeline.impl.operators.ResponseHandlingOperator.java

Source

/*
 * #%L
 * wcm.io
 * %%
 * Copyright (C) 2014 wcm.io
 * %%
 * 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.
 * #L%
 */
package io.wcm.caravan.pipeline.impl.operators;

import io.wcm.caravan.io.http.CaravanHttpClient;
import io.wcm.caravan.io.http.IllegalResponseRuntimeException;
import io.wcm.caravan.io.http.request.CaravanHttpRequest;
import io.wcm.caravan.io.http.response.Body;
import io.wcm.caravan.io.http.response.CaravanHttpResponse;
import io.wcm.caravan.pipeline.JsonPipelineInputException;
import io.wcm.caravan.pipeline.JsonPipelineOutput;
import io.wcm.caravan.pipeline.impl.JacksonFunctions;
import io.wcm.caravan.pipeline.impl.JsonPipelineOutputImpl;

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Response;

import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import rx.Observable.Operator;
import rx.Subscriber;
import rx.exceptions.Exceptions;

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableList;

/**
 * Operator that converts {@link Response} emissions from the {@link CaravanHttpClient} layer into {@link JsonPipelineOutput} objects. All recoverable
 * exceptions are wrapped in a {@link JsonPipelineInputException} before they are forwarded to the subscriber's onNext method
 */
public class ResponseHandlingOperator implements Operator<JsonPipelineOutput, CaravanHttpResponse> {

    private static final Logger log = LoggerFactory.getLogger(ResponseHandlingOperator.class);

    private final CaravanHttpRequest request;

    /**
     * @param request the URL of the outgoing request
     */
    public ResponseHandlingOperator(CaravanHttpRequest request) {
        this.request = request;
    }

    @Override
    public Subscriber<? super CaravanHttpResponse> call(Subscriber<? super JsonPipelineOutput> subscriber) {
        return new Subscriber<CaravanHttpResponse>() {

            @Override
            public void onCompleted() {
                subscriber.onCompleted();
            }

            @Override
            public void onError(Throwable e) {
                Exceptions.throwIfFatal(e);

                int statusCode = 500;
                if (e instanceof IllegalResponseRuntimeException) {
                    statusCode = ((IllegalResponseRuntimeException) e).getResponseStatusCode();
                }

                JsonPipelineInputException jsonPipelineInputException = new JsonPipelineInputException(statusCode,
                        "Failed to GET " + request.getUrl(), e).setReason(e.getMessage());
                subscriber.onError(jsonPipelineInputException);
            }

            @Override
            public void onNext(CaravanHttpResponse response) {
                try (Body body = response.body()) {
                    final int statusCode = response.status();
                    log.debug("received {} response ({}) with from {},\n{}", statusCode, response.reason(),
                            request.getUrl(), request.getCorrelationId());
                    if (statusCode == HttpServletResponse.SC_OK) {

                        JsonNode payload = JacksonFunctions.stringToNode(body.asString());
                        int maxAge = NumberUtils.toInt(response.getCacheControl().get("max-age"), -1);
                        JsonPipelineOutput model = new JsonPipelineOutputImpl(payload, ImmutableList.of(request))
                                .withMaxAge(maxAge);

                        subscriber.onNext(model);
                    } else {
                        String msg = "Request for " + request.getUrl() + " failed with HTTP status code: "
                                + statusCode + " (" + response.reason() + ")" + ", " + request.getCorrelationId();

                        if (statusCode / 100 == 4) {
                            log.info(msg);
                        } else {
                            log.warn(msg);
                        }

                        JsonPipelineInputException pipelineInputException = new JsonPipelineInputException(
                                statusCode, msg).setReason(response.reason());
                        subscriber.onError(pipelineInputException);
                    }
                } catch (IOException ex) {
                    JsonPipelineInputException pipelineInputException = new JsonPipelineInputException(500,
                            "Failed to read JSON response from " + request.getUrl(), ex)
                                    .setReason(response.reason());
                    subscriber.onError(pipelineInputException);
                }
            }
        };
    }
}