Project

General

Profile

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

    
47
    private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;
48

    
49
    private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5;
50

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

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

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

    
66
        setExecutionRequestClientTimestamp(httpPost.getURI());
67

    
68
        HttpResponse respone = super.executeHttpPost(config, httpClient, httpPost);
69

    
70
        setExecutionResponseHttpHeaderTimestamp(respone);
71

    
72
        return respone;
73
    }
74

    
75
    private void setExecutionRequestClientTimestamp(URI requestURI){
76

    
77
        LocalDateTime date = LocalDateTime.now();
78
        String dateTimeStr = date.format(DateTimeFormatter.ISO_DATE_TIME);
79
        RemoteExecutionTimestampsUtil.setLastRequestClientTime(dateTimeStr);
80
        if(requestURI != null){
81
            RemoteExecutionTimestampsUtil.setLastServiceMethod(requestURI.toString());
82
        }
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)