Project

General

Profile

Download (4.33 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2020 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.taxeditor.service;
10

    
11
import java.io.IOException;
12
import java.net.URI;
13
import java.time.LocalDateTime;
14
import java.time.format.DateTimeFormatter;
15

    
16
import org.apache.http.Header;
17
import org.apache.http.HttpResponse;
18
import org.apache.http.client.HttpClient;
19
import org.apache.http.client.methods.HttpPost;
20
import org.apache.http.config.Registry;
21
import org.apache.http.config.RegistryBuilder;
22
import org.apache.http.conn.socket.ConnectionSocketFactory;
23
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
24
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
25
import org.apache.http.impl.NoConnectionReuseStrategy;
26
import org.apache.http.impl.client.HttpClientBuilder;
27
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
28
import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor;
29
import org.springframework.remoting.httpinvoker.HttpInvokerClientConfiguration;
30

    
31
import eu.etaxonomy.taxeditor.remoting.RemoteExecutionTimestampsUtil;
32

    
33
/**
34
 * HttpInvokerRequestExecutor which extends the spring
35
 * {@link HttpComponentsHttpInvokerRequestExecutor} by two functionalities:
36
 *
37
 * <ol>
38
 * <li>Records time stamps when sending the request and when receiving the response.</li>
39
 * <li>Allows custom configuration of the {@link PoolingHttpClientConnectionManager}
40
 * (see <a href="https://dev.e-taxonomy.eu/redmine/issues/8812">https://dev.e-taxonomy.eu/redmine/issues/8812</a>).
41
 * </ol>
42
 *
43
 * @author a.kohlbecker
44
 * @since Jan 17, 2020
45
 */
46
public class TimestampingHttpInvokerRequestExecutor extends HttpComponentsHttpInvokerRequestExecutor {
47

    
48
    private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;
49

    
50
    private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5;
51

    
52
    /**
53
     * Default in PoolingHttpClientConnectionManager is 2000 milliseconds.
54
     *
55
     * see https://stackoverflow.com/questions/10558791/apache-httpclient-interim-error-nohttpresponseexception
56
     */
57
    private static final int VALIDATE_AFTER_INACTIVITY = 2000;
58

    
59
    public TimestampingHttpInvokerRequestExecutor() {
60
        super(createDefaultHttpClient());
61
    }
62

    
63
    @Override
64
    protected HttpResponse executeHttpPost(HttpInvokerClientConfiguration config, HttpClient httpClient,
65
            HttpPost httpPost) throws IOException {
66

    
67
        setExecutionRequestClientTimestamp(httpPost.getURI());
68

    
69
        HttpResponse response = super.executeHttpPost(config, httpClient, httpPost);
70

    
71
        setExecutionResponseHttpHeaderTimestamp(response);
72

    
73
        return response;
74
    }
75

    
76
    private void setExecutionRequestClientTimestamp(URI requestURI){
77

    
78
        LocalDateTime date = LocalDateTime.now();
79
        String dateTimeStr = date.format(DateTimeFormatter.ISO_DATE_TIME);
80
        RemoteExecutionTimestampsUtil.setLastRequestClientTime(dateTimeStr);
81
        if(requestURI != null){
82
            RemoteExecutionTimestampsUtil.setLastService(requestURI.toString());
83
        }
84
    }
85

    
86
    private void setExecutionResponseHttpHeaderTimestamp(HttpResponse respone){
87
        Header dateHeader = respone.getFirstHeader("Date");
88
        if(dateHeader != null){
89
            RemoteExecutionTimestampsUtil.setLastResponseHttpHeaderTime(dateHeader.getValue());
90
        }
91
    }
92

    
93
    private static HttpClient createDefaultHttpClient() {
94
        Registry<ConnectionSocketFactory> schemeRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
95
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
96
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
97
                .build();
98

    
99
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(schemeRegistry);
100
        connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
101
        connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
102
        connectionManager.setValidateAfterInactivity(VALIDATE_AFTER_INACTIVITY);
103

    
104
        return HttpClientBuilder.create()
105
                .setConnectionManager(connectionManager)
106
                .setConnectionReuseStrategy(new NoConnectionReuseStrategy()) // see #8812
107
                .build();
108
    }
109
}
(7-7/7)