From 3e33c8a835e9cfc9a9eeaf094b4fec3218d83114 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:33:54 +1000 Subject: [PATCH 01/12] ongoing work around connection problems with tx.fhir.org --- .../fhir/dstu2/utils/client/ClientUtils.java | 56 +++++---- .../dstu2/utils/client/FHIRToolingClient.java | 44 +++---- .../dstu2016may/utils/client/ClientUtils.java | 58 ++++++---- .../utils/client/FHIRToolingClient.java | 48 ++++---- .../fhir/dstu3/utils/client/ClientUtils.java | 59 ++++++---- .../dstu3/utils/client/FHIRToolingClient.java | 44 +++---- .../hl7/fhir/r4/utils/client/ClientUtils.java | 59 ++++++---- .../r4/utils/client/FHIRToolingClient.java | 44 +++---- .../hl7/fhir/r5/utils/client/ClientUtils.java | 59 ++++++---- .../r5/utils/client/FHIRToolingClient.java | 108 +++++++++--------- 10 files changed, 324 insertions(+), 255 deletions(-) diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ClientUtils.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ClientUtils.java index a2e548929..ce0e570e5 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ClientUtils.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/ClientUtils.java @@ -86,6 +86,7 @@ import org.hl7.fhir.dstu2.model.Resource; import org.hl7.fhir.dstu2.model.ResourceType; import org.hl7.fhir.dstu2.utils.ResourceUtilities; import org.hl7.fhir.utilities.ToolingClientLogger; +import org.hl7.fhir.utilities.Utilities; /** * Helper class handling lower level HTTP transport concerns. @@ -96,6 +97,7 @@ public class ClientUtils { public static final String DEFAULT_CHARSET = "UTF-8"; public static final String HEADER_LOCATION = "location"; + private static boolean debugging = false; private HttpHost proxy; private int timeout = 5000; @@ -136,34 +138,34 @@ public class ClientUtils { this.password = password; } - public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat) { + public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, int timeoutLoading) { HttpOptions options = new HttpOptions(optionsUri); - return issueResourceRequest(resourceFormat, options); + return issueResourceRequest(resourceFormat, options, timeoutLoading); } - public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat) { + public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, int timeoutLoading) { HttpGet httpget = new HttpGet(resourceUri); - return issueResourceRequest(resourceFormat, httpget); + return issueResourceRequest(resourceFormat, httpget, timeoutLoading); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, headers); + return issueResourceRequest(resourceFormat, httpPut, payload, headers, timeoutLoading); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, null); + return issueResourceRequest(resourceFormat, httpPut, payload, null, timeoutLoading); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers) { + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { HttpPost httpPost = new HttpPost(resourceUri); - return issueResourceRequest(resourceFormat, httpPost, payload, headers); + return issueResourceRequest(resourceFormat, httpPost, payload, headers, timeoutLoading); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat) { - return issuePostRequest(resourceUri, payload, resourceFormat, null); + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + return issuePostRequest(resourceUri, payload, resourceFormat, null, timeoutLoading); } public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat) { @@ -184,10 +186,10 @@ public class ClientUtils { } } - public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat) { + public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { HttpPost httpPost = new HttpPost(resourceUri); configureFhirRequest(httpPost, resourceFormat); - HttpResponse response = sendPayload(httpPost, payload, proxy); + HttpResponse response = sendPayload(httpPost, payload, proxy, timeoutLoading); return unmarshalFeed(response, resourceFormat); } @@ -206,8 +208,8 @@ public class ClientUtils { * Request/Response Helper methods ***********************************************************/ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request) { - return issueResourceRequest(resourceFormat, request, null); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, int timeoutLoading) { + return issueResourceRequest(resourceFormat, request, null, timeoutLoading); } /** @@ -215,8 +217,8 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload) { - return issueResourceRequest(resourceFormat, request, payload, null); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, int timeoutLoading) { + return issueResourceRequest(resourceFormat, request, payload, null, timeoutLoading); } /** @@ -224,11 +226,11 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers) { + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, int timeoutLoading) { configureFhirRequest(request, resourceFormat, headers); HttpResponse response = null; if(request instanceof HttpEntityEnclosingRequest && payload != null) { - response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy); + response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, timeoutLoading); } else if (request instanceof HttpEntityEnclosingRequest && payload == null){ throw new EFhirClientException("PUT and POST requests require a non-null payload"); } else { @@ -278,14 +280,20 @@ public class ClientUtils { * @param payload * @return */ - protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy) { + @SuppressWarnings({ "resource", "deprecation" }) + protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, int timeoutLoading) { HttpResponse response = null; boolean ok = false; + long t = System.currentTimeMillis(); int tryCount = 0; while (!ok) { try { tryCount++; HttpClient httpclient = new DefaultHttpClient(); + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setConnectionTimeout(params, timeout); + HttpConnectionParams.setSoTimeout(params, timeout * timeoutLoading); + if(proxy != null) { httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } @@ -294,7 +302,8 @@ public class ClientUtils { response = httpclient.execute(request); ok = true; } catch(IOException ioe) { - if (tryCount <= retryCount) { + System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+")"); + if (tryCount <= retryCount || (tryCount < 3 && ioe instanceof org.apache.http.conn.ConnectTimeoutException)) { ok = false; } else { throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); @@ -323,6 +332,9 @@ public class ClientUtils { } response = httpclient.execute(request); } catch(IOException ioe) { + if (ClientUtils.debugging ) { + ioe.printStackTrace(); + } throw new EFhirClientException("Error sending Http Request: "+ioe.getMessage(), ioe); } return response; diff --git a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java index 260b190f1..684a4a4c3 100644 --- a/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu2/src/main/java/org/hl7/fhir/dstu2/utils/client/FHIRToolingClient.java @@ -87,6 +87,9 @@ public class FHIRToolingClient { public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String hostKey = "http.proxyHost"; public static final String portKey = "http.proxyPort"; + private static final int TIMEOUT_NORMAL = 1; + private static final int TIMEOUT_OPERATION = 2; + private static final int TIMEOUT_OPERATION_LONG = 3; private String base; private ResourceAddress resourceAddress; @@ -172,9 +175,9 @@ public class FHIRToolingClient { Conformance conformance = null; try { if(useOptionsVerb) { - conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat()).getReference();//TODO fix this + conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference();//TODO fix this } else { - conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat()).getReference(); + conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); } } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); @@ -192,9 +195,9 @@ public class FHIRToolingClient { Conformance conformance = null; try { if(useOptionsVerb) { - conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat()).getReference();//TODO fix this + conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference();//TODO fix this } else { - conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat()).getReference(); + conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); } } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); @@ -205,7 +208,7 @@ public class FHIRToolingClient { public T read(Class resourceClass, String id) {//TODO Change this to AddressableResource ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -221,7 +224,7 @@ public class FHIRToolingClient { public T vread(Class resourceClass, String id, String version) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -240,7 +243,7 @@ public class FHIRToolingClient { public T getCanonical(Class resourceClass, String canonicalURL) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -264,7 +267,7 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -293,7 +296,7 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -497,9 +500,9 @@ public class FHIRToolingClient { ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; ResourceRequest result; if (complex) - result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); + result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); else - result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -522,7 +525,7 @@ public class FHIRToolingClient { public Bundle transaction(Bundle batch) { Bundle transactionResult = null; try { - transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); + transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_NORMAL+batch.getEntry().size()); } catch (Exception e) { handleException("An error occurred trying to process this transaction request", e); } @@ -530,11 +533,10 @@ public class FHIRToolingClient { } @SuppressWarnings("unchecked") - public OperationOutcome validate(Class resourceClass, T resource, String id) { ResourceRequest result = null; try { - result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); + result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), 3); result.addErrorStatus(400);//gone result.addErrorStatus(422);//Unprocessable Entity result.addSuccessStatus(200);//OK @@ -704,7 +706,7 @@ public class FHIRToolingClient { public ValueSet expandValueset(ValueSet source) { List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"), - utils.getResourceAsByteArray(source, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(source, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION_LONG); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -719,7 +721,7 @@ public class FHIRToolingClient { public Parameters lookupCode(Map params) { - ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(ValueSet.class, "lookup", params), getPreferredResourceFormat()); + ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(ValueSet.class, "lookup", params), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -733,14 +735,12 @@ public class FHIRToolingClient { } public ValueSet expandValueset(ValueSet source, Parameters expParams,Map params) { List
headers = null; - Parameters p = expParams == null ? new Parameters() : expParams.copy(); p.addParameter().setName("valueSet").setResource(source); for (String n : params.keySet()) p.addParameter().setName(n).setValue(new StringType(params.get(n))); - ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); result.addErrorStatus(410); //gone result.addErrorStatus(404); //unknown result.addErrorStatus(405); @@ -779,7 +779,7 @@ public class FHIRToolingClient { params.addParameter().setName("name").setValue(new StringType(name)); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -798,7 +798,7 @@ public class FHIRToolingClient { params.addParameter().setName("concept").setValue(coding); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -837,7 +837,7 @@ public class FHIRToolingClient { public Parameters getTerminologyCapabilities() { - return (Parameters) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat()).getReference(); + return (Parameters) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); } diff --git a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/ClientUtils.java b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/ClientUtils.java index 9aaeb97a2..06ebdbc4f 100644 --- a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/ClientUtils.java +++ b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/ClientUtils.java @@ -86,6 +86,7 @@ import org.hl7.fhir.dstu2016may.model.Resource; import org.hl7.fhir.dstu2016may.model.ResourceType; import org.hl7.fhir.dstu2016may.utils.ResourceUtilities; import org.hl7.fhir.utilities.ToolingClientLogger; +import org.hl7.fhir.utilities.Utilities; /** * Helper class handling lower level HTTP transport concerns. @@ -94,8 +95,9 @@ import org.hl7.fhir.utilities.ToolingClientLogger; */ public class ClientUtils { - public static String DEFAULT_CHARSET = "UTF-8"; + public static final String DEFAULT_CHARSET = "UTF-8"; public static final String HEADER_LOCATION = "location"; + private static boolean debugging = false; private HttpHost proxy; private int timeout = 5000; @@ -136,34 +138,34 @@ public class ClientUtils { this.password = password; } - public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat) { + public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, int timeoutLoading) { HttpOptions options = new HttpOptions(optionsUri); - return issueResourceRequest(resourceFormat, options); + return issueResourceRequest(resourceFormat, options, timeoutLoading); } - public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat) { + public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, int timeoutLoading) { HttpGet httpget = new HttpGet(resourceUri); - return issueResourceRequest(resourceFormat, httpget); + return issueResourceRequest(resourceFormat, httpget, timeoutLoading); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, headers); + return issueResourceRequest(resourceFormat, httpPut, payload, headers, timeoutLoading); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, null); + return issueResourceRequest(resourceFormat, httpPut, payload, null, timeoutLoading); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers) { + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { HttpPost httpPost = new HttpPost(resourceUri); - return issueResourceRequest(resourceFormat, httpPost, payload, headers); + return issueResourceRequest(resourceFormat, httpPost, payload, headers, timeoutLoading); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat) { - return issuePostRequest(resourceUri, payload, resourceFormat, null); + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + return issuePostRequest(resourceUri, payload, resourceFormat, null, timeoutLoading); } public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat) { @@ -184,10 +186,10 @@ public class ClientUtils { } } - public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat) { + public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { HttpPost httpPost = new HttpPost(resourceUri); configureFhirRequest(httpPost, resourceFormat); - HttpResponse response = sendPayload(httpPost, payload, proxy); + HttpResponse response = sendPayload(httpPost, payload, proxy, timeoutLoading); return unmarshalFeed(response, resourceFormat); } @@ -206,8 +208,8 @@ public class ClientUtils { * Request/Response Helper methods ***********************************************************/ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request) { - return issueResourceRequest(resourceFormat, request, null); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, int timeoutLoading) { + return issueResourceRequest(resourceFormat, request, null, timeoutLoading); } /** @@ -215,8 +217,8 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload) { - return issueResourceRequest(resourceFormat, request, payload, null); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, int timeoutLoading) { + return issueResourceRequest(resourceFormat, request, payload, null, timeoutLoading); } /** @@ -224,11 +226,11 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers) { + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, int timeoutLoading) { configureFhirRequest(request, resourceFormat, headers); HttpResponse response = null; if(request instanceof HttpEntityEnclosingRequest && payload != null) { - response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy); + response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, timeoutLoading); } else if (request instanceof HttpEntityEnclosingRequest && payload == null){ throw new EFhirClientException("PUT and POST requests require a non-null payload"); } else { @@ -278,14 +280,20 @@ public class ClientUtils { * @param payload * @return */ - protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy) { + @SuppressWarnings({ "resource", "deprecation" }) + protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, int timeoutLoading) { HttpResponse response = null; boolean ok = false; + long t = System.currentTimeMillis(); int tryCount = 0; while (!ok) { try { tryCount++; HttpClient httpclient = new DefaultHttpClient(); + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setConnectionTimeout(params, timeout); + HttpConnectionParams.setSoTimeout(params, timeout * timeoutLoading); + if(proxy != null) { httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); } @@ -294,7 +302,8 @@ public class ClientUtils { response = httpclient.execute(request); ok = true; } catch(IOException ioe) { - if (tryCount <= retryCount) { + System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+")"); + if (tryCount <= retryCount || (tryCount < 3 && ioe instanceof org.apache.http.conn.ConnectTimeoutException)) { ok = false; } else { throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); @@ -323,6 +332,9 @@ public class ClientUtils { } response = httpclient.execute(request); } catch(IOException ioe) { + if (ClientUtils.debugging ) { + ioe.printStackTrace(); + } throw new EFhirClientException("Error sending Http Request: "+ioe.getMessage(), ioe); } return response; diff --git a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java index 65cbecb11..8a5742eef 100644 --- a/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu2016may/src/main/java/org/hl7/fhir/dstu2016may/utils/client/FHIRToolingClient.java @@ -42,6 +42,7 @@ import java.util.Map; import org.apache.http.Header; import org.apache.http.HttpHost; import org.hl7.fhir.dstu2016may.model.Bundle; +import org.hl7.fhir.dstu2016may.model.CodeSystem; import org.hl7.fhir.dstu2016may.model.Coding; import org.hl7.fhir.dstu2016may.model.ConceptMap; import org.hl7.fhir.dstu2016may.model.Conformance; @@ -87,6 +88,9 @@ public class FHIRToolingClient { public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String hostKey = "http.proxyHost"; public static final String portKey = "http.proxyPort"; + private static final int TIMEOUT_NORMAL = 1; + private static final int TIMEOUT_OPERATION = 2; + private static final int TIMEOUT_OPERATION_LONG = 3; private String base; private ResourceAddress resourceAddress; @@ -172,9 +176,9 @@ public class FHIRToolingClient { Conformance conformance = null; try { if(useOptionsVerb) { - conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat()).getReference();//TODO fix this + conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference();//TODO fix this } else { - conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat()).getReference(); + conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); } } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); @@ -192,9 +196,9 @@ public class FHIRToolingClient { Conformance conformance = null; try { if(useOptionsVerb) { - conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat()).getReference();//TODO fix this + conformance = (Conformance)utils.issueOptionsRequest(resourceAddress.getBaseServiceUri(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference();//TODO fix this } else { - conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat()).getReference(); + conformance = (Conformance)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); } } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); @@ -205,7 +209,7 @@ public class FHIRToolingClient { public T read(Class resourceClass, String id) {//TODO Change this to AddressableResource ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -221,7 +225,7 @@ public class FHIRToolingClient { public T vread(Class resourceClass, String id, String version) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -240,7 +244,7 @@ public class FHIRToolingClient { public T getCanonical(Class resourceClass, String canonicalURL) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -264,7 +268,7 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -293,7 +297,7 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -497,9 +501,9 @@ public class FHIRToolingClient { ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; ResourceRequest result; if (complex) - result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); + result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); else - result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat()); + result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -522,7 +526,7 @@ public class FHIRToolingClient { public Bundle transaction(Bundle batch) { Bundle transactionResult = null; try { - transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); + transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_NORMAL+batch.getEntry().size()); } catch (Exception e) { handleException("An error occurred trying to process this transaction request", e); } @@ -534,7 +538,7 @@ public class FHIRToolingClient { public OperationOutcome validate(Class resourceClass, T resource, String id) { ResourceRequest result = null; try { - result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat()); + result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), 3); result.addErrorStatus(400);//gone result.addErrorStatus(422);//Unprocessable Entity result.addSuccessStatus(200);//OK @@ -701,10 +705,12 @@ public class FHIRToolingClient { return feed; } - public ValueSet expandValueset(ValueSet source) { + public ValueSet expandValueset(ValueSet source, Parameters expParams) { List
headers = null; + Parameters p = expParams == null ? new Parameters() : expParams.copy(); + p.addParameter().setName("valueSet").setResource(source); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"), - utils.getResourceAsByteArray(source, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -719,7 +725,7 @@ public class FHIRToolingClient { public Parameters lookupCode(Map params) { - ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(ValueSet.class, "lookup", params), getPreferredResourceFormat()); + ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -733,14 +739,12 @@ public class FHIRToolingClient { } public ValueSet expandValueset(ValueSet source, Parameters expParams,Map params) { List
headers = null; - Parameters p = expParams == null ? new Parameters() : expParams.copy(); p.addParameter().setName("valueSet").setResource(source); for (String n : params.keySet()) p.addParameter().setName(n).setValue(new StringType(params.get(n))); - ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -779,7 +783,7 @@ public class FHIRToolingClient { params.addParameter().setName("name").setValue(new StringType(name)); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -798,7 +802,7 @@ public class FHIRToolingClient { params.addParameter().setName("concept").setValue(coding); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -837,7 +841,7 @@ public class FHIRToolingClient { public Parameters getTerminologyCapabilities() { - return (Parameters) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat()).getReference(); + return (Parameters) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); } diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java index 823392fe3..0ecd807e7 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java @@ -98,9 +98,11 @@ public class ClientUtils { public static final String DEFAULT_CHARSET = "UTF-8"; public static final String HEADER_LOCATION = "location"; private static boolean debugging = false; + public static final int TIMEOUT_SOCKET = 5000; + public static final int TIMEOUT_CONNECT = 1000; private HttpHost proxy; - private int timeout = 5000; + private int timeout = TIMEOUT_SOCKET; private String username; private String password; private ToolingClientLogger logger; @@ -138,34 +140,34 @@ public class ClientUtils { this.password = password; } - public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, int timeoutLoading) { + public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, String message, int timeout) { HttpOptions options = new HttpOptions(optionsUri); - return issueResourceRequest(resourceFormat, options, timeoutLoading); + return issueResourceRequest(resourceFormat, options, message, timeout); } - public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, int timeoutLoading) { + public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, String message, int timeout) { HttpGet httpget = new HttpGet(resourceUri); - return issueResourceRequest(resourceFormat, httpget, timeoutLoading); + return issueResourceRequest(resourceFormat, httpget, message, timeout); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, String message, int timeout) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, headers, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPut, payload, headers, message, timeout); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, null, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPut, payload, null, message, timeout); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, String message, int timeout) { HttpPost httpPost = new HttpPost(resourceUri); - return issueResourceRequest(resourceFormat, httpPost, payload, headers, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPost, payload, headers, message, timeout); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { - return issuePostRequest(resourceUri, payload, resourceFormat, null, timeoutLoading); + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { + return issuePostRequest(resourceUri, payload, resourceFormat, null, message, timeout); } public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat) { @@ -186,10 +188,10 @@ public class ClientUtils { } } - public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { HttpPost httpPost = new HttpPost(resourceUri); configureFhirRequest(httpPost, resourceFormat); - HttpResponse response = sendPayload(httpPost, payload, proxy, timeoutLoading); + HttpResponse response = sendPayload(httpPost, payload, proxy, message, timeout); return unmarshalFeed(response, resourceFormat); } @@ -208,8 +210,8 @@ public class ClientUtils { * Request/Response Helper methods ***********************************************************/ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, int timeoutLoading) { - return issueResourceRequest(resourceFormat, request, null, timeoutLoading); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, String message, int timeout) { + return issueResourceRequest(resourceFormat, request, null, message, timeout); } /** @@ -217,8 +219,8 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, int timeoutLoading) { - return issueResourceRequest(resourceFormat, request, payload, null, timeoutLoading); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, String message, int timeout) { + return issueResourceRequest(resourceFormat, request, payload, null, message, timeout); } /** @@ -226,11 +228,11 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, int timeoutLoading) { + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, String message, int timeout) { configureFhirRequest(request, resourceFormat, headers); HttpResponse response = null; if(request instanceof HttpEntityEnclosingRequest && payload != null) { - response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, timeoutLoading); + response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, message, timeout); } else if (request instanceof HttpEntityEnclosingRequest && payload == null){ throw new EFhirClientException("PUT and POST requests require a non-null payload"); } else { @@ -281,7 +283,7 @@ public class ClientUtils { * @return */ @SuppressWarnings({ "resource", "deprecation" }) - protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, int timeoutLoading) { + protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, String message, int timeout) { HttpResponse response = null; boolean ok = false; long t = System.currentTimeMillis(); @@ -291,8 +293,8 @@ public class ClientUtils { tryCount++; HttpClient httpclient = new DefaultHttpClient(); HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, timeout); - HttpConnectionParams.setSoTimeout(params, timeout * timeoutLoading); + HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); + HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); if(proxy != null) { httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); @@ -302,10 +304,17 @@ public class ClientUtils { response = httpclient.execute(request); ok = true; } catch(IOException ioe) { - System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+")"); + System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); if (tryCount <= retryCount || (tryCount < 3 && ioe instanceof org.apache.http.conn.ConnectTimeoutException)) { ok = false; + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } } else { + if (tryCount > 1) { + System.out.println("Giving up: "+ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); + } throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); } } diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java index d5b371957..5a8a1ee42 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/FHIRToolingClient.java @@ -89,9 +89,10 @@ public class FHIRToolingClient { public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String hostKey = "http.proxyHost"; public static final String portKey = "http.proxyPort"; - private static final int TIMEOUT_NORMAL = 1; - private static final int TIMEOUT_OPERATION = 2; - private static final int TIMEOUT_OPERATION_LONG = 3; + private static final int TIMEOUT_NORMAL = 15; + private static final int TIMEOUT_OPERATION = 30; + private static final int TIMEOUT_OPERATION_LONG = 60; + private static final int TIMEOUT_OPERATION_EXPAND = 120; private String base; private ResourceAddress resourceAddress; @@ -171,7 +172,7 @@ public class FHIRToolingClient { public CapabilityStatement getCapabilitiesStatement() { CapabilityStatement conformance = null; try { - conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), "CapabilitiesStatement", TIMEOUT_NORMAL).getReference(); } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); } @@ -182,7 +183,7 @@ public class FHIRToolingClient { if (capabilities != null) return capabilities; try { - capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), "CapabilitiesStatement-Quick", TIMEOUT_NORMAL).getReference(); } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); } @@ -192,7 +193,7 @@ public class FHIRToolingClient { public T read(Class resourceClass, String id) {//TODO Change this to AddressableResource ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), "Read "+resourceClass.getName()+"/"+id, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -208,7 +209,7 @@ public class FHIRToolingClient { public T vread(Class resourceClass, String id, String version) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), "VRead "+resourceClass.getName()+"/"+id+"/?_history/"+version, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -227,7 +228,7 @@ public class FHIRToolingClient { public T getCanonical(Class resourceClass, String canonicalURL) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), "Read "+resourceClass.getName()+"?url="+canonicalURL, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -251,7 +252,8 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, + "Update "+resource.fhirType()+"/"+resource.getId(), TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -280,7 +282,8 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, + "Update "+resource.fhirType()+"/"+id, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -484,9 +487,10 @@ public class FHIRToolingClient { ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; ResourceRequest result; if (complex) - result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION); + result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), + "POST "+resourceClass.getName()+"/$"+name, TIMEOUT_OPERATION_LONG); else - result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION); + result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), "GET "+resourceClass.getName()+"/$"+name, TIMEOUT_OPERATION_LONG); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -509,7 +513,7 @@ public class FHIRToolingClient { public Bundle transaction(Bundle batch) { Bundle transactionResult = null; try { - transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_NORMAL+batch.getEntry().size()); + transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "transaction", TIMEOUT_NORMAL+batch.getEntry().size()); } catch (Exception e) { handleException("An error occurred trying to process this transaction request", e); } @@ -520,7 +524,7 @@ public class FHIRToolingClient { public OperationOutcome validate(Class resourceClass, T resource, String id) { ResourceRequest result = null; try { - result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION); + result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "POST "+resourceClass.getName()+(id != null ? "/"+id : "")+"/$validate", TIMEOUT_OPERATION_LONG); result.addErrorStatus(400);//gone result.addErrorStatus(422);//Unprocessable Entity result.addSuccessStatus(200);//OK @@ -694,7 +698,7 @@ public class FHIRToolingClient { if (profile != null) p.addParameter().setName("profile").setResource(profile); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -709,7 +713,7 @@ public class FHIRToolingClient { public Parameters lookupCode(Map params) { - ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), TIMEOUT_NORMAL); + ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), "CodeSystem/$lookup", TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -730,7 +734,7 @@ public class FHIRToolingClient { for (String n : params.keySet()) p.addParameter().setName(n).setValue(new StringType(params.get(n))); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -769,7 +773,7 @@ public class FHIRToolingClient { params.addParameter().setName("name").setValue(new StringType(name)); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "Closure?name="+name, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -788,7 +792,7 @@ public class FHIRToolingClient { params.addParameter().setName("concept").setValue(coding); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "UpdateClosure?name="+name, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -827,7 +831,7 @@ public class FHIRToolingClient { public Parameters getTerminologyCapabilities() { - return (Parameters) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + return (Parameters) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), "TerminologyCapabilities", TIMEOUT_NORMAL).getReference(); } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java index e2bf7ca05..442d7d7c3 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java @@ -98,9 +98,11 @@ public class ClientUtils { public static final String DEFAULT_CHARSET = "UTF-8"; public static final String HEADER_LOCATION = "location"; private static boolean debugging = false; + public static final int TIMEOUT_SOCKET = 5000; + public static final int TIMEOUT_CONNECT = 1000; private HttpHost proxy; - private int timeout = 5000; + private int timeout = TIMEOUT_SOCKET; private String username; private String password; private ToolingClientLogger logger; @@ -138,34 +140,34 @@ public class ClientUtils { this.password = password; } - public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, int timeoutLoading) { + public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, String message, int timeout) { HttpOptions options = new HttpOptions(optionsUri); - return issueResourceRequest(resourceFormat, options, timeoutLoading); + return issueResourceRequest(resourceFormat, options, message, timeout); } - public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, int timeoutLoading) { + public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, String message, int timeout) { HttpGet httpget = new HttpGet(resourceUri); - return issueResourceRequest(resourceFormat, httpget, timeoutLoading); + return issueResourceRequest(resourceFormat, httpget, message, timeout); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, String message, int timeout) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, headers, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPut, payload, headers, message, timeout); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, null, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPut, payload, null, message, timeout); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, String message, int timeout) { HttpPost httpPost = new HttpPost(resourceUri); - return issueResourceRequest(resourceFormat, httpPost, payload, headers, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPost, payload, headers, message, timeout); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { - return issuePostRequest(resourceUri, payload, resourceFormat, null, timeoutLoading); + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { + return issuePostRequest(resourceUri, payload, resourceFormat, null, message, timeout); } public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat) { @@ -186,10 +188,10 @@ public class ClientUtils { } } - public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { HttpPost httpPost = new HttpPost(resourceUri); configureFhirRequest(httpPost, resourceFormat); - HttpResponse response = sendPayload(httpPost, payload, proxy, timeoutLoading); + HttpResponse response = sendPayload(httpPost, payload, proxy, message, timeout); return unmarshalFeed(response, resourceFormat); } @@ -208,8 +210,8 @@ public class ClientUtils { * Request/Response Helper methods ***********************************************************/ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, int timeoutLoading) { - return issueResourceRequest(resourceFormat, request, null, timeoutLoading); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, String message, int timeout) { + return issueResourceRequest(resourceFormat, request, null, message, timeout); } /** @@ -217,8 +219,8 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, int timeoutLoading) { - return issueResourceRequest(resourceFormat, request, payload, null, timeoutLoading); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, String message, int timeout) { + return issueResourceRequest(resourceFormat, request, payload, null, message, timeout); } /** @@ -226,11 +228,11 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, int timeoutLoading) { + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, String message, int timeout) { configureFhirRequest(request, resourceFormat, headers); HttpResponse response = null; if(request instanceof HttpEntityEnclosingRequest && payload != null) { - response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, timeoutLoading); + response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, message, timeout); } else if (request instanceof HttpEntityEnclosingRequest && payload == null){ throw new EFhirClientException("PUT and POST requests require a non-null payload"); } else { @@ -281,7 +283,7 @@ public class ClientUtils { * @return */ @SuppressWarnings({ "resource", "deprecation" }) - protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, int timeoutLoading) { + protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, String message, int timeout) { HttpResponse response = null; boolean ok = false; long t = System.currentTimeMillis(); @@ -291,8 +293,8 @@ public class ClientUtils { tryCount++; HttpClient httpclient = new DefaultHttpClient(); HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, timeout); - HttpConnectionParams.setSoTimeout(params, timeout * timeoutLoading); + HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); + HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); if(proxy != null) { httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); @@ -302,10 +304,17 @@ public class ClientUtils { response = httpclient.execute(request); ok = true; } catch(IOException ioe) { - System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+")"); + System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); if (tryCount <= retryCount || (tryCount < 3 && ioe instanceof org.apache.http.conn.ConnectTimeoutException)) { ok = false; + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } } else { + if (tryCount > 1) { + System.out.println("Giving up: "+ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); + } throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); } } diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java index 75ee51863..99150f918 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/FHIRToolingClient.java @@ -89,9 +89,10 @@ public class FHIRToolingClient { public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String hostKey = "http.proxyHost"; public static final String portKey = "http.proxyPort"; - private static final int TIMEOUT_NORMAL = 1; - private static final int TIMEOUT_OPERATION = 2; - private static final int TIMEOUT_OPERATION_LONG = 3; + private static final int TIMEOUT_NORMAL = 15; + private static final int TIMEOUT_OPERATION = 30; + private static final int TIMEOUT_OPERATION_LONG = 60; + private static final int TIMEOUT_OPERATION_EXPAND = 120; private String base; private ResourceAddress resourceAddress; @@ -168,13 +169,13 @@ public class FHIRToolingClient { } public TerminologyCapabilities getTerminologyCapabilities() { - return (TerminologyCapabilities) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + return (TerminologyCapabilities) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), "TerminologyCapabilities", TIMEOUT_NORMAL).getReference(); } public CapabilityStatement getCapabilitiesStatement() { CapabilityStatement conformance = null; try { - conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), "CapabilitiesStatement", TIMEOUT_NORMAL).getReference(); } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); } @@ -185,7 +186,7 @@ public class FHIRToolingClient { if (capabilities != null) return capabilities; try { - capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), "CapabilitiesStatement-Quick", TIMEOUT_NORMAL).getReference(); } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); } @@ -195,7 +196,7 @@ public class FHIRToolingClient { public T read(Class resourceClass, String id) {//TODO Change this to AddressableResource ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), "Read "+resourceClass.getName()+"/"+id, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -211,7 +212,7 @@ public class FHIRToolingClient { public T vread(Class resourceClass, String id, String version) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), "VRead "+resourceClass.getName()+"/"+id+"/?_history/"+version, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -230,7 +231,7 @@ public class FHIRToolingClient { public T getCanonical(Class resourceClass, String canonicalURL) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), "Read "+resourceClass.getName()+"?url="+canonicalURL, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -254,7 +255,8 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, + "Update "+resource.fhirType()+"/"+resource.getId(), TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -283,7 +285,8 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, + "Update "+resource.fhirType()+"/"+id, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -487,9 +490,10 @@ public class FHIRToolingClient { ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; ResourceRequest result; if (complex) - result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); + result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), + "POST "+resourceClass.getName()+"/$"+name, TIMEOUT_OPERATION_LONG); else - result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); + result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), "GET "+resourceClass.getName()+"/$"+name, TIMEOUT_OPERATION_LONG); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -512,7 +516,7 @@ public class FHIRToolingClient { public Bundle transaction(Bundle batch) { Bundle transactionResult = null; try { - transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_NORMAL+batch.getEntry().size()); + transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "transaction", TIMEOUT_NORMAL+batch.getEntry().size()); } catch (Exception e) { handleException("An error occurred trying to process this transaction request", e); } @@ -523,7 +527,7 @@ public class FHIRToolingClient { public OperationOutcome validate(Class resourceClass, T resource, String id) { ResourceRequest result = null; try { - result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), 3); + result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "POST "+resourceClass.getName()+(id != null ? "/"+id : "")+"/$validate", TIMEOUT_OPERATION_LONG); result.addErrorStatus(400);//gone result.addErrorStatus(422);//Unprocessable Entity result.addSuccessStatus(200);//OK @@ -695,7 +699,7 @@ public class FHIRToolingClient { Parameters p = expParams == null ? new Parameters() : expParams.copy(); p.addParameter().setName("valueSet").setResource(source); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -710,7 +714,7 @@ public class FHIRToolingClient { public Parameters lookupCode(Map params) { - ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), TIMEOUT_NORMAL); + ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), "CodeSystem/$lookup", TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -729,7 +733,7 @@ public class FHIRToolingClient { for (String n : params.keySet()) p.addParameter().setName(n).setValue(new StringType(params.get(n))); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -768,7 +772,7 @@ public class FHIRToolingClient { params.addParameter().setName("name").setValue(new StringType(name)); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "Closure?name="+name, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -787,7 +791,7 @@ public class FHIRToolingClient { params.addParameter().setName("concept").setValue(coding); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "UpdateClosure?name="+name, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java index e085afe3f..1148d2018 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java @@ -98,9 +98,11 @@ public class ClientUtils { public static final String DEFAULT_CHARSET = "UTF-8"; public static final String HEADER_LOCATION = "location"; private static boolean debugging = false; + public static final int TIMEOUT_SOCKET = 5000; + public static final int TIMEOUT_CONNECT = 1000; private HttpHost proxy; - private int timeout = 5000; + private int timeout = TIMEOUT_SOCKET; private String username; private String password; private ToolingClientLogger logger; @@ -138,34 +140,34 @@ public class ClientUtils { this.password = password; } - public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, int timeoutLoading) { + public ResourceRequest issueOptionsRequest(URI optionsUri, String resourceFormat, String message, int timeout) { HttpOptions options = new HttpOptions(optionsUri); - return issueResourceRequest(resourceFormat, options, timeoutLoading); + return issueResourceRequest(resourceFormat, options, message, timeout); } - public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, int timeoutLoading) { + public ResourceRequest issueGetResourceRequest(URI resourceUri, String resourceFormat, String message, int timeout) { HttpGet httpget = new HttpGet(resourceUri); - return issueResourceRequest(resourceFormat, httpget, timeoutLoading); + return issueResourceRequest(resourceFormat, httpget, message, timeout); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, String message, int timeout) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, headers, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPut, payload, headers, message, timeout); } - public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + public ResourceRequest issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { HttpPut httpPut = new HttpPut(resourceUri); - return issueResourceRequest(resourceFormat, httpPut, payload, null, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPut, payload, null, message, timeout); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, int timeoutLoading) { + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, List
headers, String message, int timeout) { HttpPost httpPost = new HttpPost(resourceUri); - return issueResourceRequest(resourceFormat, httpPost, payload, headers, timeoutLoading); + return issueResourceRequest(resourceFormat, httpPost, payload, headers, message, timeout); } - public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { - return issuePostRequest(resourceUri, payload, resourceFormat, null, timeoutLoading); + public ResourceRequest issuePostRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { + return issuePostRequest(resourceUri, payload, resourceFormat, null, message, timeout); } public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat) { @@ -186,10 +188,10 @@ public class ClientUtils { } } - public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, int timeoutLoading) { + public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout) { HttpPost httpPost = new HttpPost(resourceUri); configureFhirRequest(httpPost, resourceFormat); - HttpResponse response = sendPayload(httpPost, payload, proxy, timeoutLoading); + HttpResponse response = sendPayload(httpPost, payload, proxy, message, timeout); return unmarshalFeed(response, resourceFormat); } @@ -208,8 +210,8 @@ public class ClientUtils { * Request/Response Helper methods ***********************************************************/ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, int timeoutLoading) { - return issueResourceRequest(resourceFormat, request, null, timeoutLoading); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, String message, int timeout) { + return issueResourceRequest(resourceFormat, request, null, message, timeout); } /** @@ -217,8 +219,8 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, int timeoutLoading) { - return issueResourceRequest(resourceFormat, request, payload, null, timeoutLoading); + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, String message, int timeout) { + return issueResourceRequest(resourceFormat, request, payload, null, message, timeout); } /** @@ -226,11 +228,11 @@ public class ClientUtils { * @param options * @return */ - protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, int timeoutLoading) { + protected ResourceRequest issueResourceRequest(String resourceFormat, HttpUriRequest request, byte[] payload, List
headers, String message, int timeout) { configureFhirRequest(request, resourceFormat, headers); HttpResponse response = null; if(request instanceof HttpEntityEnclosingRequest && payload != null) { - response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, timeoutLoading); + response = sendPayload((HttpEntityEnclosingRequestBase)request, payload, proxy, message, timeout); } else if (request instanceof HttpEntityEnclosingRequest && payload == null){ throw new EFhirClientException("PUT and POST requests require a non-null payload"); } else { @@ -281,7 +283,7 @@ public class ClientUtils { * @return */ @SuppressWarnings({ "resource", "deprecation" }) - protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, int timeoutLoading) { + protected HttpResponse sendPayload(HttpEntityEnclosingRequestBase request, byte[] payload, HttpHost proxy, String message, int timeout) { HttpResponse response = null; boolean ok = false; long t = System.currentTimeMillis(); @@ -291,8 +293,8 @@ public class ClientUtils { tryCount++; HttpClient httpclient = new DefaultHttpClient(); HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, timeout); - HttpConnectionParams.setSoTimeout(params, timeout * timeoutLoading); + HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); + HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); if(proxy != null) { httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); @@ -302,10 +304,17 @@ public class ClientUtils { response = httpclient.execute(request); ok = true; } catch(IOException ioe) { - System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+")"); + System.out.println(ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); if (tryCount <= retryCount || (tryCount < 3 && ioe instanceof org.apache.http.conn.ConnectTimeoutException)) { ok = false; + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } } else { + if (tryCount > 1) { + System.out.println("Giving up: "+ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); + } throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); } } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java index 5e5fcb0de..f56896d7b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java @@ -85,9 +85,10 @@ public class FHIRToolingClient { public static final String DATE_FORMAT = "yyyy-MM-dd"; public static final String hostKey = "http.proxyHost"; public static final String portKey = "http.proxyPort"; - private static final int TIMEOUT_NORMAL = 1; - private static final int TIMEOUT_OPERATION = 2; - private static final int TIMEOUT_OPERATION_LONG = 3; + private static final int TIMEOUT_NORMAL = 15; + private static final int TIMEOUT_OPERATION = 30; + private static final int TIMEOUT_OPERATION_LONG = 60; + private static final int TIMEOUT_OPERATION_EXPAND = 120; private String base; private ResourceAddress resourceAddress; @@ -164,13 +165,13 @@ public class FHIRToolingClient { } public TerminologyCapabilities getTerminologyCapabilities() { - return (TerminologyCapabilities) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + return (TerminologyCapabilities) utils.issueGetResourceRequest(resourceAddress.resolveMetadataTxCaps(), getPreferredResourceFormat(), "TerminologyCapabilities", TIMEOUT_NORMAL).getReference(); } public CapabilityStatement getCapabilitiesStatement() { CapabilityStatement conformance = null; try { - conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + conformance = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(false), getPreferredResourceFormat(), "CapabilitiesStatement", TIMEOUT_NORMAL).getReference(); } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); } @@ -181,7 +182,7 @@ public class FHIRToolingClient { if (capabilities != null) return capabilities; try { - capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), TIMEOUT_NORMAL).getReference(); + capabilities = (CapabilityStatement)utils.issueGetResourceRequest(resourceAddress.resolveMetadataUri(true), getPreferredResourceFormat(), "CapabilitiesStatement-Quick", TIMEOUT_NORMAL).getReference(); } catch(Exception e) { handleException("An error has occurred while trying to fetch the server's conformance statement", e); } @@ -191,7 +192,7 @@ public class FHIRToolingClient { public T read(Class resourceClass, String id) {//TODO Change this to AddressableResource ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), getPreferredResourceFormat(), "Read "+resourceClass.getName()+"/"+id, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addSuccessStatus(200);//Only one for now @@ -207,7 +208,7 @@ public class FHIRToolingClient { public T vread(Class resourceClass, String id, String version) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndIdAndVersion(resourceClass, id, version), getPreferredResourceFormat(), "VRead "+resourceClass.getName()+"/"+id+"/?_history/"+version, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -226,7 +227,7 @@ public class FHIRToolingClient { public T getCanonical(Class resourceClass, String canonicalURL) { ResourceRequest result = null; try { - result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), TIMEOUT_NORMAL); + result = utils.issueGetResourceRequest(resourceAddress.resolveGetUriFromResourceClassAndCanonical(resourceClass, canonicalURL), getPreferredResourceFormat(), "Read "+resourceClass.getName()+"?url="+canonicalURL, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405);//unknown @@ -250,7 +251,8 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, + "Update "+resource.fhirType()+"/"+resource.getId(), TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -279,7 +281,8 @@ public class FHIRToolingClient { ResourceRequest result = null; try { List
headers = null; - result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); + result = utils.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, + "Update "+resource.fhirType()+"/"+id, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -470,45 +473,48 @@ public class FHIRToolingClient { // } - public Parameters operateType(Class resourceClass, String name, Parameters params) { - boolean complex = false; - for (ParametersParameterComponent p : params.getParameter()) - complex = complex || !(p.getValue() instanceof PrimitiveType); - Parameters searchResults = null; - String ps = ""; - try { - if (!complex) - for (ParametersParameterComponent p : params.getParameter()) - if (p.getValue() instanceof PrimitiveType) - ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; - ResourceRequest result; - if (complex) - result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); - else - result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), TIMEOUT_OPERATION_LONG); - result.addErrorStatus(410);//gone - result.addErrorStatus(404);//unknown - result.addSuccessStatus(200);//Only one for now - if(result.isUnsuccessfulRequest()) - throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); - if (result.getPayload() instanceof Parameters) - return (Parameters) result.getPayload(); - else { - Parameters p_out = new Parameters(); - p_out.addParameter().setName("return").setResource(result.getPayload()); - return p_out; - } - } catch (Exception e) { - handleException("Error performing operation '"+name+"' with parameters " + ps, e); - } - return null; - } + public Parameters operateType(Class resourceClass, String name, Parameters params) { + boolean complex = false; + for (ParametersParameterComponent p : params.getParameter()) + complex = complex || !(p.getValue() instanceof PrimitiveType); + Parameters searchResults = null; + String ps = ""; + try { + if (!complex) + for (ParametersParameterComponent p : params.getParameter()) + if (p.getValue() instanceof PrimitiveType) + ps += p.getName() + "=" + Utilities.encodeUri(((PrimitiveType) p.getValue()).asStringValue())+"&"; + ResourceRequest result; + if (complex) { + result = utils.issuePostRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), + "POST "+resourceClass.getName()+"/$"+name, TIMEOUT_OPERATION_LONG); + } else { + result = utils.issueGetResourceRequest(resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps), getPreferredResourceFormat(), "GET "+resourceClass.getName()+"/$"+name, TIMEOUT_OPERATION_LONG); + } + result.addErrorStatus(410);//gone + result.addErrorStatus(404);//unknown + result.addSuccessStatus(200);//Only one for now + if(result.isUnsuccessfulRequest()) { + throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome)result.getPayload()); + } + if (result.getPayload() instanceof Parameters) { + return (Parameters) result.getPayload(); + } else { + Parameters p_out = new Parameters(); + p_out.addParameter().setName("return").setResource(result.getPayload()); + return p_out; + } + } catch (Exception e) { + handleException("Error performing operation '"+name+"' with parameters " + ps, e); + } + return null; + } public Bundle transaction(Bundle batch) { Bundle transactionResult = null; try { - transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), TIMEOUT_NORMAL+batch.getEntry().size()); + transactionResult = utils.postBatchRequest(resourceAddress.getBaseServiceUri(), utils.getFeedAsByteArray(batch, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "transaction", TIMEOUT_NORMAL+batch.getEntry().size()); } catch (Exception e) { handleException("An error occurred trying to process this transaction request", e); } @@ -519,7 +525,7 @@ public class FHIRToolingClient { public OperationOutcome validate(Class resourceClass, T resource, String id) { ResourceRequest result = null; try { - result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), 3); + result = utils.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id), utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), "POST "+resourceClass.getName()+(id != null ? "/"+id : "")+"/$validate", TIMEOUT_OPERATION_LONG); result.addErrorStatus(400);//gone result.addErrorStatus(422);//Unprocessable Entity result.addSuccessStatus(200);//OK @@ -691,7 +697,7 @@ public class FHIRToolingClient { Parameters p = expParams == null ? new Parameters() : expParams.copy(); p.addParameter().setName("valueSet").setResource(source); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -706,7 +712,7 @@ public class FHIRToolingClient { public Parameters lookupCode(Map params) { - ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), TIMEOUT_NORMAL); + ResourceRequest result = utils.issueGetResourceRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup", params), getPreferredResourceFormat(), "CodeSystem/$lookup", TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -725,7 +731,7 @@ public class FHIRToolingClient { for (String n : params.keySet()) p.addParameter().setName(n).setValue(new StringType(params.get(n))); ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), - utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, 4); + utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -764,7 +770,7 @@ public class FHIRToolingClient { params.addParameter().setName("name").setValue(new StringType(name)); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_NORMAL); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "Closure?name="+name, TIMEOUT_NORMAL); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); @@ -783,7 +789,7 @@ public class FHIRToolingClient { params.addParameter().setName("concept").setValue(coding); List
headers = null; ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap()), - utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, TIMEOUT_OPERATION); + utils.getResourceAsByteArray(params, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "UpdateClosure?name="+name, TIMEOUT_OPERATION); result.addErrorStatus(410);//gone result.addErrorStatus(404);//unknown result.addErrorStatus(405); From 9b0ce65f08ef94ace8c97d30d4b7627b39f785c2 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:34:30 +1000 Subject: [PATCH 02/12] fix for bug processing CCDA constraints (logical model constraints) --- .../java/org/hl7/fhir/r5/conformance/ProfileUtilities.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 6b699f4a1..5ee1f033b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -4616,7 +4616,7 @@ public class ProfileUtilities extends TranslatingUtilities { this.prefixLength = prefixLength; this.base = base; if (Utilities.isAbsoluteUrl(base)) { - throw new Error("Wrong!"); + this.base = urlTail(base); } this.name = name; } @@ -5191,7 +5191,7 @@ public class ProfileUtilities extends TranslatingUtilities { // } // - private String urlTail(String profile) { + private static String urlTail(String profile) { return profile.contains("/") ? profile.substring(profile.lastIndexOf("/")+1) : profile; } From f93f47ee24d713db23cfec232b564eaf3018cc01 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:35:14 +1000 Subject: [PATCH 03/12] fix for bug loading Measures from packages --- .../hl7/fhir/r5/context/SimpleWorkerContext.java | 4 ++-- .../org/hl7/fhir/utilities/cache/NpmPackage.java | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java index 3a87b4ff1..6fe9cde60 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/SimpleWorkerContext.java @@ -386,7 +386,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon return new String[] {"CodeSystem", "ValueSet", "ConceptMap", "NamingSystem", "StructureDefinition", "StructureMap", "SearchParameter", "OperationDefinition", "CapabilityStatement", "Conformance", - "Questionnaire", "ImplementationGuide" }; + "Questionnaire", "ImplementationGuide", "Measure" }; } @Override @@ -441,7 +441,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon } } else { if (types.length == 0) { - types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire", "ConceptMap", "StructureMap", "NamingSystem" }; + types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire", "ConceptMap", "StructureMap", "NamingSystem", "Measures" }; } for (PackageResourceInformation pri : pi.listIndexedResources(types)) { try { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java index 334ab7d4d..76598aa2b 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/NpmPackage.java @@ -336,8 +336,7 @@ public class NpmPackage { throw new IOException("Error parsing "+ij.getAbsolutePath()+": "+e.getMessage(), e); } } - loadSubFolders(rootPath, f); - + loadSubFolders(rootPath, f); } } } @@ -536,13 +535,14 @@ public class NpmPackage { public List listIndexedResources(String... types) throws IOException { List res = new ArrayList(); - NpmPackageFolder folder = folders.get("package"); - for (JsonElement e : folder.index.getAsJsonArray("files")) { - JsonObject fi = e.getAsJsonObject(); - if (Utilities.existsInList(JSONUtil.str(fi, "resourceType"), types)) { - res.add(new PackageResourceInformation(folder.folder.getAbsolutePath(), fi)); + for (NpmPackageFolder folder : folders.values()) { + for (JsonElement e : folder.index.getAsJsonArray("files")) { + JsonObject fi = e.getAsJsonObject(); + if (Utilities.existsInList(JSONUtil.str(fi, "resourceType"), types)) { + res.add(new PackageResourceInformation(folder.folder.getAbsolutePath(), fi)); + } } - } + } // Collections.sort(res, new PackageResourceInformationSorter()); return res; } From 8b3ce7b3cca89629b20fbfc7c39ae831318fda3b Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:36:20 +1000 Subject: [PATCH 04/12] fix NPEs loading invalid packages --- .../org/hl7/fhir/utilities/cache/BasePackageCacheManager.java | 3 +++ .../fhir/utilities/cache/FilesystemPackageCacheManager.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java index 549eb5b04..82e295e89 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/BasePackageCacheManager.java @@ -128,6 +128,9 @@ public abstract class BasePackageCacheManager implements IPackageCacheManager { } private String getPackageId(String canonical, String server) throws IOException { + if (canonical == null) { + return null; + } PackageClient pc = myClientFactory.apply(server); List res = pc.search(null, canonical, null, false); if (res.size() == 0) { diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java index 13baa282a..45fd24e84 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/cache/FilesystemPackageCacheManager.java @@ -544,6 +544,9 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple // ========================= Package Mgmt API ======================================================================= private String getPackageIdFromBuildList(String canonical) throws IOException { + if (canonical == null) { + return null; + } checkBuildLoaded(); if (buildInfo != null) { for (JsonElement n : buildInfo) { From 879e5344b3182d8365aa1734dd67a0d93e2baf9f Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:37:27 +1000 Subject: [PATCH 05/12] Start Working on i18n for Rendering + Fix case bug rendering bundles and parameters --- .../hl7/fhir/r5/renderers/BundleRenderer.java | 54 +++++++++++-------- .../hl7/fhir/r5/renderers/DataRenderer.java | 10 ++-- .../fhir/r5/renderers/ParametersRenderer.java | 2 +- .../org/hl7/fhir/r5/renderers/Renderer.java | 46 ++++++++++++++++ .../fhir/r5/renderers/ResourceRenderer.java | 4 +- .../src/main/resources/Messages.properties | 16 ++++++ 6 files changed, 101 insertions(+), 31 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/BundleRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/BundleRenderer.java index dca727389..33fa539ff 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/BundleRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/BundleRenderer.java @@ -28,6 +28,7 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode; public class BundleRenderer extends ResourceRenderer { + public BundleRenderer(RenderingContext context, ResourceContext rcontext) { super(context, rcontext); } @@ -63,7 +64,7 @@ public class BundleRenderer extends ResourceRenderer { // nothing } else { XhtmlNode root = new XhtmlNode(NodeType.Element, "div"); - root.para().addText("Bundle "+b.getId()+" of type "+b.get("type").primitiveValue()); + root.para().addText(formatMessage(RENDER_BUNDLE_HEADER_ROOT, b.getId(), b.get("type").primitiveValue())); int i = 0; for (BaseWrapper be : entries) { i++; @@ -71,10 +72,14 @@ public class BundleRenderer extends ResourceRenderer { root.an(makeInternalLink(be.get("fullUrl").primitiveValue())); } if (be.has("resource") && be.getChildByName("resource").getValues().get(0).has("id")) { - root.an(be.get("resource").fhirType().toLowerCase() + "_" + be.getChildByName("resource").getValues().get(0).get("id").primitiveValue()); + root.an(be.get("resource").fhirType() + "_" + be.getChildByName("resource").getValues().get(0).get("id").primitiveValue()); } root.hr(); - root.para().addText("Entry "+Integer.toString(i)+(be.has("fullUrl") ? " - Full URL = " + be.get("fullUrl").primitiveValue() : "")); + if (be.has("fullUrl")) { + root.para().addText(formatMessage(RENDER_BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.get("fullUrl").primitiveValue())); + } else { + root.para().addText(formatMessage(RENDER_BUNDLE_HEADER_ENTRY, Integer.toString(i))); + } // if (be.hasRequest()) // renderRequest(root, be.getRequest()); // if (be.hasSearch()) @@ -82,7 +87,7 @@ public class BundleRenderer extends ResourceRenderer { // if (be.hasResponse()) // renderResponse(root, be.getResponse()); if (be.has("resource")) { - root.para().addText("Resource "+be.get("resource").fhirType()+":"); + root.para().addText(formatMessage(RENDER_BUNDLE_RESOURCE, be.get("resource").fhirType())); ResourceWrapper rw = be.getChildByName("resource").getAsResource(); root.blockquote().addChildren(rw.getNarrative()); } @@ -94,24 +99,29 @@ public class BundleRenderer extends ResourceRenderer { public XhtmlNode render(Bundle b) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome { if (b.getType() == BundleType.DOCUMENT) { - if (!b.hasEntry() || !(b.getEntryFirstRep().hasResource() && b.getEntryFirstRep().getResource() instanceof Composition)) + if (!b.hasEntry() || !(b.getEntryFirstRep().hasResource() && b.getEntryFirstRep().getResource() instanceof Composition)) { throw new FHIRException("Invalid document - first entry is not a Composition"); + } Composition dr = (Composition) b.getEntryFirstRep().getResource(); return dr.getText().getDiv(); } else if ((b.getType() == BundleType.COLLECTION && allEntresAreHistoryProvenance(b))) { return null; } else { XhtmlNode root = new XhtmlNode(NodeType.Element, "div"); - root.para().addText("Bundle "+b.getId()+" of type "+b.getType().toCode()); + root.para().addText(formatMessage(RENDER_BUNDLE_HEADER_ROOT, b.getId(), b.getType().toCode())); int i = 0; for (BundleEntryComponent be : b.getEntry()) { i++; if (be.hasFullUrl()) root.an(makeInternalLink(be.getFullUrl())); if (be.hasResource() && be.getResource().hasId()) - root.an(be.getResource().getResourceType().name().toLowerCase() + "_" + be.getResource().getId()); + root.an(be.getResource().getResourceType().name() + "_" + be.getResource().getId()); root.hr(); - root.para().addText("Entry "+Integer.toString(i)+(be.hasFullUrl() ? " - Full URL = " + be.getFullUrl() : "")); + if (be.hasFullUrl()) { + root.para().addText(formatMessage(RENDER_BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.getFullUrl())); + } else { + root.para().addText(formatMessage(RENDER_BUNDLE_HEADER_ENTRY, Integer.toString(i))); + } if (be.hasRequest()) renderRequest(root, be.getRequest()); if (be.hasSearch()) @@ -119,7 +129,7 @@ public class BundleRenderer extends ResourceRenderer { if (be.hasResponse()) renderResponse(root, be.getResponse()); if (be.hasResource()) { - root.para().addText("Resource "+be.getResource().fhirType()+":"); + root.para().addText(formatMessage(RENDER_BUNDLE_RESOURCE, be.getResource().fhirType())); if (be.hasResource() && be.getResource() instanceof DomainResource) { DomainResource dr = (DomainResource) be.getResource(); if ( dr.getText().hasDiv()) @@ -178,45 +188,47 @@ public class BundleRenderer extends ResourceRenderer { private void renderSearch(XhtmlNode root, BundleEntrySearchComponent search) { StringBuilder b = new StringBuilder(); - b.append("Search: "); + b.append(formatMessage(RENDER_BUNDLE_SEARCH)); if (search.hasMode()) - b.append("mode = "+search.getMode().toCode()); + b.append(formatMessage(RENDER_BUNDLE_SEARCH_MODE, search.getMode().toCode())); if (search.hasScore()) { if (search.hasMode()) b.append(","); - b.append("score = "+search.getScore()); + b.append(formatMessage(RENDER_BUNDLE_SEARCH_SCORE, search.getScore())); } root.para().addText(b.toString()); } private void renderResponse(XhtmlNode root, BundleEntryResponseComponent response) { - root.para().addText("Response:"); + root.para().addText(formatMessage(RENDER_BUNDLE_RESPONSE)); StringBuilder b = new StringBuilder(); b.append(response.getStatus()+"\r\n"); if (response.hasLocation()) - b.append("Location: "+response.getLocation()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_LOCATION, response.getLocation())+"\r\n"); if (response.hasEtag()) - b.append("E-Tag: "+response.getEtag()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_ETAG, response.getEtag())+"\r\n"); if (response.hasLastModified()) - b.append("LastModified: "+response.getEtag()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_LAST_MOD, response.getEtag())+"\r\n"); root.pre().addText(b.toString()); } private void renderRequest(XhtmlNode root, BundleEntryRequestComponent request) { - root.para().addText("Request:"); + root.para().addText(formatMessage(RENDER_BUNDLE_REQUEST)); StringBuilder b = new StringBuilder(); b.append(request.getMethod()+" "+request.getUrl()+"\r\n"); if (request.hasIfNoneMatch()) - b.append("If-None-Match: "+request.getIfNoneMatch()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_IF_NON_MATCH, request.getIfNoneMatch())+"\r\n"); if (request.hasIfModifiedSince()) - b.append("If-Modified-Since: "+request.getIfModifiedSince()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_IF_MOD, request.getIfModifiedSince())+"\r\n"); if (request.hasIfMatch()) - b.append("If-Match: "+request.getIfMatch()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_IF_MATCH, request.getIfMatch())+"\r\n"); if (request.hasIfNoneExist()) - b.append("If-None-Exist: "+request.getIfNoneExist()+"\r\n"); + b.append(formatMessage(RENDER_BUNDLE_IF_NONE, request.getIfNoneExist())+"\r\n"); root.pre().addText(b.toString()); } + + private String makeInternalLink(String fullUrl) { return fullUrl.replace(":", "-"); } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java index d3748aa42..be047566d 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DataRenderer.java @@ -56,17 +56,13 @@ import org.hl7.fhir.utilities.xhtml.XhtmlParser; public class DataRenderer extends Renderer { // -- 1. context -------------------------------------------------------------- - - protected RenderingContext context; - + public DataRenderer(RenderingContext context) { - super(); - this.context = context; + super(context); } public DataRenderer(IWorkerContext worker) { - super(); - this.context = new RenderingContext(worker, new MarkDownProcessor(Dialect.COMMON_MARK), ValidationOptions.defaults(), "http://hl7.org/fhir/R4", "", null, ResourceRendererMode.RESOURCE); + super(worker); } // -- 2. Markdown support ------------------------------------------------------- diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java index 0cbc2b635..fc8e6436b 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ParametersRenderer.java @@ -77,7 +77,7 @@ public class ParametersRenderer extends ResourceRenderer { td = tr.td(); XhtmlNode para = td.para(); para.tx(rw.fhirType()+"/"+rw.getId()); - para.an(rw.fhirType().toLowerCase()+"_"+rw.getId()).tx(" "); + para.an(rw.fhirType()+"_"+rw.getId()).tx(" "); XhtmlNode x = rw.getNarrative(); if (x != null) { td.addChildren(x); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java index fc1a1867c..fdab9eb80 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/Renderer.java @@ -1,5 +1,11 @@ package org.hl7.fhir.r5.renderers; +import org.hl7.fhir.r5.context.IWorkerContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext; +import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode; +import org.hl7.fhir.utilities.MarkDownProcessor; +import org.hl7.fhir.utilities.MarkDownProcessor.Dialect; +import org.hl7.fhir.utilities.validation.ValidationOptions; /** * Rendering framework: @@ -20,4 +26,44 @@ package org.hl7.fhir.r5.renderers; */ public class Renderer { + protected RenderingContext context; + + public Renderer(RenderingContext context) { + this.context = context; + } + + public Renderer(IWorkerContext worker) { + this.context = new RenderingContext(worker, new MarkDownProcessor(Dialect.COMMON_MARK), ValidationOptions.defaults(), "http://hl7.org/fhir/R5", "", null, ResourceRendererMode.RESOURCE); + } + + + protected static final String RENDER_BUNDLE_HEADER_ROOT = "RENDER_BUNDLE_HEADER_ROOT"; + protected static final String RENDER_BUNDLE_HEADER_ENTRY = "RENDER_BUNDLE_HEADER_ENTRY"; + protected static final String RENDER_BUNDLE_HEADER_ENTRY_URL = "RENDER_BUNDLE_HEADER_ENTRY_URL"; + protected static final String RENDER_BUNDLE_RESOURCE = "RENDER_BUNDLE_RESOURCE"; + protected static final String RENDER_BUNDLE_SEARCH = "RENDER_BUNDLE_SEARCH"; + protected static final String RENDER_BUNDLE_SEARCH_MODE = "RENDER_BUNDLE_SEARCH_MODE"; + protected static final String RENDER_BUNDLE_SEARCH_SCORE = "RENDER_BUNDLE_SEARCH_SCORE"; + protected static final String RENDER_BUNDLE_RESPONSE = "RENDER_BUNDLE_RESPONSE"; + protected static final String RENDER_BUNDLE_LOCATION = "RENDER_BUNDLE_LOCATION"; + protected static final String RENDER_BUNDLE_ETAG = "RENDER_BUNDLE_ETAG"; + protected static final String RENDER_BUNDLE_LAST_MOD = "RENDER_BUNDLE_LAST_MOD"; + protected static final String RENDER_BUNDLE_REQUEST = "RENDER_BUNDLE_REQUEST"; + protected static final String RENDER_BUNDLE_IF_NON_MATCH = "RENDER_BUNDLE_IF_NON_MATCH"; + protected static final String RENDER_BUNDLE_IF_MOD = "RENDER_BUNDLE_IF_MOD"; + protected static final String RENDER_BUNDLE_IF_MATCH = "RENDER_BUNDLE_IF_MATCH"; + protected static final String RENDER_BUNDLE_IF_NONE = "RENDER_BUNDLE_IF_NONE"; + + + /** the plan here is to make this have it's own implementation of messages, rather than using the + * validator messages, for better alignment with publisher I18n strategy + * + * @param theMessage + * @param theMessageArguments + * @return + */ + protected String formatMessage(String theMessage, Object... theMessageArguments) { + return context.getWorker().formatMessage(theMessage, theMessageArguments); + } + } diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java index 4b2d5447a..1904b74cd 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java @@ -220,7 +220,7 @@ public abstract class ResourceRenderer extends DataRenderer { if (rcontext != null) { BundleEntryComponent bundleResource = rcontext.resolve(url); if (bundleResource != null) { - String bundleUrl = "#" + bundleResource.getResource().getResourceType().name().toLowerCase() + "_" + bundleResource.getResource().getId(); + String bundleUrl = "#" + bundleResource.getResource().getResourceType().name() + "_" + bundleResource.getResource().getId(); return new ResourceWithReference(bundleUrl, new ResourceWrapperDirect(this.context, bundleResource.getResource())); } org.hl7.fhir.r5.elementmodel.Element bundleElement = rcontext.resolveElement(url); @@ -228,7 +228,7 @@ public abstract class ResourceRenderer extends DataRenderer { String bundleUrl = null; Element br = bundleElement.getNamedChild("resource"); if (br.getChildValue("id") != null) { - bundleUrl = "#" + br.fhirType().toLowerCase() + "_" + br.getChildValue("id"); + bundleUrl = "#" + br.fhirType() + "_" + br.getChildValue("id"); } else { bundleUrl = "#" +fullUrlToAnchor(bundleElement.getChildValue("fullUrl")); } diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index 8bd7307cf..243766cad 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -575,3 +575,19 @@ VALIDATION_VAL_PROFILE_OTHER_VERSION = Profile is for a different version of FHI VALIDATION_VAL_PROFILE_THIS_VERSION_OK = Profile for this version of FHIR - all OK VALIDATION_VAL_PROFILE_THIS_VERSION_OTHER = Profile is for this version of FHIR, but is an invalid type {0} BUNDLE_BUNDLE_ENTRY_MULTIPLE_PROFILES = Multiple profiles found for contained resource. This is not supported at this time. (Type {0}: {1}) +RENDER_BUNDLE_HEADER_ROOT = Bundle {0} of type {1} +RENDER_BUNDLE_HEADER_ENTRY = Entry {0} +RENDER_BUNDLE_HEADER_ENTRY_URL = Entry {0} - Full URL = {1} +RENDER_BUNDLE_RESOURCE = Resource {0}: +RENDER_BUNDLE_SEARCH = Search: +RENDER_BUNDLE_SEARCH_MODE = mode = {0} +RENDER_BUNDLE_SEARCH_SCORE = score = {0} +RENDER_BUNDLE_RESPONSE = Response: +RENDER_BUNDLE_LOCATION = Location = {0} +RENDER_BUNDLE_ETAG = ETag = {0} +RENDER_BUNDLE_LAST_MOD = LastModified = {0} +RENDER_BUNDLE_REQUEST = Request: +RENDER_BUNDLE_IF_NON_MATCH = If-None-Match = {0} +RENDER_BUNDLE_IF_MOD = If-Modified-Since = {0} +RENDER_BUNDLE_IF_MATCH = If-Match = {0} +RENDER_BUNDLE_IF_NONE = If-None-Exist = {0} From 3e97c095e625b383981578498c70759f77eaf3e7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:38:43 +1000 Subject: [PATCH 06/12] Fix for problem with expansion code checking and incomplete value sets --- .../r5/terminologies/ValueSetCheckerSimple.java | 2 +- .../validation/tests/ValidationEngineTests.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java index 3bc0e2b24..4d0e53427 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java @@ -144,7 +144,7 @@ public class ValueSetCheckerSimple implements ValueSetChecker { throw new FHIRException(warningMessage); } - if (cs!=null) { + if (cs!=null && cs.getContent() == CodeSystemContentMode.COMPLETE) { res = validateCode(code, cs); } else { // it's in the expansion, but we could find it in a code system diff --git a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java index 8bf699c79..742437fe3 100644 --- a/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java +++ b/org.hl7.fhir.validation/src/test/java/org/hl7/fhir/validation/tests/ValidationEngineTests.java @@ -24,7 +24,7 @@ public class ValidationEngineTests { @Test public void testCurrentXml() throws Exception { if (!TestUtilities.silent) - System.out.println("Validate patient-example.xml in Current version"); + System.out.println("TestCurrentXml: Validate patient-example.xml in Current version"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, "4.0.1"); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient-example.xml"), null); int e = errors(op); @@ -44,7 +44,7 @@ public class ValidationEngineTests { @Test public void testCurrentJson() throws Exception { if (!TestUtilities.silent) - System.out.println("Validate patient-example.json in Current version"); + System.out.println("TestCurrentJson: Validate patient-example.json in Current version"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r4.core#4.0.1", DEF_TX, null, FhirPublication.R4, "4.0.1"); OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "patient-example.json"), null); int e = errors(op); @@ -64,7 +64,7 @@ public class ValidationEngineTests { return; } if (!TestUtilities.silent) - System.out.println("Validate patient-example.xml in v1.4.0 version"); + System.out.println("Test140: Validate patient-example.xml in v1.4.0 version"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r2b.core#1.4.0", DEF_TX, null, FhirPublication.DSTU2016May, "1.4.0"); ve.setNoInvariantChecks(true); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient140.xml"), null); @@ -89,7 +89,7 @@ public class ValidationEngineTests { return; } if (!org.hl7.fhir.validation.tests.utilities.TestUtilities.silent) - System.out.println("Validate patient-example.xml in v1.0.2 version"); + System.out.println("Test102: Validate patient-example.xml in v1.0.2 version"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "41.0.2"); ve.setNoInvariantChecks(true); OperationOutcome op = ve.validate(FhirFormat.XML, TestingUtilities.loadTestResourceStream("validator", "patient102.xml"), null); @@ -114,7 +114,7 @@ public class ValidationEngineTests { return; } if (!TestUtilities.silent) - System.out.println("Validate patient-example.xml in v1.0.2 version"); + System.out.println("TestObs102: Validate patient-example.xml in v1.0.2 version"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r2.core#1.0.2", DEF_TX, null, FhirPublication.DSTU2, "1.0.2"); ve.setNoInvariantChecks(true); OperationOutcome op = ve.validate(FhirFormat.JSON, TestingUtilities.loadTestResourceStream("validator", "observation102.json"), null); @@ -136,7 +136,7 @@ public class ValidationEngineTests { @Test public void test301() throws Exception { if (!TestUtilities.silent) - System.out.println("Validate observation301.xml against Core"); + System.out.println("Test301: Validate observation301.xml against Core"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2"); if (!TestUtilities.silent) System.out.println(" .. load USCore"); @@ -155,7 +155,7 @@ public class ValidationEngineTests { @Test public void test301USCore() throws Exception { if (!TestUtilities.silent) - System.out.println("Validate patient300.xml against US-Core"); + System.out.println("Test301USCore: Validate patient300.xml against US-Core"); ValidationEngine ve = new ValidationEngine("hl7.fhir.r3.core#3.0.2", DEF_TX, null, FhirPublication.STU3, "3.0.2"); if (!TestUtilities.silent) System.out.println(" .. load USCore"); From 23d62721c65e456b69d4b8548a752c26d862b6d3 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Thu, 6 Aug 2020 22:38:58 +1000 Subject: [PATCH 07/12] release notes --- RELEASE_NOTES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e69de29bb..cfe93a365 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -0,0 +1,9 @@ +Validator: +* Fix for problem with expansion code checking and incomplete value sets + +General Code changes: +* Work on connection problems to terminology server +* Fix for problem loading Measures from packages +* Work on i18n for Rendering +* fix case bug renderung bundles and parameters +* start working on i18n for Rendering \ No newline at end of file From 4add0f3ac88fe679439da5c1180e726262f03600 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Aug 2020 11:26:44 +1000 Subject: [PATCH 08/12] Continue to work on connection timeout issues --- .../fhir/dstu3/utils/client/ClientUtils.java | 39 +++++++++++-------- .../hl7/fhir/r4/utils/client/ClientUtils.java | 39 +++++++++++-------- .../hl7/fhir/r5/utils/client/ClientUtils.java | 39 +++++++++++-------- .../r5/utils/client/FHIRToolingClient.java | 3 +- 4 files changed, 71 insertions(+), 49 deletions(-) diff --git a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java index 0ecd807e7..9508a02ac 100644 --- a/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java +++ b/org.hl7.fhir.dstu3/src/main/java/org/hl7/fhir/dstu3/utils/client/ClientUtils.java @@ -107,6 +107,7 @@ public class ClientUtils { private String password; private ToolingClientLogger logger; private int retryCount; + private HttpClient httpclient; public HttpHost getProxy() { return proxy; @@ -291,14 +292,11 @@ public class ClientUtils { while (!ok) { try { tryCount++; - HttpClient httpclient = new DefaultHttpClient(); - HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); - HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); - - if(proxy != null) { - httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + if (httpclient == null) { + makeClient(proxy); } + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); request.setEntity(new ByteArrayEntity(payload)); log(request); response = httpclient.execute(request); @@ -313,7 +311,7 @@ public class ClientUtils { } } else { if (tryCount > 1) { - System.out.println("Giving up: "+ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); + System.out.println("Giving up: "+ioe.getMessage()+" (R3 / "+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); } throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); } @@ -322,6 +320,18 @@ public class ClientUtils { return response; } + @SuppressWarnings("deprecation") + public void makeClient(HttpHost proxy) { + httpclient = new DefaultHttpClient(); + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); + HttpConnectionParams.setSoTimeout(params, timeout); + HttpConnectionParams.setSoKeepalive(params, true); + if(proxy != null) { + httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + } + } + /** * * @param request @@ -331,13 +341,8 @@ public class ClientUtils { protected HttpResponse sendRequest(HttpUriRequest request) { HttpResponse response = null; try { - HttpClient httpclient = new DefaultHttpClient(); - log(request); - HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, timeout); - HttpConnectionParams.setSoTimeout(params, timeout); - if(proxy != null) { - httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + if (httpclient == null) { + makeClient(proxy); } response = httpclient.execute(request); } catch(IOException ioe) { @@ -582,7 +587,9 @@ public class ClientUtils { HttpResponse response = null; try { log(request); - HttpClient httpclient = new DefaultHttpClient(); + if (httpclient == null) { + makeClient(proxy); + } request.setEntity(new ByteArrayEntity(payload)); response = httpclient.execute(request); log(response); diff --git a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java index 442d7d7c3..c9d9ac2ae 100644 --- a/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java +++ b/org.hl7.fhir.r4/src/main/java/org/hl7/fhir/r4/utils/client/ClientUtils.java @@ -107,6 +107,7 @@ public class ClientUtils { private String password; private ToolingClientLogger logger; private int retryCount; + private HttpClient httpclient; public HttpHost getProxy() { return proxy; @@ -291,14 +292,11 @@ public class ClientUtils { while (!ok) { try { tryCount++; - HttpClient httpclient = new DefaultHttpClient(); - HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); - HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); - - if(proxy != null) { - httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + if (httpclient == null) { + makeClient(proxy); } + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); request.setEntity(new ByteArrayEntity(payload)); log(request); response = httpclient.execute(request); @@ -313,7 +311,7 @@ public class ClientUtils { } } else { if (tryCount > 1) { - System.out.println("Giving up: "+ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); + System.out.println("Giving up: "+ioe.getMessage()+" (R4 / "+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); } throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); } @@ -322,6 +320,18 @@ public class ClientUtils { return response; } + @SuppressWarnings("deprecation") + public void makeClient(HttpHost proxy) { + httpclient = new DefaultHttpClient(); + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); + HttpConnectionParams.setSoTimeout(params, timeout); + HttpConnectionParams.setSoKeepalive(params, true); + if(proxy != null) { + httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + } + } + /** * * @param request @@ -331,13 +341,8 @@ public class ClientUtils { protected HttpResponse sendRequest(HttpUriRequest request) { HttpResponse response = null; try { - HttpClient httpclient = new DefaultHttpClient(); - log(request); - HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, timeout); - HttpConnectionParams.setSoTimeout(params, timeout); - if(proxy != null) { - httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + if (httpclient == null) { + makeClient(proxy); } response = httpclient.execute(request); } catch(IOException ioe) { @@ -583,7 +588,9 @@ public class ClientUtils { HttpResponse response = null; try { log(request); - HttpClient httpclient = new DefaultHttpClient(); + if (httpclient == null) { + makeClient(proxy); + } request.setEntity(new ByteArrayEntity(payload)); response = httpclient.execute(request); log(response); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java index 1148d2018..12517281f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/ClientUtils.java @@ -107,6 +107,7 @@ public class ClientUtils { private String password; private ToolingClientLogger logger; private int retryCount; + private HttpClient httpclient; public HttpHost getProxy() { return proxy; @@ -291,14 +292,11 @@ public class ClientUtils { while (!ok) { try { tryCount++; - HttpClient httpclient = new DefaultHttpClient(); - HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); - HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); - - if(proxy != null) { - httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + if (httpclient == null) { + makeClient(proxy); } + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setSoTimeout(params, timeout < 1 ? this.timeout : timeout * 1000); request.setEntity(new ByteArrayEntity(payload)); log(request); response = httpclient.execute(request); @@ -313,7 +311,7 @@ public class ClientUtils { } } else { if (tryCount > 1) { - System.out.println("Giving up: "+ioe.getMessage()+" ("+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); + System.out.println("Giving up: "+ioe.getMessage()+" (R5 / "+(System.currentTimeMillis()-t)+"ms / "+Utilities.describeSize(payload.length)+" for "+message+")"); } throw new EFhirClientException("Error sending HTTP Post/Put Payload: "+ioe.getMessage(), ioe); } @@ -322,6 +320,18 @@ public class ClientUtils { return response; } + @SuppressWarnings("deprecation") + public void makeClient(HttpHost proxy) { + httpclient = new DefaultHttpClient(); + HttpParams params = httpclient.getParams(); + HttpConnectionParams.setConnectionTimeout(params, TIMEOUT_CONNECT); + HttpConnectionParams.setSoTimeout(params, timeout); + HttpConnectionParams.setSoKeepalive(params, true); + if(proxy != null) { + httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + } + } + /** * * @param request @@ -331,13 +341,8 @@ public class ClientUtils { protected HttpResponse sendRequest(HttpUriRequest request) { HttpResponse response = null; try { - HttpClient httpclient = new DefaultHttpClient(); - log(request); - HttpParams params = httpclient.getParams(); - HttpConnectionParams.setConnectionTimeout(params, timeout); - HttpConnectionParams.setSoTimeout(params, timeout); - if(proxy != null) { - httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); + if (httpclient == null) { + makeClient(proxy); } response = httpclient.execute(request); } catch(IOException ioe) { @@ -583,7 +588,9 @@ public class ClientUtils { HttpResponse response = null; try { log(request); - HttpClient httpclient = new DefaultHttpClient(); + if (httpclient == null) { + makeClient(proxy); + } request.setEntity(new ByteArrayEntity(payload)); response = httpclient.execute(request); log(response); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java index f56896d7b..1e9c94af7 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/client/FHIRToolingClient.java @@ -728,8 +728,9 @@ public class FHIRToolingClient { List
headers = null; Parameters p = expParams == null ? new Parameters() : expParams.copy(); p.addParameter().setName("valueSet").setResource(source); - for (String n : params.keySet()) + for (String n : params.keySet()) { p.addParameter().setName(n).setValue(new StringType(params.get(n))); + } ResourceRequest result = utils.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params), utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(), headers, "ValueSet/$expand?url="+source.getUrl(), TIMEOUT_OPERATION_EXPAND); result.addErrorStatus(410);//gone From 800e381629389a0ce13434b41d0de24cc53857a7 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Aug 2020 11:27:57 +1000 Subject: [PATCH 09/12] Fix bug in DiagnosticReportRenderer (wrong element accessed) --- .../main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java | 3 ++- .../org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java index 3062c0734..d8ed01548 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/context/BaseWorkerContext.java @@ -570,8 +570,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte CacheToken cacheToken = txCache.generateExpandToken(vs, hierarchical); ValueSetExpansionOutcome res; res = txCache.getExpansion(cacheToken); - if (res != null) + if (res != null) { return res; + } Parameters p = expParameters.copy(); p.setParameter("includeDefinition", false); p.setParameter("excludeNested", !hierarchical); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java index 9a2daa048..d026fcab5 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/DiagnosticReportRenderer.java @@ -79,7 +79,7 @@ public class DiagnosticReportRenderer extends ResourceRenderer { if (dr.has("issued")) { tr = tbl.tr(); tr.td().tx("Reported"); - eff = (DataType) getProperty(dr, "effective[x]").value().getBase(); + eff = (DataType) getProperty(dr, "issued").value().getBase(); render(tr.td(), getProperty(dr, "issued").value()); } From a12b1bdc9341f7b75298f3dd168852e64d33aa58 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Aug 2020 11:28:18 +1000 Subject: [PATCH 10/12] change type of resource parameter to ResourceRender.build --- .../main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java index 1904b74cd..61fd75c3f 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/renderers/ResourceRenderer.java @@ -50,7 +50,7 @@ public abstract class ResourceRenderer extends DataRenderer { this.rcontext = rcontext; } - public XhtmlNode build(DomainResource dr) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { + public XhtmlNode build(Resource dr) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome { XhtmlNode x = new XhtmlNode(NodeType.Element, "div"); render(x, dr); return x; From ad07997c5d649124cd001286e1ff8f5b11da2276 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Aug 2020 11:30:31 +1000 Subject: [PATCH 11/12] fix bug handling fragment code systems with value sets with pre-build expansions --- .../r5/terminologies/ValueSetCheckerSimple.java | 2 +- .../org/hl7/fhir/r5/utils/ResourceUtilities.java | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java index 4d0e53427..41933ffb6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/terminologies/ValueSetCheckerSimple.java @@ -144,7 +144,7 @@ public class ValueSetCheckerSimple implements ValueSetChecker { throw new FHIRException(warningMessage); } - if (cs!=null && cs.getContent() == CodeSystemContentMode.COMPLETE) { + if (cs!=null && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) { res = validateCode(code, cs); } else { // it's in the expansion, but we could find it in a code system diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceUtilities.java index 8c5f3077a..0cf3e1fa6 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ResourceUtilities.java @@ -72,19 +72,22 @@ public class ResourceUtilities { } public static String getErrorDescription(OperationOutcome error) { - if (error.hasText() && error.getText().hasDiv()) + if (error.hasText() && error.getText().hasDiv()) { return new XhtmlComposer(XhtmlComposer.XML).composePlainText(error.getText().getDiv()); + } StringBuilder b = new StringBuilder(); - for (OperationOutcomeIssueComponent t : error.getIssue()) - if (t.getSeverity() == IssueSeverity.ERROR) + for (OperationOutcomeIssueComponent t : error.getIssue()) { + if (t.getSeverity() == IssueSeverity.ERROR) { b.append("Error:" +t.getDetails()+"\r\n"); - else if (t.getSeverity() == IssueSeverity.FATAL) + } else if (t.getSeverity() == IssueSeverity.FATAL) { b.append("Fatal:" +t.getDetails()+"\r\n"); - else if (t.getSeverity() == IssueSeverity.WARNING) + } else if (t.getSeverity() == IssueSeverity.WARNING) { b.append("Warning:" +t.getDetails()+"\r\n"); - else if (t.getSeverity() == IssueSeverity.INFORMATION) + } else if (t.getSeverity() == IssueSeverity.INFORMATION) { b.append("Information:" +t.getDetails()+"\r\n"); + } + } return b.toString(); } From deeae26b42663c8b14704beb7f48b44cb1b102fd Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Fri, 7 Aug 2020 11:37:38 +1000 Subject: [PATCH 12/12] release notes --- RELEASE_NOTES.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index cfe93a365..410f872bb 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,9 +1,7 @@ Validator: -* Fix for problem with expansion code checking and incomplete value sets +* no changes -General Code changes: -* Work on connection problems to terminology server -* Fix for problem loading Measures from packages -* Work on i18n for Rendering -* fix case bug renderung bundles and parameters -* start working on i18n for Rendering \ No newline at end of file +Other code: +* Continue to work on connection timeout issues +* Fix bug in DiagnosticReportRenderer (wrong element accessed) +* change type of resource parameter to ResourceRender.build \ No newline at end of file