Merge remote-tracking branch 'upstream/master'

This commit is contained in:
bdenton 2016-01-21 18:53:25 -08:00
commit d516e1afa1
5 changed files with 99 additions and 26 deletions

View File

@ -47,6 +47,16 @@ public interface IRestfulClientFactory {
*/ */
public static final int DEFAULT_SOCKET_TIMEOUT = 10000; public static final int DEFAULT_SOCKET_TIMEOUT = 10000;
/**
* Default value for {@link #getPoolMaxTotal() ()}
*/
public static final int DEFAULT_POOL_MAX = 20;
/**
* Default value for {@link #getPoolMaxPerRoute() }
*/
public static final int DEFAULT_POOL_MAX_PER_ROUTE = DEFAULT_POOL_MAX;
/** /**
* Gets the connection request timeout, in milliseconds. This is the amount of time that the HTTPClient connection * Gets the connection request timeout, in milliseconds. This is the amount of time that the HTTPClient connection
* pool may wait for an available connection before failing. This setting typically does not need to be adjusted. * pool may wait for an available connection before failing. This setting typically does not need to be adjusted.
@ -99,6 +109,22 @@ public interface IRestfulClientFactory {
*/ */
int getSocketTimeout(); int getSocketTimeout();
/**
* Gets the maximum number of connections allowed in the pool.
* <p>
* The default value for this setting is defined by {@link #DEFAULT_POOL_MAX}
* </p>
*/
int getPoolMaxTotal();
/**
* Gets the maximum number of connections per route allowed in the pool.
* <p>
* The default value for this setting is defined by {@link #DEFAULT_POOL_MAX_PER_ROUTE}
* </p>
*/
int getPoolMaxPerRoute();
/** /**
* Instantiates a new client instance * Instantiates a new client instance
* *
@ -193,4 +219,19 @@ public interface IRestfulClientFactory {
*/ */
void setSocketTimeout(int theSocketTimeout); void setSocketTimeout(int theSocketTimeout);
/**
* Sets the maximum number of connections allowed in the pool.
* <p>
* The default value for this setting is defined by {@link #DEFAULT_POOL_MAX}
* </p>
*/
void setPoolMaxTotal(int thePoolMaxTotal);
/**
* Sets the maximum number of connections per route allowed in the pool.
* <p>
* The default value for this setting is defined by {@link #DEFAULT_POOL_MAX_PER_ROUTE}
* </p>
*/
void setPoolMaxPerRoute(int thePoolMaxPerRoute);
} }

View File

@ -68,7 +68,9 @@ public class RestfulClientFactory implements IRestfulClientFactory {
private ServerValidationModeEnum myServerValidationMode = DEFAULT_SERVER_VALIDATION_MODE; private ServerValidationModeEnum myServerValidationMode = DEFAULT_SERVER_VALIDATION_MODE;
private int mySocketTimeout = DEFAULT_SOCKET_TIMEOUT; private int mySocketTimeout = DEFAULT_SOCKET_TIMEOUT;
private Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<String>()); private Set<String> myValidatedServerBaseUrls = Collections.synchronizedSet(new HashSet<String>());
private int myPoolMaxTotal = DEFAULT_POOL_MAX;
private int myPoolMaxPerRoute = DEFAULT_POOL_MAX_PER_ROUTE;
/** /**
* Constructor * Constructor
*/ */
@ -100,7 +102,9 @@ public class RestfulClientFactory implements IRestfulClientFactory {
if (myHttpClient == null) { if (myHttpClient == null) {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
connectionManager.setMaxTotal(myPoolMaxTotal);
connectionManager.setDefaultMaxPerRoute(myPoolMaxPerRoute);
//@formatter:off //@formatter:off
RequestConfig defaultRequestConfig = RequestConfig.custom() RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(mySocketTimeout) .setSocketTimeout(mySocketTimeout)
@ -149,6 +153,16 @@ public class RestfulClientFactory implements IRestfulClientFactory {
return mySocketTimeout; return mySocketTimeout;
} }
@Override
public int getPoolMaxTotal() {
return myPoolMaxTotal;
}
@Override
public int getPoolMaxPerRoute() {
return myPoolMaxPerRoute;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) { private <T extends IRestfulClient> T instantiateProxy(Class<T> theClientType, InvocationHandler theInvocationHandler) {
T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler); T proxy = (T) Proxy.newProxyInstance(theClientType.getClassLoader(), new Class[] { theClientType }, theInvocationHandler);
@ -276,6 +290,18 @@ public class RestfulClientFactory implements IRestfulClientFactory {
myHttpClient = null; myHttpClient = null;
} }
@Override
public synchronized void setPoolMaxTotal(int thePoolMaxTotal) {
myPoolMaxTotal = thePoolMaxTotal;
myHttpClient = null;
}
@Override
public synchronized void setPoolMaxPerRoute(int thePoolMaxPerRoute) {
myPoolMaxPerRoute = thePoolMaxPerRoute;
myHttpClient = null;
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) { void validateServerBase(String theServerBase, HttpClient theHttpClient, BaseClient theClient) {

View File

@ -51,6 +51,7 @@ import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.annotation.Update; import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.method.BaseMethodBinding; import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.IParameter;
import ca.uhn.fhir.rest.method.SearchMethodBinding; import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.method.SearchParameter; import ca.uhn.fhir.rest.method.SearchParameter;
import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.param.DateRangeParam;
@ -236,16 +237,19 @@ public class ServerConformanceProviderDstu2Test {
if (resourceBinding.getResourceName().equals("Patient")) { if (resourceBinding.getResourceName().equals("Patient")) {
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings(); List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0); SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next(); for (IParameter next : binding.getParameters()) {
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription()); SearchParameter param = (SearchParameter) next;
found = true; if (param.getDescription().contains("The patient's identifier (MRN or other card number")) {
found = true;
}
}
} }
} }
assertTrue(found); assertTrue(found);
Conformance conformance = sc.getServerConformance(createHttpServletRequest()); Conformance conformance = sc.getServerConformance(createHttpServletRequest());
String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance); String conf = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(conformance);
ourLog.info(conf); ourLog.info("AAAAAA" + conf);
assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>")); assertThat(conf, containsString("<documentation value=\"The patient's identifier (MRN or other card number)\"/>"));
assertThat(conf, containsString("<type value=\"token\"/>")); assertThat(conf, containsString("<type value=\"token\"/>"));
@ -377,8 +381,12 @@ public class ServerConformanceProviderDstu2Test {
if (resourceBinding.getResourceName().equals("Patient")) { if (resourceBinding.getResourceName().equals("Patient")) {
List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings(); List<BaseMethodBinding<?>> methodBindings = resourceBinding.getMethodBindings();
SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0); SearchMethodBinding binding = (SearchMethodBinding) methodBindings.get(0);
SearchParameter param = (SearchParameter) binding.getParameters().iterator().next(); for (IParameter next : binding.getParameters()) {
assertEquals("The patient's identifier (MRN or other card number)", param.getDescription()); SearchParameter param = (SearchParameter) next;
if (param.getDescription().contains("The patient's identifier (MRN or other card number")) {
found = true;
}
}
found = true; found = true;
} }
} }
@ -522,8 +530,7 @@ public class ServerConformanceProviderDstu2Test {
public static class MultiOptionalProvider { public static class MultiOptionalProvider {
@Search(type = Patient.class) @Search(type = Patient.class)
public Patient findPatient(@Description(shortDefinition = "The patient's identifier") @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier, public Patient findPatient(@Description(shortDefinition = "The patient's identifier") @OptionalParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier, @Description(shortDefinition = "The patient's name") @OptionalParam(name = Patient.SP_NAME) StringDt theName) {
@Description(shortDefinition = "The patient's name") @OptionalParam(name = Patient.SP_NAME) StringDt theName) {
return null; return null;
} }
@ -556,8 +563,7 @@ public class ServerConformanceProviderDstu2Test {
public static class PlainProviderWithExtendedOperationOnNoType { public static class PlainProviderWithExtendedOperationOnNoType {
@Operation(name = "plain", idempotent = true, returnParameters = { @OperationParam(min = 1, max = 2, name = "out1", type = StringDt.class) }) @Operation(name = "plain", idempotent = true, returnParameters = { @OperationParam(min = 1, max = 2, name = "out1", type = StringDt.class) })
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
return null; return null;
} }
@ -566,8 +572,7 @@ public class ServerConformanceProviderDstu2Test {
public static class ProviderWithExtendedOperationReturningBundle implements IResourceProvider { public static class ProviderWithExtendedOperationReturningBundle implements IResourceProvider {
@Operation(name = "everything", idempotent = true) @Operation(name = "everything", idempotent = true)
public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, public ca.uhn.fhir.rest.server.IBundleProvider everything(javax.servlet.http.HttpServletRequest theServletRequest, @IdParam ca.uhn.fhir.model.primitive.IdDt theId, @OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
@OperationParam(name = "start") DateDt theStart, @OperationParam(name = "end") DateDt theEnd) {
return null; return null;
} }
@ -582,9 +587,8 @@ public class ServerConformanceProviderDstu2Test {
@Description(shortDefinition = "This is a search for stuff!") @Description(shortDefinition = "This is a search for stuff!")
@Search @Search
public List<DiagnosticReport> findDiagnosticReportsByPatient(@RequiredParam(name = DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId, public List<DiagnosticReport> findDiagnosticReportsByPatient(@RequiredParam(name = DiagnosticReport.SP_SUBJECT + '.' + Patient.SP_IDENTIFIER) IdentifierDt thePatientId, @OptionalParam(name = DiagnosticReport.SP_CODE) TokenOrListParam theNames,
@OptionalParam(name = DiagnosticReport.SP_CODE) TokenOrListParam theNames, @OptionalParam(name = DiagnosticReport.SP_DATE) DateRangeParam theDateRange, @OptionalParam(name = DiagnosticReport.SP_DATE) DateRangeParam theDateRange, @IncludeParam(allow = { "DiagnosticReport.result" }) Set<Include> theIncludes) throws Exception {
@IncludeParam(allow = { "DiagnosticReport.result" }) Set<Include> theIncludes) throws Exception {
return null; return null;
} }
@ -613,19 +617,12 @@ public class ServerConformanceProviderDstu2Test {
public static class SearchProvider { public static class SearchProvider {
@Search(type = Patient.class) @Search(type = Patient.class)
public Patient findPatient1( public Patient findPatient1(@Description(shortDefinition = "The patient's identifier (MRN or other card number)") @RequiredParam(name = Patient.SP_IDENTIFIER) IdentifierDt theIdentifier) {
@Description(shortDefinition = "The patient's identifier (MRN or other card number)")
@RequiredParam(name = Patient.SP_IDENTIFIER)
IdentifierDt theIdentifier) {
return null; return null;
} }
@Search(type = Patient.class) @Search(type = Patient.class)
public Patient findPatient2( public Patient findPatient2(@Description(shortDefinition = "All patients linked to the given patient") @OptionalParam(name = "link", targetTypes = { Patient.class }) ReferenceAndListParam theLink) {
@Description(shortDefinition="All patients linked to the given patient")
@OptionalParam(name="link", targetTypes={ Patient.class } )
ReferenceAndListParam theLink
) {
return null; return null;
} }

View File

@ -216,6 +216,10 @@
<id>karlmdavis</id> <id>karlmdavis</id>
<name>Karl M. Davis</name> <name>Karl M. Davis</name>
</developer> </developer>
<developer>
<id>matt-blanchette</id>
<name>Matt Blanchette</name>
</developer>
</developers> </developers>
<licenses> <licenses>

View File

@ -145,6 +145,11 @@
running in an old serlvet container should be tested well before use. Thanks to Bill Denton running in an old serlvet container should be tested well before use. Thanks to Bill Denton
for reporting! for reporting!
</action> </action>
<action type="add" issue="288">
Add new methods to RestfulClientFactory allowing you to configure the size of the
client pool used by Apache HttpClient. Thanks to Matt Blanchette for the pull
request!
</action>
</release> </release>
<release version="1.3" date="2015-11-14"> <release version="1.3" date="2015-11-14">
<action type="add"> <action type="add">