sinanselimoglu / geocoder-java

Automatically exported from code.google.com/p/geocoder-java
1 stars 0 forks source link

Use timeouts #43

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
None of the geocoder implementations seem to define timeout values. That's bad 
in a production system. Here's an implementation that attempts to define as 
many useful timeouts as possible:

/**
 * @author Antti Koivisto
 */
public class TimeoutSafeGeoCoder extends Geocoder {

    private static final int HTTP_CLIENT_CONNECTION_TIMEOUT = 5 * 1000;  // 5 seconds
    private static final int HTTP_CLIENT_METHOD_TIMEOUT = 5 * 1000; // 5 seconds
    private static final int HTTP_CLIENT_MAX_CONNECTIONS = 200;
    private static final int DEFAULT_URL_CONNECTION_TIMEOUT = 60 * 1000; // 60 seconds

    private final HttpClient httpClient;

    /**
     * Use given connectionTimeout as HttpConnectionManagerParams.setConnectionTimeout();
     * @param connectionTimeout
     */
    public TimeoutSafeGeoCoder(int connectionTimeout) {
        httpClient = setupHttpClient(connectionTimeout);
    }
    public TimeoutSafeGeoCoder() {
        httpClient = setupHttpClient(DEFAULT_URL_CONNECTION_TIMEOUT);
    }
    public TimeoutSafeGeoCoder(final String clientId, final String clientKey) throws InvalidKeyException {
        super(clientId, clientKey);
        httpClient = setupHttpClient(DEFAULT_URL_CONNECTION_TIMEOUT);
    }

    private HttpClient setupHttpClient(int connectionTimeout) {
        // As mapHandler may be used from several threads simultaneously, we must use HttpClient in
        // thread-safe way (see http://hc.apache.org/httpclient-3.x/threading.html)
        HttpConnectionManagerParams cmParams = new HttpConnectionManagerParams();
        // maxConnectionsPerHost and maxTotalConnections must be set here, as the default values
        // are not suitable for this use. As the FonectaMapHandler only connects to one host, we
        // can use same number in both.
        cmParams.setDefaultMaxConnectionsPerHost(HTTP_CLIENT_MAX_CONNECTIONS);
        cmParams.setMaxTotalConnections(HTTP_CLIENT_MAX_CONNECTIONS);
        cmParams.setConnectionTimeout(connectionTimeout);
        MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
        connectionManager.setParams(cmParams);
        return new HttpClient(connectionManager);
    }

    protected GeocodeResponse request(Gson gson, String urlString) throws IOException {
        final GetMethod getMethod = new GetMethod(urlString);
        try {
            getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(3, false));
            getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, new Integer(HTTP_CLIENT_METHOD_TIMEOUT));

            httpClient.executeMethod(getMethod);

            final Reader reader = new InputStreamReader(getMethod.getResponseBodyAsStream(), getMethod.getResponseCharSet());
            return gson.fromJson(reader, GeocodeResponse.class);
        } finally {
            getMethod.releaseConnection();
        }
    }
}

Original issue reported on code.google.com by antti.p....@gmail.com on 29 Apr 2014 at 12:08

GoogleCodeExporter commented 9 years ago
Now you can pass HttpClient directly to constructor 

Original comment by panchmp on 30 Apr 2014 at 10:23