HandleExceptionOperator.java

  1. /*
  2.  * #%L
  3.  * wcm.io
  4.  * %%
  5.  * Copyright (C) 2014 wcm.io
  6.  * %%
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *      http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  * #L%
  19.  */
  20. package io.wcm.caravan.pipeline.impl.operators;

  21. import io.wcm.caravan.io.http.IllegalResponseRuntimeException;
  22. import io.wcm.caravan.io.http.request.CaravanHttpRequest;
  23. import io.wcm.caravan.pipeline.JsonPipelineExceptionHandler;
  24. import io.wcm.caravan.pipeline.JsonPipelineInputException;
  25. import io.wcm.caravan.pipeline.JsonPipelineOutput;
  26. import io.wcm.caravan.pipeline.impl.JacksonFunctions;
  27. import io.wcm.caravan.pipeline.impl.JsonPipelineOutputImpl;

  28. import java.util.List;

  29. import rx.Observable;
  30. import rx.Observable.Operator;
  31. import rx.Subscriber;
  32. import rx.exceptions.Exceptions;

  33. /**
  34.  * An operator that delegates all non-fatal exception-handling to the given function, allowing the user of the
  35.  * pipeline to specify fallback content for certain expected exception scenarios.
  36.  */
  37. public class HandleExceptionOperator implements Operator<JsonPipelineOutput, JsonPipelineOutput> {

  38.   private final List<CaravanHttpRequest> requests;
  39.   private final JsonPipelineExceptionHandler handler;

  40.   /**
  41.    * @param requests the outgoing REST request(s)
  42.    * @param handler the function to call when an exception is caught
  43.    */
  44.   public HandleExceptionOperator(List<CaravanHttpRequest> requests, JsonPipelineExceptionHandler handler) {
  45.     this.requests = requests;
  46.     this.handler = handler;
  47.   }

  48.   @Override
  49.   public Subscriber<? super JsonPipelineOutput> call(Subscriber<? super JsonPipelineOutput> subscriber) {
  50.     return new Subscriber<JsonPipelineOutput>() {

  51.       @Override
  52.       public void onCompleted() {
  53.         subscriber.onCompleted();
  54.       }

  55.       @Override
  56.       public void onError(Throwable e) {

  57.         Exceptions.throwIfFatal(e);

  58.         // extract the HTTP status code from the exceptions known to contain such information
  59.         int statusCode = 500;
  60.         if (e instanceof JsonPipelineInputException) {
  61.           statusCode = ((JsonPipelineInputException)e).getStatusCode();
  62.         }
  63.         if (e instanceof IllegalResponseRuntimeException) {
  64.           statusCode = ((IllegalResponseRuntimeException)e).getResponseStatusCode();
  65.         }

  66.         JsonPipelineOutput defaultFallbackContent = new JsonPipelineOutputImpl(JacksonFunctions.emptyObject(), requests)
  67.             .withStatusCode(statusCode)
  68.             .withMaxAge(0);

  69.         try {
  70.           Observable<JsonPipelineOutput> fallbackResponse = handler.call(defaultFallbackContent, (RuntimeException)e);

  71.           fallbackResponse.subscribe(subscriber);
  72.         }
  73.         catch (Throwable rethrown) {
  74.           subscriber.onError(rethrown);
  75.         }
  76.       }

  77.       @Override
  78.       public void onNext(JsonPipelineOutput output) {
  79.         subscriber.onNext(output);
  80.       }
  81.     };
  82.   }
  83. }