FIx test issue

This commit is contained in:
jamesagnew 2018-07-29 18:20:09 -04:00
parent 518092cbd4
commit fc9f2ec0fb
5 changed files with 113 additions and 91 deletions

View File

@ -9,9 +9,9 @@ package ca.uhn.fhir.rest.server.exceptions;
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -19,11 +19,13 @@ package ca.uhn.fhir.rest.server.exceptions;
* limitations under the License. * limitations under the License.
* #L% * #L%
*/ */
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.util.CoverageIgnore; import ca.uhn.fhir.util.CoverageIgnore;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
/** /**
* Represents an <b>HTTP 410 Resource Gone</b> response, which geenerally * Represents an <b>HTTP 410 Resource Gone</b> response, which geenerally
@ -33,12 +35,12 @@ import ca.uhn.fhir.util.CoverageIgnore;
public class ResourceGoneException extends BaseServerResponseException { public class ResourceGoneException extends BaseServerResponseException {
public static final int STATUS_CODE = Constants.STATUS_HTTP_410_GONE; public static final int STATUS_CODE = Constants.STATUS_HTTP_410_GONE;
private static final long serialVersionUID = 1L;
/** /**
* Constructor which creates an error message based on a given resource ID * Constructor which creates an error message based on a given resource ID
* *
* @param theResourceId * @param theResourceId The ID of the resource that could not be found
* The ID of the resource that could not be found
*/ */
public ResourceGoneException(IIdType theResourceId) { public ResourceGoneException(IIdType theResourceId) {
super(STATUS_CODE, "Resource " + (theResourceId != null ? theResourceId.getValue() : "") + " is gone/deleted"); super(STATUS_CODE, "Resource " + (theResourceId != null ? theResourceId.getValue() : "") + " is gone/deleted");
@ -46,7 +48,7 @@ public class ResourceGoneException extends BaseServerResponseException {
/** /**
* @deprecated This constructor has a dependency on a specific model version and will be removed. Deprecated in HAPI * @deprecated This constructor has a dependency on a specific model version and will be removed. Deprecated in HAPI
* 1.6 - 2016-07-02 * 1.6 - 2016-07-02
*/ */
@Deprecated @Deprecated
public ResourceGoneException(Class<? extends IBaseResource> theClass, BaseIdentifierDt thePatientId) { public ResourceGoneException(Class<? extends IBaseResource> theClass, BaseIdentifierDt thePatientId) {
@ -55,11 +57,9 @@ public class ResourceGoneException extends BaseServerResponseException {
/** /**
* Constructor which creates an error message based on a given resource ID * Constructor which creates an error message based on a given resource ID
* *
* @param theClass * @param theClass The type of resource that could not be found
* The type of resource that could not be found * @param theResourceId The ID of the resource that could not be found
* @param theResourceId
* The ID of the resource that could not be found
*/ */
public ResourceGoneException(Class<? extends IBaseResource> theClass, IIdType theResourceId) { public ResourceGoneException(Class<? extends IBaseResource> theClass, IIdType theResourceId) {
super(STATUS_CODE, "Resource of type " + theClass.getSimpleName() + " with ID " + theResourceId + " is gone/deleted"); super(STATUS_CODE, "Resource of type " + theClass.getSimpleName() + " with ID " + theResourceId + " is gone/deleted");
@ -67,20 +67,21 @@ public class ResourceGoneException extends BaseServerResponseException {
/** /**
* Constructor * Constructor
* *
* @param theMessage * @param theMessage The message
* The message * @param theOperationOutcome The OperationOutcome resource to return to the client
* @param theOperationOutcome
* The OperationOutcome resource to return to the client
*/ */
public ResourceGoneException(String theMessage, IBaseOperationOutcome theOperationOutcome) { public ResourceGoneException(String theMessage, IBaseOperationOutcome theOperationOutcome) {
super(STATUS_CODE, theMessage, theOperationOutcome); super(STATUS_CODE, theMessage, theOperationOutcome);
} }
/**
* Constructor
*
* @param theMessage The message
*/
public ResourceGoneException(String theMessage) { public ResourceGoneException(String theMessage) {
super(STATUS_CODE, theMessage); super(STATUS_CODE, theMessage);
} }
private static final long serialVersionUID = 1L;
} }

View File

@ -36,7 +36,7 @@ public class FifoMemoryPagingProvider extends BasePagingProvider implements IPag
Validate.isTrue(theSize > 0, "theSize must be greater than 0"); Validate.isTrue(theSize > 0, "theSize must be greater than 0");
mySize = theSize; mySize = theSize;
myBundleProviders = new LinkedHashMap<String, IBundleProvider>(mySize); myBundleProviders = new LinkedHashMap<>(mySize);
} }
@Override @Override

View File

@ -98,12 +98,16 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
} }
if (pageId != null) { if (pageId != null) {
// This is a page request by Search ID and Page ID
resultList = pagingProvider.retrieveResultList(thePagingAction, pageId); resultList = pagingProvider.retrieveResultList(thePagingAction, pageId);
validateHaveBundleProvider(thePagingAction, resultList);
} else { } else {
// This is a page request by Search ID and Offset
resultList = pagingProvider.retrieveResultList(thePagingAction); resultList = pagingProvider.retrieveResultList(thePagingAction);
validateHaveBundleProvider(thePagingAction, resultList);
offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET); offsetI = RestfulServerUtils.tryToExtractNamedParameter(theRequest, Constants.PARAM_PAGINGOFFSET);
if (offsetI == null || offsetI < 0) { if (offsetI == null || offsetI < 0) {
@ -117,13 +121,6 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
} }
} }
// Return an HTTP 409 if the search is not known
if (resultList == null) {
ourLog.info("Client requested unknown paging ID[{}]", thePagingAction);
String msg = getContext().getLocalizer().getMessage(PageMethodBinding.class, "unknownSearchId", thePagingAction);
throw new ResourceGoneException(msg);
}
ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding()); ResponseEncoding responseEncoding = RestfulServerUtils.determineResponseEncodingNoDefault(theRequest, theServer.getDefaultResponseEncoding());
Set<Include> includes = new HashSet<>(); Set<Include> includes = new HashSet<>();
@ -160,6 +157,15 @@ public class PageMethodBinding extends BaseResourceReturningMethodBinding {
return createBundleFromBundleProvider(theServer, theRequest, count, linkSelf, includes, resultList, start, bundleType, encodingEnum, thePagingAction); return createBundleFromBundleProvider(theServer, theRequest, count, linkSelf, includes, resultList, start, bundleType, encodingEnum, thePagingAction);
} }
private void validateHaveBundleProvider(String thePagingAction, IBundleProvider theBundleProvider) {
// Return an HTTP 410 if the search is not known
if (theBundleProvider == null) {
ourLog.info("Client requested unknown paging ID[{}]", thePagingAction);
String msg = getContext().getLocalizer().getMessage(PageMethodBinding.class, "unknownSearchId", thePagingAction);
throw new ResourceGoneException(msg);
}
}
@Override @Override
public RestOperationTypeEnum getRestOperationType() { public RestOperationTypeEnum getRestOperationType() {
return RestOperationTypeEnum.GET_PAGE; return RestOperationTypeEnum.GET_PAGE;

View File

@ -36,8 +36,8 @@ import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -50,6 +50,7 @@ public class PagingUsingNamedPagesR4Test {
private static Server ourServer; private static Server ourServer;
private static RestfulServer servlet; private static RestfulServer servlet;
private static IBundleProvider ourNextBundleProvider;
private IPagingProvider myPagingProvider; private IPagingProvider myPagingProvider;
@Before @Before
@ -59,6 +60,17 @@ public class PagingUsingNamedPagesR4Test {
ourNextBundleProvider = null; ourNextBundleProvider = null;
} }
private List<IBaseResource> createPatients(int theLow, int theHigh) {
List<IBaseResource> patients = new ArrayList<>();
for (int id = theLow; id <= theHigh; id++) {
Patient pt = new Patient();
pt.setId("Patient/" + id);
pt.addName().setFamily("FAM" + id);
patients.add(pt);
}
return patients;
}
private Bundle executeAndReturnBundle(HttpGet httpGet, EncodingEnum theExpectEncoding) throws IOException { private Bundle executeAndReturnBundle(HttpGet httpGet, EncodingEnum theExpectEncoding) throws IOException {
Bundle bundle; Bundle bundle;
try (CloseableHttpResponse status = ourClient.execute(httpGet)) { try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
@ -74,32 +86,6 @@ public class PagingUsingNamedPagesR4Test {
return bundle; return bundle;
} }
@Test
public void testPagingLinksSanitizeBundleType() throws Exception {
List<IBaseResource> patients0 = createPatients(0, 9);
BundleProviderWithNamedPages provider0 = new BundleProviderWithNamedPages(patients0, "SEARCHID0", "PAGEID0", 1000);
provider0.setNextPageId("PAGEID1");
when(myPagingProvider.retrieveResultList(eq("SEARCHID0"), eq("PAGEID0"))).thenReturn(provider0);
// Initial search
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "?_getpages=SEARCHID0&pageId=PAGEID0&_format=xml&_bundletype=FOO" + UrlUtil.escapeUrlParam("\""));
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(responseContent);
assertThat(responseContent, not(containsString("FOO\"")));
assertEquals(200, status.getStatusLine().getStatusCode());
EncodingEnum ct = EncodingEnum.forContentType(status.getEntity().getContentType().getValue().replaceAll(";.*", "").trim());
assert ct != null;
Bundle bundle = EncodingEnum.XML.newParser(ourCtx).parseResource(Bundle.class, responseContent);
assertEquals(10, bundle.getEntry().size());
}
}
@Test @Test
public void testPaging() throws Exception { public void testPaging() throws Exception {
@ -131,43 +117,79 @@ public class PagingUsingNamedPagesR4Test {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=xml"); httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_format=xml");
bundle = executeAndReturnBundle(httpGet, EncodingEnum.XML); bundle = executeAndReturnBundle(httpGet, EncodingEnum.XML);
linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl(); linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl();
assertEquals("http://localhost:"+ourPort+"/Patient?_format=xml", linkSelf); assertEquals("http://localhost:" + ourPort + "/Patient?_format=xml", linkSelf);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl(); linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertEquals("http://localhost:"+ourPort+"?_getpages=SEARCHID0&pageId=PAGEID1&_format=xml&_bundletype=searchset", linkNext); assertEquals("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID1&_format=xml&_bundletype=searchset", linkNext);
assertNull(bundle.getLink(Constants.LINK_PREVIOUS)); assertNull(bundle.getLink(Constants.LINK_PREVIOUS));
// Fetch the next page // Fetch the next page
httpGet = new HttpGet(linkNext); httpGet = new HttpGet(linkNext);
bundle = executeAndReturnBundle(httpGet, EncodingEnum.XML); bundle = executeAndReturnBundle(httpGet, EncodingEnum.XML);
linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl(); linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl();
assertEquals("http://localhost:"+ourPort+"?_getpages=SEARCHID0&pageId=PAGEID1&_format=xml&_bundletype=searchset", linkSelf); assertEquals("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID1&_format=xml&_bundletype=searchset", linkSelf);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl(); linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertEquals("http://localhost:"+ourPort+"?_getpages=SEARCHID0&pageId=PAGEID2&_format=xml&_bundletype=searchset", linkNext); assertEquals("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID2&_format=xml&_bundletype=searchset", linkNext);
linkPrev = bundle.getLink(Constants.LINK_PREVIOUS).getUrl(); linkPrev = bundle.getLink(Constants.LINK_PREVIOUS).getUrl();
assertEquals("http://localhost:"+ourPort+"?_getpages=SEARCHID0&pageId=PAGEID0&_format=xml&_bundletype=searchset", linkPrev); assertEquals("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID0&_format=xml&_bundletype=searchset", linkPrev);
// Fetch the next page // Fetch the next page
httpGet = new HttpGet(linkNext); httpGet = new HttpGet(linkNext);
bundle = executeAndReturnBundle(httpGet, EncodingEnum.XML); bundle = executeAndReturnBundle(httpGet, EncodingEnum.XML);
linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl(); linkSelf = bundle.getLink(Constants.LINK_SELF).getUrl();
assertEquals("http://localhost:"+ourPort+"?_getpages=SEARCHID0&pageId=PAGEID2&_format=xml&_bundletype=searchset", linkSelf); assertEquals("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID2&_format=xml&_bundletype=searchset", linkSelf);
assertNull(bundle.getLink(Constants.LINK_NEXT)); assertNull(bundle.getLink(Constants.LINK_NEXT));
linkPrev = bundle.getLink(Constants.LINK_PREVIOUS).getUrl(); linkPrev = bundle.getLink(Constants.LINK_PREVIOUS).getUrl();
assertEquals("http://localhost:"+ourPort+"?_getpages=SEARCHID0&pageId=PAGEID1&_format=xml&_bundletype=searchset", linkPrev); assertEquals("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID1&_format=xml&_bundletype=searchset", linkPrev);
} }
private List<IBaseResource> createPatients(int theLow, int theHigh) { @Test
List<IBaseResource> patients = new ArrayList<>(); public void testPagingLinkUnknownPage() throws Exception {
for (int id = theLow; id <= theHigh; id++) {
Patient pt = new Patient(); when(myPagingProvider.retrieveResultList(nullable(String.class))).thenReturn(null);
pt.setId("Patient/" + id); when(myPagingProvider.retrieveResultList(nullable(String.class), nullable(String.class))).thenReturn(null);
pt.addName().setFamily("FAM" + id);
patients.add(pt); // With ID
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID0&_format=xml&_bundletype=FOO" + UrlUtil.escapeUrlParam("\""));
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(responseContent);
assertThat(responseContent, not(containsString("FOO\"")));
assertEquals(410, status.getStatusLine().getStatusCode());
} }
return patients;
// Without ID
httpGet = new HttpGet("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_format=xml&_bundletype=FOO" + UrlUtil.escapeUrlParam("\""));
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(responseContent);
assertThat(responseContent, not(containsString("FOO\"")));
assertEquals(410, status.getStatusLine().getStatusCode());
}
} }
@Test
public void testPagingLinksSanitizeBundleType() throws Exception {
List<IBaseResource> patients0 = createPatients(0, 9);
BundleProviderWithNamedPages provider0 = new BundleProviderWithNamedPages(patients0, "SEARCHID0", "PAGEID0", 1000);
provider0.setNextPageId("PAGEID1");
when(myPagingProvider.retrieveResultList(eq("SEARCHID0"), eq("PAGEID0"))).thenReturn(provider0);
// Initial search
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "?_getpages=SEARCHID0&_pageId=PAGEID0&_format=xml&_bundletype=FOO" + UrlUtil.escapeUrlParam("\""));
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(responseContent);
assertThat(responseContent, not(containsString("FOO\"")));
assertEquals(200, status.getStatusLine().getStatusCode());
EncodingEnum ct = EncodingEnum.forContentType(status.getEntity().getContentType().getValue().replaceAll(";.*", "").trim());
assert ct != null;
Bundle bundle = EncodingEnum.XML.newParser(ourCtx).parseResource(Bundle.class, responseContent);
assertEquals(10, bundle.getEntry().size());
}
}
@AfterClass @AfterClass
public static void afterClassClearContext() throws Exception { public static void afterClassClearContext() throws Exception {
@ -201,7 +223,6 @@ public class PagingUsingNamedPagesR4Test {
} }
private static IBundleProvider ourNextBundleProvider;
public static class DummyPatientResourceProvider implements IResourceProvider { public static class DummyPatientResourceProvider implements IResourceProvider {
@ -222,5 +243,4 @@ public class PagingUsingNamedPagesR4Test {
} }
} }

35
pom.xml
View File

@ -96,10 +96,6 @@
</dependency> </dependency>
</dependencies> </dependencies>
<prerequisites>
<maven>3.2</maven>
</prerequisites>
<developers> <developers>
<developer> <developer>
<id>jamesagnew</id> <id>jamesagnew</id>
@ -1615,29 +1611,28 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId> <artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version> <version>3.0.0-M2</version>
<executions> <executions>
<execution> <execution>
<id>enforce-java</id> <id>enforce-maven</id>
<goals> <goals>
<goal>enforce</goal> <goal>enforce</goal>
</goals> </goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.3.1</version>
</requireMavenVersion>
<requireJavaVersion>
<version>1.8</version>
<message>
The hapi-fhir Maven build requires JDK version 1.8.x.
</message>
</requireJavaVersion>
</rules>
</configuration>
</execution> </execution>
</executions> </executions>
<configuration>
<rules>
<requireMavenVersion>
<version>3.3</version>
</requireMavenVersion>
<requireJavaVersion>
<!--<version>[1.8,)</version>-->
<version>1.8</version>
<message>
The hapi-fhir Maven build requires JDK version 1.8.x.
</message>
</requireJavaVersion>
</rules>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>