Skip to content

Commit 583bca0

Browse files
authored
Support external configuration of HTTP-related timeouts when invoking microservice endpoints. (#79)
* Support external configuration of HTTP-related timeouts when invoking microservice endpoints. * Address style rules. * Address style rules.
1 parent 07d1459 commit 583bca0

File tree

4 files changed

+304
-0
lines changed

4 files changed

+304
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Licensed to Islandora Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
* The Islandora Foundation licenses this file to you under the MIT License.
7+
* You may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* https://opensource.org/licenses/MIT
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package ca.islandora.alpaca.connector.derivative;
20+
21+
import org.apache.camel.component.http4.HttpClientConfigurer;
22+
import org.apache.http.client.config.RequestConfig;
23+
import org.apache.http.impl.client.HttpClientBuilder;
24+
25+
/**
26+
* Provides a default HttpClient {@link RequestConfig} with custom values for connection request, connect, and socket
27+
* timeout values. Custom values must be set on this class prior to invoking
28+
* {@link #configureHttpClient(HttpClientBuilder)}.
29+
*
30+
* @author Elliot Metsger ([email protected])
31+
*/
32+
public class RequestConfigConfigurer implements HttpClientConfigurer {
33+
34+
/**
35+
* The RequestConfig instance that is built by this configurer; exposed for testing purposes.
36+
*/
37+
RequestConfig built;
38+
39+
private int connectionRequestTimeoutMs = RequestConfig.DEFAULT.getConnectionRequestTimeout();
40+
41+
private int connectTimeoutMs = RequestConfig.DEFAULT.getConnectTimeout();
42+
43+
private int socketTimeoutMs = RequestConfig.DEFAULT.getSocketTimeout();
44+
45+
/**
46+
* Creates a {@link RequestConfig} using custom values for {@code connectionRequestTimeout}, {@code connectTimeout},
47+
* and {@code socketTimeout}. If custom values are not provided by this class, then the default values from
48+
* {@link RequestConfig#DEFAULT} are used.
49+
*
50+
* @param clientBuilder the HttpClientBuilder
51+
* @see #setConnectionRequestTimeoutMs(int)
52+
* @see #setConnectTimeoutMs(int)
53+
* @see #setSocketTimeoutMs(int)
54+
*/
55+
@Override
56+
public void configureHttpClient(final HttpClientBuilder clientBuilder) {
57+
final RequestConfig.Builder builder = RequestConfig.copy(RequestConfig.DEFAULT);
58+
final RequestConfig config = buildConfig(builder);
59+
clientBuilder.setDefaultRequestConfig(config);
60+
}
61+
62+
/**
63+
* Package-private to support testing.
64+
*
65+
* @param builder the RequestConfig builder
66+
* @return the RequestConfig
67+
*/
68+
RequestConfig buildConfig(final RequestConfig.Builder builder) {
69+
builder.setConnectionRequestTimeout(connectionRequestTimeoutMs)
70+
.setSocketTimeout(socketTimeoutMs)
71+
.setConnectTimeout(connectTimeoutMs);
72+
built = builder.build();
73+
return built;
74+
}
75+
76+
/**
77+
* Get the value of the connection request timeout
78+
*
79+
* @return the value
80+
*/
81+
public int getConnectionRequestTimeoutMs() {
82+
return connectionRequestTimeoutMs;
83+
}
84+
85+
/**
86+
* Set the value of the connection request timeout
87+
*
88+
* @param connectionRequestTimeoutMs the value
89+
*/
90+
public void setConnectionRequestTimeoutMs(final int connectionRequestTimeoutMs) {
91+
this.connectionRequestTimeoutMs = connectionRequestTimeoutMs;
92+
}
93+
94+
/**
95+
* Get the value of the connect timeout
96+
*
97+
* @return the value
98+
*/
99+
public int getConnectTimeoutMs() {
100+
return connectTimeoutMs;
101+
}
102+
103+
/**
104+
* Set the value of the connect timeout
105+
*
106+
* @param connectTimeoutMs the value
107+
*/
108+
public void setConnectTimeoutMs(final int connectTimeoutMs) {
109+
this.connectTimeoutMs = connectTimeoutMs;
110+
}
111+
112+
/**
113+
* Get the value of the socket timeout
114+
*
115+
* @return the value
116+
*/
117+
public int getSocketTimeoutMs() {
118+
return socketTimeoutMs;
119+
}
120+
121+
/**
122+
* Set the value of the socket timeout
123+
*
124+
* @param socketTimeoutMs the value
125+
*/
126+
public void setSocketTimeoutMs(final int socketTimeoutMs) {
127+
this.socketTimeoutMs = socketTimeoutMs;
128+
}
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Licensed to Islandora Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
* The Islandora Foundation licenses this file to you under the MIT License.
7+
* You may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* https://opensource.org/licenses/MIT
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package ca.islandora.alpaca.connector.derivative;
20+
21+
import org.apache.camel.component.http4.HttpComponent;
22+
import org.apache.camel.test.blueprint.CamelBlueprintTestSupport;
23+
import org.junit.Test;
24+
25+
/**
26+
* Insures that the Camel HTTP component as configured by Blueprint is properly configured.
27+
*
28+
* @author Elliot Metsger ([email protected])
29+
*/
30+
public class HttpConfigurerTest extends CamelBlueprintTestSupport {
31+
32+
@Override
33+
protected String getBlueprintDescriptor() {
34+
return "/OSGI-INF/blueprint/blueprint-httpconfigurer-test.xml";
35+
}
36+
37+
/**
38+
* Insure that the default RequestConfig for the HttpComponent carries the timeout values specified in the
39+
* blueprint xml.
40+
*
41+
* Note that the RequestConfig and RequestConfigConfigurer are difficult to test with mocking frameworks such as
42+
* Mockito due to the presence of final methods in the relevant HttpClient classes.
43+
*
44+
* @throws Exception
45+
*/
46+
@Test
47+
public void testRequestConfig() throws Exception {
48+
context.start();
49+
final HttpComponent http = (HttpComponent) context.getComponent("http");
50+
51+
final RequestConfigConfigurer configurer = (RequestConfigConfigurer) http.getHttpClientConfigurer();
52+
53+
assertEquals(10000, configurer.built.getSocketTimeout());
54+
assertEquals(10000, configurer.built.getConnectTimeout());
55+
assertEquals(10000, configurer.built.getConnectionRequestTimeout());
56+
}
57+
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Licensed to Islandora Foundation under one or more contributor license
3+
* agreements. See the NOTICE file distributed with this work for additional
4+
* information regarding copyright ownership.
5+
*
6+
* The Islandora Foundation licenses this file to you under the MIT License.
7+
* You may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* https://opensource.org/licenses/MIT
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package ca.islandora.alpaca.connector.derivative;
20+
21+
import org.apache.http.client.config.RequestConfig;
22+
import org.junit.Test;
23+
24+
import static org.junit.Assert.assertEquals;
25+
import static org.junit.Assert.assertNotNull;
26+
27+
/**
28+
* Verifies the behaviors and state of the RequestConfigConfigurer.
29+
*
30+
* @author Elliot Metsger ([email protected])
31+
*/
32+
public class RequestConfigConfigurerTest {
33+
34+
/**
35+
* The default state of the RequestConfigConfigurer should provide the same timeout values as the default
36+
* RequestConfig.
37+
*/
38+
@Test
39+
public void testDefaultValues() {
40+
final RequestConfigConfigurer underTest = new RequestConfigConfigurer();
41+
42+
assertEquals(RequestConfig.DEFAULT.getConnectionRequestTimeout(), underTest.getConnectionRequestTimeoutMs());
43+
assertEquals(RequestConfig.DEFAULT.getConnectTimeout(), underTest.getConnectTimeoutMs());
44+
assertEquals(RequestConfig.DEFAULT.getSocketTimeout(), underTest.getSocketTimeoutMs());
45+
}
46+
47+
/**
48+
* Insure state is properly maintained by the RequestConfigConfigurer.
49+
*/
50+
@Test
51+
public void testCustomValues() {
52+
final RequestConfigConfigurer underTest = new RequestConfigConfigurer();
53+
underTest.setConnectionRequestTimeoutMs(12345);
54+
underTest.setConnectTimeoutMs(1111111);
55+
underTest.setSocketTimeoutMs(9999999);
56+
57+
assertEquals(12345, underTest.getConnectionRequestTimeoutMs());
58+
assertEquals(1111111, underTest.getConnectTimeoutMs());
59+
assertEquals(9999999, underTest.getSocketTimeoutMs());
60+
}
61+
62+
/**
63+
* Insure state from the RequestConfigConfigurer is properly communicated to the built RequestConfig.
64+
*/
65+
@Test
66+
public void testBuild() {
67+
final RequestConfigConfigurer underTest = new RequestConfigConfigurer();
68+
underTest.setConnectionRequestTimeoutMs(12345);
69+
underTest.setConnectTimeoutMs(1111111);
70+
underTest.setSocketTimeoutMs(9999999);
71+
72+
underTest.buildConfig(RequestConfig.custom());
73+
74+
assertNotNull(underTest.built);
75+
76+
assertEquals(12345, underTest.built.getConnectionRequestTimeout());
77+
assertEquals(1111111, underTest.built.getConnectTimeout());
78+
assertEquals(9999999, underTest.built.getSocketTimeout());
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
5+
xsi:schemaLocation="
6+
http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd
7+
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
8+
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
9+
10+
<!-- OSGI blueprint property placeholder -->
11+
<cm:property-placeholder id="properties" persistent-id="ca.islandora.alpaca.connector.derivative" update-strategy="reload" >
12+
<cm:default-properties>
13+
<cm:property name="error.maxRedeliveries" value="5"/>
14+
<cm:property name="in.stream" value="seda:islandora-connector.derivative-index"/>
15+
<cm:property name="derivative.service.url" value="http://example.org/derivative/convert"/>
16+
</cm:default-properties>
17+
</cm:property-placeholder>
18+
19+
<bean id="requestConfigConfigurer" class="ca.islandora.alpaca.connector.derivative.RequestConfigConfigurer">
20+
<property name="connectionRequestTimeoutMs" value="10000"/>
21+
<property name="connectTimeoutMs" value="10000"/>
22+
<property name="socketTimeoutMs" value="10000"/>
23+
</bean>
24+
25+
<bean id="http" class="org.apache.camel.component.http4.HttpComponent">
26+
<property name="httpClientConfigurer" ref="requestConfigConfigurer"/>
27+
</bean>
28+
29+
<bean id="https" class="org.apache.camel.component.http4.HttpComponent">
30+
<property name="httpClientConfigurer" ref="requestConfigConfigurer"/>
31+
</bean>
32+
33+
<camelContext id="IslandoraTriplestoreIndexer" xmlns="http://camel.apache.org/schema/blueprint">
34+
<package>ca.islandora.alpaca.connector.derivative</package>
35+
</camelContext>
36+
37+
</blueprint>

0 commit comments

Comments
 (0)