ch.unifr.pai.twice.comm.clientServerTime.client.ClientServerTimeOffset.java Source code

Java tutorial

Introduction

Here is the source code for ch.unifr.pai.twice.comm.clientServerTime.client.ClientServerTimeOffset.java

Source

package ch.unifr.pai.twice.comm.clientServerTime.client;

/*
 * Copyright 2013 Oliver Schmid
 * 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.
 */

import java.util.Date;

import ch.unifr.pai.twice.comm.clientServerTime.server.PingServlet;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * This class provides logic to estimate the server time offset to adapt the time stamps for triggered events according to the estimated server time.
 * 
 * @author Oliver Schmid
 * 
 */
public class ClientServerTimeOffset {

    /**
     * The method sends a request asynchronously to the server side ({@link PingServlet}) and measures the time that it takes. The offset is then defined by
     * dividing the resulting round-trip time by two given the theoretical assumption that the connection is symmetrical (identical up- and downstream speed).
     * Although this requirement is almost never the case, it is precise enough for not affecting user experience and allows to establish a consistent event
     * ordering mechanism between distributed systems.
     * 
     * @param callback
     *            called at the end of the request providing the estimated offset between the server side and the local system clock in milliseconds.
     */
    public static void getServerTimeOffset(final AsyncCallback<Long> callback) {
        RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, GWT.getHostPageBaseURL() + "ping");
        final long startTime = getCurrentTime();
        try {
            rb.sendRequest(null, createServerTimeOffsetRequestCallback(callback, startTime));
        } catch (RequestException e) {
            callback.onFailure(e);
        }
    }

    static long getCurrentTime() {
        return new Date().getTime();
    }

    static RequestCallback createServerTimeOffsetRequestCallback(final AsyncCallback<Long> callback,
            final long startTime) {
        return new RequestCallback() {

            @Override
            public void onResponseReceived(Request request, Response response) {
                long endTime = getCurrentTime();
                long duration = endTime - startTime;
                String result = response.getText();
                if (result != null) {
                    long serverTime = Long.parseLong(result);
                    // We assume that the upload and download for a very small request are the same (50% of the request duration for upload, 50% for
                    // download)
                    long difference = serverTime - (endTime - (duration / 2));
                    callback.onSuccess(difference);
                }
            }

            @Override
            public void onError(Request request, Throwable exception) {
                callback.onFailure(exception);

            }
        };
    }
}