Skip to content

Commit f293b48

Browse files
[7367] Fix value set not found with remote terminology service (#7368)
* [7367] Fix value set not found with remote terminology service * [7367] Fix unit tests * [7367] update changelog * [7367] address review comments * [7367] change to optionalParam --------- Co-authored-by: jmarchionatto <[email protected]>
1 parent 9d79d95 commit f293b48

File tree

4 files changed

+66
-27
lines changed

4 files changed

+66
-27
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
type: fix
3+
issue: 7367
4+
title: "Previously, when the Remote Terminology Service was enabled and its base URL was set to
5+
[https://r4.ontoserver.csiro.au/fhir/](https://r4.ontoserver.csiro.au/fhir/), some `$validate` requests returned
6+
a 404 Not Found, and the OperationOutcome in the response contained error messages indicating the referenced `ValueSet`
7+
could not be found. This has now been fixed."
8+
9+

hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/interceptor/RemoteTerminologyServiceJpaR4Test.java

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import ca.uhn.fhir.rest.annotation.Search;
1212
import ca.uhn.fhir.rest.api.EncodingEnum;
1313
import ca.uhn.fhir.rest.api.ValidationModeEnum;
14+
import ca.uhn.fhir.rest.param.TokenParam;
1415
import ca.uhn.fhir.rest.param.UriParam;
1516
import ca.uhn.fhir.rest.server.IResourceProvider;
1617
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
@@ -122,8 +123,8 @@ public void testValidateSimpleCode() {
122123

123124
// Verify 1
124125
Assertions.assertEquals(2, myCaptureQueriesListener.countGetConnections());
125-
assertThat(ourValueSetProvider.mySearchUrls).asList().containsExactlyInAnyOrder(
126-
"http://hl7.org/fhir/ValueSet/administrative-gender|4.0.1",
126+
assertThat(ourValueSetProvider.mySearchParams).asList().containsExactlyInAnyOrder(
127+
"http://hl7.org/fhir/ValueSet/administrative-gender", "4.0.1",
127128
"http://hl7.org/fhir/ValueSet/administrative-gender","http://hl7.org/fhir/ValueSet/administrative-gender"
128129
);
129130
assertThat(ourCodeSystemProvider.mySearchUrls).asList().containsExactlyInAnyOrder(
@@ -140,7 +141,7 @@ public void testValidateSimpleCode() {
140141

141142
// Verify 2
142143
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
143-
assertThat(ourValueSetProvider.mySearchUrls).asList().isEmpty();
144+
assertThat(ourValueSetProvider.mySearchParams).asList().isEmpty();
144145
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
145146

146147
}
@@ -161,8 +162,8 @@ public void testValidateSimpleCode_SupportedByRemoteService() {
161162

162163
// Verify 1
163164
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
164-
assertThat(ourValueSetProvider.mySearchUrls).asList().containsExactlyInAnyOrder(
165-
"http://hl7.org/fhir/ValueSet/administrative-gender|4.0.1",
165+
assertThat(ourValueSetProvider.mySearchParams).asList().containsExactlyInAnyOrder(
166+
"http://hl7.org/fhir/ValueSet/administrative-gender", "4.0.1",
166167
"http://hl7.org/fhir/ValueSet/administrative-gender"
167168
);
168169
assertThat(ourValueSetProvider.myValidatedCodes).asList().containsExactlyInAnyOrder(
@@ -184,7 +185,7 @@ public void testValidateSimpleCode_SupportedByRemoteService() {
184185

185186
// Verify 2
186187
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
187-
assertThat(ourValueSetProvider.mySearchUrls).asList().isEmpty();
188+
assertThat(ourValueSetProvider.mySearchParams).asList().isEmpty();
188189
assertThat(ourValueSetProvider.myValidatedCodes).asList().isEmpty();
189190
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
190191
assertThat(ourCodeSystemProvider.myValidatedCodes).asList().isEmpty();
@@ -214,19 +215,15 @@ public void testValidateSimpleCode_SupportedByRemoteService_EmptyValueSet() {
214215

215216
// Verify 1
216217
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
217-
assertThat(ourValueSetProvider.mySearchUrls).asList().containsExactlyInAnyOrder(
218-
"http://hl7.org/fhir/ValueSet/administrative-gender|4.0.1",
218+
assertThat(ourValueSetProvider.mySearchParams).asList().containsExactlyInAnyOrder(
219+
"http://hl7.org/fhir/ValueSet/administrative-gender", "4.0.1",
219220
"http://hl7.org/fhir/ValueSet/administrative-gender"
220221
);
221222
assertThat(ourValueSetProvider.myValidatedCodes).asList().containsExactlyInAnyOrder(
222-
"http://hl7.org/fhir/ValueSet/administrative-gender#http://hl7.org/fhir/administrative-gender#female"
223-
);
224-
assertThat(ourCodeSystemProvider.mySearchUrls).asList().containsExactlyInAnyOrder(
225-
"http://hl7.org/fhir/administrative-gender"
226-
);
227-
assertThat(ourCodeSystemProvider.myValidatedCodes).asList().containsExactlyInAnyOrder(
228-
"http://hl7.org/fhir/administrative-gender#female#null"
223+
"http://hl7.org/fhir/ValueSet/administrative-gender#null#female"
229224
);
225+
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
226+
assertThat(ourCodeSystemProvider.myValidatedCodes).asList().isEmpty();
230227

231228
// Test 2 (should rely on caches)
232229
ourCodeSystemProvider.clearCalls();
@@ -237,7 +234,7 @@ public void testValidateSimpleCode_SupportedByRemoteService_EmptyValueSet() {
237234

238235
// Verify 2
239236
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
240-
assertThat(ourValueSetProvider.mySearchUrls).asList().isEmpty();
237+
assertThat(ourValueSetProvider.mySearchParams).asList().isEmpty();
241238
assertThat(ourValueSetProvider.myValidatedCodes).asList().isEmpty();
242239
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
243240
assertThat(ourCodeSystemProvider.myValidatedCodes).asList().isEmpty();
@@ -262,7 +259,7 @@ public void testValidateSimpleExtension() {
262259
// Verify 1
263260
myCaptureQueriesListener.logSelectQueries();
264261
Assertions.assertEquals(3, myCaptureQueriesListener.countGetConnections());
265-
assertThat(ourValueSetProvider.mySearchUrls).asList().isEmpty();
262+
assertThat(ourValueSetProvider.mySearchParams).asList().isEmpty();
266263
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
267264

268265
// Test 2 (should rely on caches)
@@ -274,7 +271,7 @@ public void testValidateSimpleExtension() {
274271

275272
// Verify 2
276273
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
277-
assertThat(ourValueSetProvider.mySearchUrls).asList().isEmpty();
274+
assertThat(ourValueSetProvider.mySearchParams).asList().isEmpty();
278275
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
279276

280277
}
@@ -310,7 +307,7 @@ public void testValidateMultipleCodings() {
310307

311308
// Verify 1
312309
Assertions.assertEquals(2, myCaptureQueriesListener.countGetConnections());
313-
assertThat(ourValueSetProvider.mySearchUrls).asList().containsExactlyInAnyOrder(
310+
assertThat(ourValueSetProvider.mySearchParams).asList().containsExactlyInAnyOrder(
314311
"http://hl7.org/fhir/ValueSet/identifier-type",
315312
"http://hl7.org/fhir/ValueSet/identifier-type"
316313
);
@@ -329,7 +326,7 @@ public void testValidateMultipleCodings() {
329326

330327
// Verify 2
331328
Assertions.assertEquals(0, myCaptureQueriesListener.countGetConnections());
332-
assertThat(ourValueSetProvider.mySearchUrls).asList().isEmpty();
329+
assertThat(ourValueSetProvider.mySearchParams).asList().isEmpty();
333330
assertThat(ourCodeSystemProvider.mySearchUrls).asList().isEmpty();
334331
assertEquals(0, ourValueSetProvider.myValidatedCodes.size());
335332
assertEquals(0, ourCodeSystemProvider.myValidatedCodes.size());
@@ -443,7 +440,7 @@ public void add(CodeSystem theCs) {
443440
private static class MyValueSetProvider implements IResourceProvider {
444441

445442
private final ListMultimap<String, ValueSet> myUrlToValueSets = MultimapBuilder.hashKeys().arrayListValues().build();
446-
private final List<String> mySearchUrls = new ArrayList<>();
443+
private final List<String> mySearchParams = new ArrayList<>();
447444
private final List<String> myValidatedCodes = new ArrayList<>();
448445

449446
public void clearAll() {
@@ -452,7 +449,7 @@ public void clearAll() {
452449
}
453450

454451
public void clearCalls() {
455-
mySearchUrls.clear();
452+
mySearchParams.clear();
456453
myValidatedCodes.clear();
457454
}
458455

@@ -477,9 +474,14 @@ public Parameters validateCode(
477474
}
478475

479476
@Search
480-
public List<ValueSet> find(@OptionalParam(name = "url") UriParam theUrlParam) {
477+
public List<ValueSet> find(@OptionalParam(name = "url") UriParam theUrlParam,
478+
@OptionalParam(name = "version") TokenParam theVersion) {
481479
String url = theUrlParam != null ? theUrlParam.getValue() : null;
482-
mySearchUrls.add(url);
480+
mySearchParams.add(url);
481+
482+
if (theVersion != null) {
483+
mySearchParams.add(theVersion.getValue());
484+
}
483485
List<ValueSet> retVal = myUrlToValueSets.get(defaultString(url));
484486
ourLog.info("Remote terminology fetch ValueSet[{}] - Found: {}", url, !retVal.isEmpty());
485487
return retVal;

hapi-fhir-test-utilities/src/main/java/ca/uhn/fhir/test/utilities/validation/IValidationProvidersR4.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@
2222
import ca.uhn.fhir.rest.annotation.IdParam;
2323
import ca.uhn.fhir.rest.annotation.Operation;
2424
import ca.uhn.fhir.rest.annotation.OperationParam;
25+
import ca.uhn.fhir.rest.annotation.OptionalParam;
26+
import ca.uhn.fhir.rest.annotation.Search;
2527
import ca.uhn.fhir.rest.api.server.RequestDetails;
28+
import ca.uhn.fhir.rest.param.TokenParam;
29+
import ca.uhn.fhir.rest.param.UriParam;
2630
import jakarta.servlet.http.HttpServletRequest;
31+
import org.apache.commons.lang3.StringUtils;
2732
import org.hl7.fhir.instance.model.api.IBaseParameters;
2833
import org.hl7.fhir.instance.model.api.IBaseResource;
2934
import org.hl7.fhir.r4.model.BooleanType;
@@ -130,14 +135,29 @@ public IBaseParameters validateCode(
130135
String code = theCode != null ? theCode.getValue() : null;
131136
return getTerminologyResponse("$validate-code", url, code);
132137
}
138+
139+
@Search
140+
public List<ValueSet> find(@OptionalParam(name = "url") UriParam theUrlParam,
141+
@OptionalParam(name = "version") TokenParam theVersionParam) {
142+
ValueSet valueSet = getTerminologyResource(theUrlParam);
143+
String version = theVersionParam.getValue();
144+
if (valueSet != null && StringUtils.isNotEmpty(version)) {
145+
valueSet.setVersion(version);
146+
}
147+
148+
return valueSet != null ? List.of(valueSet) : List.of();
149+
}
150+
133151
@Override
134152
public Class<? extends IBaseResource> getResourceType() {
135153
return ValueSet.class;
136154
}
155+
137156
@Override
138157
Class<Parameters> getParameterType() {
139158
return Parameters.class;
140159
}
160+
141161
@Override
142162
public ValueSet addTerminologyResource(String theUrl) {
143163
ValueSet valueSet = new ValueSet();

hapi-fhir-validation/src/main/java/org/hl7/fhir/common/hapi/validation/support/RemoteTerminologyServiceValidationSupport.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import ca.uhn.fhir.rest.client.api.IGenericClient;
1414
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
1515
import ca.uhn.fhir.rest.gclient.IQuery;
16+
import ca.uhn.fhir.rest.gclient.StringClientParam;
1617
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
1718
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
1819
import ca.uhn.fhir.util.BundleUtil;
@@ -544,9 +545,16 @@ private IBaseResource fetchValueSet(String theValueSetUrl, SummaryEnum theSummar
544545
Class<? extends IBaseBundle> bundleType =
545546
myCtx.getResourceDefinition("Bundle").getImplementingClass(IBaseBundle.class);
546547

547-
IQuery<IBaseBundle> valueSetQuery = client.search()
548-
.forResource("ValueSet")
549-
.where(CodeSystem.URL.matches().value(theValueSetUrl));
548+
IQuery<IBaseBundle> valueSetQuery = client.search().forResource("ValueSet");
549+
550+
int pipeIdx = theValueSetUrl.indexOf("|");
551+
if (pipeIdx < 0) {
552+
valueSetQuery.where(CodeSystem.URL.matches().value(theValueSetUrl));
553+
} else {
554+
valueSetQuery.where(CodeSystem.URL.matches().value(theValueSetUrl.substring(0, pipeIdx)));
555+
valueSetQuery.where(
556+
new StringClientParam("version").matches().value(theValueSetUrl.substring(pipeIdx + 1)));
557+
}
550558

551559
if (theSummaryParam != null) {
552560
valueSetQuery.summaryMode(theSummaryParam);

0 commit comments

Comments
 (0)