001 /**
002 * Copyright (C) 2009-2011 the original author or authors.
003 * See the notice.md file distributed with this work for additional
004 * information regarding copyright ownership.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.fusesource.restygwt.client.callback;
020
021 import java.util.logging.Logger;
022
023 import org.fusesource.restygwt.client.Method;
024
025 import com.google.gwt.core.client.GWT;
026 import com.google.gwt.http.client.Request;
027 import com.google.gwt.http.client.RequestBuilder;
028 import com.google.gwt.http.client.RequestCallback;
029 import com.google.gwt.http.client.RequestException;
030 import com.google.gwt.http.client.Response;
031 import com.google.gwt.logging.client.LogConfiguration;
032 import com.google.gwt.user.client.Timer;
033 import com.google.gwt.user.client.Window;
034
035 public class RetryingFilterawareRequestCallback extends DefaultFilterawareRequestCallback {
036
037 /**
038 * Used by RetryingCallback
039 * default value is 5
040 */
041 protected int numberOfRetries = 5;
042
043 /**
044 * time to wait for reconnect upon failure
045 */
046 protected int gracePeriod = 1000;
047
048 protected int currentRetryCounter = 0;
049
050 public RetryingFilterawareRequestCallback(Method method) {
051 super(method);
052 }
053
054 public RetryingFilterawareRequestCallback(Method method,
055 int gracePeriodMillis, int numberOfRetries) {
056 super(method);
057 this.gracePeriod = gracePeriodMillis;
058 this.numberOfRetries = numberOfRetries;
059 }
060
061 @Override
062 public final void onResponseReceived(Request request, Response response) {
063 int code = response.getStatusCode();
064 if (!(code < 300 && code >= 200)) {
065 /*
066 * retry only on GET requests that are no redirects (301, 302, 303)
067 */
068 if (code != 301
069 && code != 302
070 && code != 303
071 && code != 404
072 && (method.builder == null // jsonp method do not have a builder !!
073 || method.builder.getHTTPMethod().equalsIgnoreCase("get"))) {
074 handleErrorGracefully(request, response, requestCallback);
075 } else {
076 if (LogConfiguration.loggingIsEnabled()) {
077 Logger.getLogger(RetryingFilterawareRequestCallback.class.getName()).severe(
078 "ERROR with non-GET method: " + method.builder.getHTTPMethod() + " "
079 + method.builder.getUrl() + ", " + response.getStatusText());
080 }
081
082 /*
083 * RuntimeException token from
084 * com.google.gwt.http.client.Request#fireOnResponseReceived()
085 */
086 requestCallback.onError(request, new RuntimeException("Response "
087 + response.getStatusCode() + " for " + method.builder.getHTTPMethod() + " "
088 + method.builder.getUrl()));
089 }
090 return;
091 } else {
092 // filter only in success case for now
093 runFilters(request, response);
094 }
095 }
096
097 // /**
098 // * TODO when is this used ? maybe just forward to requestCallback.onError
099 // */
100 // @Override
101 // public void onError(Request request, Throwable exception) {
102 // if (LogConfiguration.loggingIsEnabled()) {
103 // Logger.getLogger(RetryingFilterawareRequestCallback.class.getName())
104 // .severe("call onError in " + this.getClass() + ". this should not happen...");
105 // }
106 // requestCallback.onError(request, exception);
107 //// handleErrorGracefully(null, null, null);
108 // }
109
110 public void handleErrorGracefully(Request request, Response response,
111 RequestCallback requestCallback) {
112 // error handling...:
113 if (currentRetryCounter < numberOfRetries) {
114 System.out.println("counter " + currentRetryCounter);
115 if (GWT.isClient() && LogConfiguration.loggingIsEnabled()) {
116 Logger.getLogger(RetryingFilterawareRequestCallback.class.getName()).severe(
117 "error handling in progress for: " + method.builder.getHTTPMethod()
118 + " " + method.builder.getUrl());
119 }
120
121 currentRetryCounter++;
122
123 Timer t = new Timer() {
124 public void run() {
125 try {
126 System.out.println("run . . ." + method.builder.getCallback());
127
128 method.builder.send();
129 } catch (RequestException ex) {
130 if (GWT.isClient() && LogConfiguration.loggingIsEnabled()) {
131 Logger.getLogger(RetryingFilterawareRequestCallback.class.getName())
132 .severe(ex.getMessage());
133 }
134 }
135 }
136 };
137
138 t.schedule(gracePeriod);
139 gracePeriod = gracePeriod * 2;
140 } else {
141 if (GWT.isClient() && LogConfiguration.loggingIsEnabled()) {
142 Logger.getLogger(RetryingFilterawareRequestCallback.class.getName()).severe("Request failed: "
143 + method.builder.getHTTPMethod() + " " + method.builder.getUrl()
144 + " after " + currentRetryCounter + " tries.");
145 }
146
147 if (null != request
148 && null != response
149 && null != requestCallback) {
150 // got the original callback, call error here
151 requestCallback.onError(request, new RuntimeException("Response "
152 + response.getStatusCode() + " for " + method.builder.getHTTPMethod() + " "
153 + method.builder.getUrl() + " after " + numberOfRetries + " retries."));
154 } else {
155 // got no callback - well, goodbye
156 if (Window.confirm("something severly went wrong - error - reload page ?")) {
157 // Super severe error.
158 // reload app or redirect.
159 // ===> this breaks the app but that's by intention.
160 Window.Location.reload();
161 }
162 }
163 }
164 }
165 }