问题
I'm experimenting with the Vaadin Java framework at the moment and I've noticed that the client engine does not retry sending requests to the server. When mobile internet network is weak or inconsistent it would be good to keep retrying sending of requests rather than giving up.
Does any one know how to achieve this in Vaadin?
回答1:
Extending ApplicationConnection and overriding doAjaxRequest should be enough to achieve what you're trying to do. Something like this:
public class MyApplicationConnection extends ApplicationConnection {
private final Logger logger = Logger
.getLogger(MyApplicationConnection.class.getName());
@Override
protected void doAjaxRequest(final String uri, final JSONObject payload,
final RequestCallback requestCallback) throws RequestException {
// wrap the original request callback handle the retries
RequestCallback myRequestCallback = new RequestCallback() {
private int retries = 3;
@Override
public void onResponseReceived(Request request, Response response) {
int status = response.getStatusCode();
if (status / 100 == 2) { // 2xx Successful
requestCallback.onResponseReceived(request, response);
} else {
handleError(request, response, null);
}
}
@Override
public void onError(Request request, Throwable exception) {
handleError(request, null, exception);
}
private void handleError(Request request, Response response,
Throwable exception) {
if (retries == 0) {
logger.info("Ajax request failed.");
if (response == null) {
requestCallback.onError(request, exception);
} else {
requestCallback.onResponseReceived(request, response);
}
} else {
try {
logger.info("Ajax request failed, retrying " + retries
+ " more times.");
retries--;
MyApplicationConnection.super.doAjaxRequest(uri,
payload, this);
} catch (RequestException e) {
// something went wrong in the ajax send() call, so no
// point in retrying
logger.warning("Sending Ajax request failed. Cause: "
+ e.getMessage());
requestCallback.onError(request, exception);
}
}
}
};
super.doAjaxRequest(uri, payload, myRequestCallback);
}
}
And in your *.gwt.xml file:
<replace-with class="com.example.client.MyApplicationConnection">
<when-type-is class="com.vaadin.client.ApplicationConnection"/>
</replace-with>
You might also want to add a Timer or something to the handleError method, so that when the network is down, the request will wait for a while for it to come back up. It should be fairly trivial though.
回答2:
I found this worked well for me:
package com.vaadin.client;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.user.client.Timer;
public class RobustApplicationConnection extends ApplicationConnection {
public RobustApplicationConnection() {
this.setCommunicationErrorDelegate(new ErrorHandler());
}
private String lastURI;
private String lastPayload;
private RequestCallback lastRequestCallback;
private enum RequestType {
AjaxRequest,
UidlRequest
}
private RequestType lastRequestType;
protected void doAjaxRequest(java.lang.String uri, java.lang.String payload, RequestCallback requestCallback) throws RequestException {
super.doAjaxRequest(uri, payload, requestCallback);
lastRequestType = RequestType.AjaxRequest;
lastURI = uri;
lastPayload = payload;
lastRequestCallback = requestCallback;
}
protected void doUidlRequest(java.lang.String uri, java.lang.String payload) {
super.doUidlRequest(uri, payload);
lastRequestType = RequestType.UidlRequest;
lastURI = uri;
lastPayload = payload;
}
private class ErrorHandler implements ApplicationConnection.CommunicationErrorHandler {
@Override
public boolean onError(String details, int statusCode) {
System.out.println("retrying in quarter second ...");
Timer t = new Timer() {
public void run() {
if (lastRequestType.equals(RequestType.AjaxRequest)){
try {
System.out.println("retrying doAjaxRequest...");
doAjaxRequest(lastURI,lastPayload,lastRequestCallback);
} catch (RequestException e) {
throw new RuntimeException("RequestException");
}
} else if (lastRequestType.equals(RequestType.AjaxRequest)){
System.out.println("retrying doUidlRequest...");
doUidlRequest(lastURI,lastPayload);
}
}
};
// delay running for quarter seconds
t.schedule(250);
return true;
}
}
}
来源:https://stackoverflow.com/questions/22962285/how-can-i-force-vaadin-client-engine-to-retry-sending-requests-to-the-server