2 * Copyright (C) 2020 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.taxeditor
.service
;
11 import java
.io
.IOException
;
13 import java
.time
.LocalDateTime
;
14 import java
.time
.format
.DateTimeFormatter
;
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
;
31 import eu
.etaxonomy
.taxeditor
.remoting
.RemoteExecutionTimestampsUtil
;
34 * HttpInvokerRequestExecutor which extends the {@link HttpComponentsHttpInvokerRequestExecutor} by two functionalities:
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>).
42 * @author a.kohlbecker
45 public class TimestampingHttpInvokerRequestExecutor
extends HttpComponentsHttpInvokerRequestExecutor
{
47 private static final int DEFAULT_MAX_TOTAL_CONNECTIONS
= 100;
49 private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE
= 5;
52 * Default in PoolingHttpClientConnectionManager is 2000 milliseconds.
54 * see https://stackoverflow.com/questions/10558791/apache-httpclient-interim-error-nohttpresponseexception
56 private static final int VALIDATE_AFTER_INACTIVITY
= 2000;
58 public TimestampingHttpInvokerRequestExecutor() {
59 super(createDefaultHttpClient());
63 protected HttpResponse
executeHttpPost(HttpInvokerClientConfiguration config
, HttpClient httpClient
,
64 HttpPost httpPost
) throws IOException
{
66 setExecutionRequestClientTimestamp(httpPost
.getURI());
68 HttpResponse respone
= super.executeHttpPost(config
, httpClient
, httpPost
);
70 setExecutionResponseHttpHeaderTimestamp(respone
);
75 private void setExecutionRequestClientTimestamp(URI requestURI
){
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());
86 private void setExecutionResponseHttpHeaderTimestamp(HttpResponse respone
){
87 Header dateHeader
= respone
.getFirstHeader("Date");
88 if(dateHeader
!= null){
89 RemoteExecutionTimestampsUtil
.setLastResponseHttpHeaderTime(dateHeader
.getValue());
93 private static HttpClient
createDefaultHttpClient() {
94 Registry
<ConnectionSocketFactory
> schemeRegistry
= RegistryBuilder
.<ConnectionSocketFactory
>create()
95 .register("http", PlainConnectionSocketFactory
.getSocketFactory())
96 .register("https", SSLConnectionSocketFactory
.getSocketFactory())
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
);
104 return HttpClientBuilder
.create()
105 .setConnectionManager(connectionManager
)
106 .setConnectionReuseStrategy(new NoConnectionReuseStrategy()) // see #8812