Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
James 2017-06-29 22:16:46 -04:00
commit d81565b87c
13 changed files with 482 additions and 272 deletions

View File

@ -32,6 +32,7 @@ import ca.uhn.fhir.model.api.IQueryParameterType;
public class NumberParam extends BaseParamWithPrefix<NumberParam> implements IQueryParameterType {
private static final long serialVersionUID = 1L;
private BigDecimal myQuantity;
/**
@ -41,6 +42,16 @@ public class NumberParam extends BaseParamWithPrefix<NumberParam> implements IQu
super();
}
/**
* Constructor
*
* @param theValue
* A value, e.g. "10"
*/
public NumberParam(int theValue) {
setValue(new BigDecimal(theValue));
}
/**
* Constructor
*
@ -79,14 +90,6 @@ public class NumberParam extends BaseParamWithPrefix<NumberParam> implements IQu
}
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE);
b.append("prefix", getPrefix());
b.append("value", myQuantity);
return b.build();
}
public BigDecimal getValue() {
return myQuantity;
}
@ -96,4 +99,12 @@ public class NumberParam extends BaseParamWithPrefix<NumberParam> implements IQu
return this;
}
@Override
public String toString() {
ToStringBuilder b = new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE);
b.append("prefix", getPrefix());
b.append("value", myQuantity);
return b.build();
}
}

View File

@ -79,4 +79,9 @@ public interface IRestfulServerDefaults {
*/
boolean isUseBrowserFriendlyContentTypes();
/**
* Returns the paging provider for this server
*/
IPagingProvider getPagingProvider();
}

View File

@ -48,6 +48,7 @@ import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.interceptor.IJpaServerInterceptor;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.jpa.util.StopWatch;
@ -562,6 +563,16 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
theSavedEntity.setVersion(newVersionLong);
}
protected boolean isPagingProviderDatabaseBacked(RequestDetails theRequestDetails) {
if (theRequestDetails == null) {
return false;
}
if (theRequestDetails.getServer().getPagingProvider() instanceof DatabaseBackedPagingProvider) {
return true;
}
return false;
}
@Override
public <MT extends IBaseMetaType> MT metaAddOperation(IIdType theResourceId, MT theMetaAdd, RequestDetails theRequestDetails) {
// Notify interceptors
@ -594,6 +605,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return retVal;
}
@Override
public <MT extends IBaseMetaType> MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) {
// Notify interceptors
@ -628,7 +640,6 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
return retVal;
}
@Override
public <MT extends IBaseMetaType> MT metaGetOperation(Class<MT> theType, IIdType theId, RequestDetails theRequestDetails) {
// Notify interceptors
@ -920,14 +931,14 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
theParams.setLoadSynchronousUpTo(myDaoConfig.getMaximumSearchResultCountInTransaction());
}
if (!isPagingProviderDatabaseBacked(theRequestDetails)) {
theParams.setLoadSynchronous(true);
}
}
return mySearchCoordinatorSvc.registerSearch(this, theParams, getResourceName());
}
@Override
public Set<Long> searchForIds(SearchParameterMap theParams) {

View File

@ -46,7 +46,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
super();
}
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) {
paramMap.setCount(theCount.getValue());
@ -65,6 +65,10 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
paramMap.add("_id", new StringParam(theId.getIdPart()));
}
if (!isPagingProviderDatabaseBacked(theRequestDetails)) {
paramMap.setLoadSynchronous(true);
}
return mySearchCoordinatorSvc.registerSearch(this, paramMap, getResourceName());
}
@ -74,7 +78,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative, theRequestDetails);
}
@Override
@ -83,7 +87,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2<Patient>im
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null);
notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails);
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative, theRequestDetails);
}
}

View File

@ -2099,8 +2099,6 @@ public class SearchBuilder implements ISearchBuilder {
ScrollableResults scroll = hibernateQuery.scroll(ScrollMode.FORWARD_ONLY);
myResultsIterator = new ScrollableResultsIterator(scroll);
// myResultsIterator = query.getResultList().iterator();
// If the query resulted in extra results being requested
if (myAlsoIncludePids != null) {
myPreResultsIterator = myAlsoIncludePids.iterator();

View File

@ -50,7 +50,7 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>im
@Autowired
private ISearchParamRegistry mySerarchParamRegistry;
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative) {
private IBundleProvider doEverythingOperation(IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
SearchParameterMap paramMap = new SearchParameterMap();
if (theCount != null) {
paramMap.setCount(theCount.getValue());
@ -69,17 +69,21 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3<Patient>im
paramMap.add("_id", new StringParam(theId.getIdPart()));
}
if (!isPagingProviderDatabaseBacked(theRequestDetails)) {
paramMap.setLoadSynchronous(true);
}
return mySearchCoordinatorSvc.registerSearch(this, paramMap, getResourceName());
}
@Override
public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative);
return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative, theRequestDetails);
}
@Override
public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType<Integer> theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) {
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative);
return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative, theRequestDetails);
}
}

View File

@ -19,24 +19,9 @@ package ca.uhn.fhir.jpa.search;
* limitations under the License.
* #L%
*/
import java.util.*;
import java.util.concurrent.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import javax.transaction.Transactional.TxType;
@ -47,34 +32,18 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.data.domain.*;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.*;
import org.springframework.transaction.support.*;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchInclude;
import ca.uhn.fhir.jpa.entity.SearchResult;
import ca.uhn.fhir.jpa.entity.SearchStatusEnum;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.method.PageMethodBinding;
@ -83,7 +52,7 @@ import ca.uhn.fhir.rest.server.SimpleBundleProvider;
import ca.uhn.fhir.rest.server.exceptions.*;
public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
static final int DEFAULT_SYNC_SIZE = 250;
public static final int DEFAULT_SYNC_SIZE = 250;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchCoordinatorSvcImpl.class);
@ -360,7 +329,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
}
@VisibleForTesting
void setLoadingThrottleForUnitTests(Integer theLoadingThrottleForUnitTests) {
public void setLoadingThrottleForUnitTests(Integer theLoadingThrottleForUnitTests) {
myLoadingThrottleForUnitTests = theLoadingThrottleForUnitTests;
}
@ -369,7 +338,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
myMaxMillisToWaitForRemoteResults = theMaxMillisToWaitForRemoteResults;
}
void setNeverUseLocalSearchForUnitTests(boolean theNeverUseLocalSearchForUnitTests) {
@VisibleForTesting
public void setNeverUseLocalSearchForUnitTests(boolean theNeverUseLocalSearchForUnitTests) {
myNeverUseLocalSearchForUnitTests = theNeverUseLocalSearchForUnitTests;
}
@ -389,7 +359,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
}
@VisibleForTesting
void setSyncSizeForUnitTests(int theSyncSize) {
public void setSyncSizeForUnitTests(int theSyncSize) {
mySyncSize = theSyncSize;
}

View File

@ -12,9 +12,7 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.*;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
@ -25,17 +23,16 @@ import ca.uhn.fhir.jpa.config.WebsocketDstu2Config;
import ca.uhn.fhir.jpa.config.WebsocketDstu2DispatcherConfig;
import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.interceptor.RestHookSubscriptionDstu2Interceptor;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.parser.LenientErrorHandler;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.util.TestUtil;
@ -45,10 +42,11 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
protected static CloseableHttpClient ourHttpClient;
protected static int ourPort;
protected static RestfulServer ourRestServer;
private static Server ourServer;
protected static Server ourServer;
protected static String ourServerBase;
private static GenericWebApplicationContext ourWebApplicationContext;
protected static GenericWebApplicationContext ourWebApplicationContext;
protected static RestHookSubscriptionDstu2Interceptor ourRestHookSubscriptionInterceptor;
protected static DatabaseBackedPagingProvider ourPagingProvider;
public BaseResourceProviderDstu2Test() {
super();
@ -83,7 +81,8 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
confProvider.setImplementationDescription("THIS IS THE DESC");
ourRestServer.setServerConformanceProvider(confProvider);
ourRestServer.setPagingProvider(new FifoMemoryPagingProvider(10));
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
ourRestServer.setPagingProvider(ourPagingProvider);
Server server = new Server(ourPort);
@ -126,6 +125,8 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
ourServer = server;
}
ourRestServer.setPagingProvider(ourPagingProvider);
}
protected List<IdDt> toIdListUnqualifiedVersionless(Bundle found) {

View File

@ -5,6 +5,7 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
@ -47,11 +48,12 @@ import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.*;
import org.junit.Test;
import org.springframework.test.util.AopTestUtils;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.BundleEntry;
@ -85,10 +87,7 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.param.DateRangeParam;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringOrListParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
@ -100,10 +99,27 @@ import ca.uhn.fhir.util.UrlUtil;
public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2Test.class);
private SearchCoordinatorSvcImpl mySearchCoordinatorSvcRaw;
@Override
@After
public void after() throws Exception {
super.after();
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(null);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(SearchCoordinatorSvcImpl.DEFAULT_SYNC_SIZE);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(false);
}
@Before
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
}
@AfterClass
@ -118,6 +134,92 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
myDaoConfig.setAllowMultipleDelete(true);
}
@Test
public void testPagingOverEverythingSet() throws InterruptedException {
Patient p = new Patient();
p.setActive(true);
String pid = myPatientDao.create(p).getId().toUnqualifiedVersionless().getValue();
for (int i = 0; i < 20; i++) {
Observation o = new Observation();
o.getSubject().setReference(pid);
o.addIdentifier().setSystem("foo").setValue(Integer.toString(i));
myObservationDao.create(o);
}
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(50);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(10);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(true);
ca.uhn.fhir.model.dstu2.resource.Bundle response = ourClient
.operation()
.onInstance(new IdDt(pid))
.named("everything")
.withSearchParameter(Parameters.class, "_count", new NumberParam(10))
.returnResourceType(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.useHttpGet()
.execute();
assertEquals(10, response.getEntry().size());
assertEquals(null, response.getTotalElement().getValueAsString());
assertThat(response.getLink("next").getUrl(), not(emptyString()));
// Load page 2
String nextUrl = response.getLink("next").getUrl();
response = ourClient.fetchResourceFromUrl(ca.uhn.fhir.model.dstu2.resource.Bundle.class, nextUrl);
assertEquals(10, response.getEntry().size());
assertThat(response.getLink("next").getUrl(), not(emptyString()));
// Load page 3
Thread.sleep(2000);
nextUrl = response.getLink("next").getUrl();
response = ourClient.fetchResourceFromUrl(ca.uhn.fhir.model.dstu2.resource.Bundle.class, nextUrl);
assertEquals(1, response.getEntry().size());
assertEquals(21, response.getTotal().intValue());
assertEquals(null, response.getLink("next"));
}
@Test
public void testPagingOverEverythingSetWithNoPagingProvider() throws InterruptedException {
ourRestServer.setPagingProvider(null);
Patient p = new Patient();
p.setActive(true);
String pid = myPatientDao.create(p).getId().toUnqualifiedVersionless().getValue();
for (int i = 0; i < 20; i++) {
Observation o = new Observation();
o.getSubject().setReference(pid);
o.addIdentifier().setSystem("foo").setValue(Integer.toString(i));
myObservationDao.create(o);
}
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(50);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(10);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(true);
ca.uhn.fhir.model.dstu2.resource.Bundle response = ourClient
.operation()
.onInstance(new IdDt(pid))
.named("everything")
.withSearchParameter(Parameters.class, "_count", new NumberParam(10))
.returnResourceType(ca.uhn.fhir.model.dstu2.resource.Bundle.class)
.useHttpGet()
.execute();
assertEquals(21, response.getEntry().size());
assertEquals(21, response.getTotalElement().getValue().intValue());
assertEquals(null, response.getLink("next"));
}
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
HttpGet get = new HttpGet(ourServerBase + "/Observation?" + paramName + ":missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);

View File

@ -56,6 +56,7 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
protected static String ourServerBase;
private static GenericWebApplicationContext ourWebApplicationContext;
private TerminologyUploaderProviderDstu3 myTerminologyUploaderProvider;
protected static DatabaseBackedPagingProvider ourPagingProvider;
protected static RestHookSubscriptionDstu3Interceptor ourRestHookSubscriptionInterceptor;
protected static ISearchDao mySearchEntityDao;
protected static ISearchCoordinatorSvc mySearchCoordinatorSvc;
@ -95,7 +96,7 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
confProvider.setImplementationDescription("THIS IS THE DESC");
ourRestServer.setServerConformanceProvider(confProvider);
ourRestServer.setPagingProvider(myAppCtx.getBean(DatabaseBackedPagingProvider.class));
ourPagingProvider = myAppCtx.getBean(DatabaseBackedPagingProvider.class);
Server server = new Server(ourPort);
@ -162,6 +163,8 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
ourServer = server;
}
ourRestServer.setPagingProvider(ourPagingProvider);
}
protected boolean shouldLogClient() {

View File

@ -6,11 +6,11 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsInRelativeOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;
@ -47,9 +47,9 @@ import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.hl7.fhir.dstu3.model.Questionnaire.QuestionnaireItemType;
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionChannelType;
import org.hl7.fhir.dstu3.model.Subscription.SubscriptionStatus;
import org.hl7.fhir.instance.model.Encounter.EncounterState;
import org.hl7.fhir.instance.model.api.*;
import org.junit.*;
import org.springframework.test.util.AopTestUtils;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
@ -57,6 +57,7 @@ import com.google.common.collect.Lists;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.UriDt;
@ -76,11 +77,7 @@ import ca.uhn.fhir.util.UrlUtil;
public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu3Test.class);
@Before
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
}
private SearchCoordinatorSvcImpl mySearchCoordinatorSvcRaw;
@Override
@After
@ -90,6 +87,11 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
myDaoConfig.setAllowMultipleDelete(new DaoConfig().isAllowMultipleDelete());
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(null);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(SearchCoordinatorSvcImpl.DEFAULT_SYNC_SIZE);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(false);
}
@Override
@ -100,95 +102,10 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
myDaoConfig.setAllowMultipleDelete(true);
}
@Test
public void testSearchWithEmptyParameter() throws Exception {
Observation obs= new Observation();
obs.setStatus(ObservationStatus.FINAL);
obs.getCode().addCoding().setSystem("foo").setCode("bar");
ourClient.create().resource(obs).execute();
testSearchWithEmptyParameter("/Observation?value-quantity=");
testSearchWithEmptyParameter("/Observation?code=bar&value-quantity=");
testSearchWithEmptyParameter("/Observation?value-date=");
testSearchWithEmptyParameter("/Observation?code=bar&value-date=");
testSearchWithEmptyParameter("/Observation?value-concept=");
testSearchWithEmptyParameter("/Observation?code=bar&value-concept=");
}
private void testSearchWithEmptyParameter(String url) throws IOException, ClientProtocolException {
HttpGet get = new HttpGet(ourServerBase + url);
CloseableHttpResponse resp = ourHttpClient.execute(get);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
String respString = IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8);
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, respString);
assertEquals(1, bundle.getEntry().size());
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
}
@Test
public void testSearchWithMissingDate2() throws Exception {
MedicationRequest mr1 = new MedicationRequest();
mr1.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
mr1.addDosageInstruction().getTiming().addEventElement().setValueAsString("2017-01-01");
IIdType id1 = myMedicationRequestDao.create(mr1).getId().toUnqualifiedVersionless();
MedicationRequest mr2 = new MedicationRequest();
mr2.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
IIdType id2 = myMedicationRequestDao.create(mr2).getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/MedicationRequest?date:missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8));
List<String> ids = toUnqualifiedVersionlessIdValues(bundle);
assertThat(ids, contains(id1.getValue()));
} finally {
IOUtils.closeQuietly(resp);
}
}
@Test
public void testEverythingWithOnlyPatient() {
Patient p = new Patient();
p.setActive(true);
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
myFhirCtx.getRestfulClientFactory().setSocketTimeout(300 * 1000);
Bundle response = ourClient
.operation()
.onInstance(id)
.named("everything")
.withNoParameters(Parameters.class)
.returnResourceType(Bundle.class)
.execute();
assertEquals(1, response.getEntry().size());
}
@Test
public void testSaveAndRetrieveResourceWithExtension() {
Patient nextPatient = new Patient();
nextPatient.setId("Patient/B");
nextPatient
.addExtension()
.setUrl("http://foo")
.setValue(new Reference("Practitioner/A"));
ourClient.update().resource(nextPatient).execute();
Patient p = ourClient.read().resource(Patient.class).withId("B").execute();
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
ourLog.info(encoded);
assertThat(encoded, containsString("http://foo"));
@Before
public void beforeDisableResultReuse() {
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
}
private void checkParamMissing(String paramName) throws IOException, ClientProtocolException {
@ -198,6 +115,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals(200, resp.getStatusLine().getStatusCode());
}
private ArrayList<IBaseResource> genResourcesOfType(Bundle theRes, Class<? extends IBaseResource> theClass) {
ArrayList<IBaseResource> retVal = new ArrayList<IBaseResource>();
for (BundleEntryComponent next : theRes.getEntry()) {
@ -354,8 +272,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
/**
* See #438
*/
@ -430,7 +346,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
ourClient.create().resource(input).execute().getResource();
}
@Test
public void testCreateConditional() {
Patient patient = new Patient();
@ -552,6 +467,8 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testCreateResourceConditionalComplex() throws IOException {
Patient pt = new Patient();
@ -615,6 +532,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
}
@Test
public void testCreateResourceWithNumericId() throws IOException {
String resource = "<Patient xmlns=\"http://hl7.org/fhir\"><id value=\"2\"/></Patient>";
@ -1300,31 +1218,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = ourClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// }
@Test
public void testEverythingPatientOperation() throws Exception {
String methodName = "testEverythingOperation";
@ -1370,53 +1263,6 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
ourLog.info(ids.toString());
}
@Test
public void testSearchByLastUpdated() throws Exception {
String methodName = "testSearchByLastUpdated";
Patient p = new Patient();
p.addName().setFamily(methodName+"1");
IIdType pid1 = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
Thread.sleep(10);
long time1 = System.currentTimeMillis();
Thread.sleep(10);
Patient p2 = new Patient();
p2.addName().setFamily(methodName+"2");
IIdType pid2 = ourClient.create().resource(p2).execute().getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/Patient?_lastUpdated=lt" + new InstantType(new Date(time1)).getValueAsString());
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
List<IIdType> ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pid1));
} finally {
response.close();
}
get = new HttpGet(ourServerBase + "/Patient?_lastUpdated=gt" + new InstantType(new Date(time1)).getValueAsString());
response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
List<IIdType> ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pid2));
} finally {
response.close();
}
}
@Test
public void testEverythingPatientType() throws Exception {
String methodName = "testEverythingPatientType";
@ -1679,6 +1525,50 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals(77, ids.size());
}
@Test
public void testEverythingWithOnlyPatient() {
Patient p = new Patient();
p.setActive(true);
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
myFhirCtx.getRestfulClientFactory().setSocketTimeout(300 * 1000);
Bundle response = ourClient
.operation()
.onInstance(id)
.named("everything")
.withNoParameters(Parameters.class)
.returnResourceType(Bundle.class)
.execute();
assertEquals(1, response.getEntry().size());
}
// private void delete(String theResourceType, String theParamName, String theParamValue) {
// Bundle resources;
// do {
// IQuery<Bundle> forResource = ourClient.search().forResource(theResourceType);
// if (theParamName != null) {
// forResource = forResource.where(new StringClientParam(theParamName).matches().value(theParamValue));
// }
// resources = forResource.execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// } while (resources.size() > 0);
// }
//
// private void deleteToken(String theResourceType, String theParamName, String theParamSystem, String theParamValue)
// {
// Bundle resources = ourClient.search().forResource(theResourceType).where(new
// TokenClientParam(theParamName).exactly().systemAndCode(theParamSystem, theParamValue)).execute();
// for (IResource next : resources.toListOfResources()) {
// ourLog.info("Deleting resource: {}", next.getId());
// ourClient.delete().resource(next).execute();
// }
// }
@SuppressWarnings("unused")
@Test
public void testFullTextSearch() throws RuntimeException, Exception {
@ -1728,6 +1618,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
}
@Test
public void testHasParameter() throws Exception {
IIdType pid0;
@ -2074,6 +1965,91 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testPagingOverEverythingSet() throws InterruptedException {
Patient p = new Patient();
p.setActive(true);
String pid = myPatientDao.create(p).getId().toUnqualifiedVersionless().getValue();
for (int i = 0; i < 20; i++) {
Observation o = new Observation();
o.getSubject().setReference(pid);
o.addIdentifier().setSystem("foo").setValue(Integer.toString(i));
myObservationDao.create(o);
}
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(50);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(10);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(true);
Bundle response = ourClient
.operation()
.onInstance(new IdType(pid))
.named("everything")
.withSearchParameter(Parameters.class, "_count", new NumberParam(10))
.returnResourceType(Bundle.class)
.useHttpGet()
.execute();
assertEquals(10, response.getEntry().size());
assertEquals(null, response.getTotalElement().getValueAsString());
assertThat(response.getLink("next").getUrl(), not(emptyString()));
// Load page 2
String nextUrl = response.getLink("next").getUrl();
response = ourClient.fetchResourceFromUrl(Bundle.class, nextUrl);
assertEquals(10, response.getEntry().size());
assertEquals(null, response.getTotalElement().getValueAsString());
assertThat(response.getLink("next").getUrl(), not(emptyString()));
// Load page 3
Thread.sleep(2000);
nextUrl = response.getLink("next").getUrl();
response = ourClient.fetchResourceFromUrl(Bundle.class, nextUrl);
assertEquals(1, response.getEntry().size());
assertEquals(21, response.getTotal());
assertEquals(null, response.getLink("next"));
}
@Test
public void testPagingOverEverythingSetWithNoPagingProvider() throws InterruptedException {
ourRestServer.setPagingProvider(null);
Patient p = new Patient();
p.setActive(true);
String pid = myPatientDao.create(p).getId().toUnqualifiedVersionless().getValue();
for (int i = 0; i < 20; i++) {
Observation o = new Observation();
o.getSubject().setReference(pid);
o.addIdentifier().setSystem("foo").setValue(Integer.toString(i));
myObservationDao.create(o);
}
mySearchCoordinatorSvcRaw.setLoadingThrottleForUnitTests(50);
mySearchCoordinatorSvcRaw.setSyncSizeForUnitTests(10);
mySearchCoordinatorSvcRaw.setNeverUseLocalSearchForUnitTests(true);
Bundle response = ourClient
.operation()
.onInstance(new IdType(pid))
.named("everything")
.withSearchParameter(Parameters.class, "_count", new NumberParam(10))
.returnResourceType(Bundle.class)
.useHttpGet()
.execute();
assertEquals(21, response.getEntry().size());
assertEquals(21, response.getTotalElement().getValue().intValue());
assertEquals(null, response.getLink("next"));
}
@Test
public void testPatchUsingJsonPatch() throws Exception {
String methodName = "testPatchUsingJsonPatch";
@ -2297,6 +2273,25 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals("<div xmlns=\"http://www.w3.org/1999/xhtml\">HELLO WORLD</div>", actual.getText().getDiv().getValueAsString());
}
@Test
public void testSaveAndRetrieveResourceWithExtension() {
Patient nextPatient = new Patient();
nextPatient.setId("Patient/B");
nextPatient
.addExtension()
.setUrl("http://foo")
.setValue(new Reference("Practitioner/A"));
ourClient.update().resource(nextPatient).execute();
Patient p = ourClient.read().resource(Patient.class).withId("B").execute();
String encoded = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
ourLog.info(encoded);
assertThat(encoded, containsString("http://foo"));
}
@Test
public void testSaveAndRetrieveWithContained() {
Patient p1 = new Patient();
@ -2517,6 +2512,52 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testSearchByLastUpdated() throws Exception {
String methodName = "testSearchByLastUpdated";
Patient p = new Patient();
p.addName().setFamily(methodName+"1");
IIdType pid1 = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
Thread.sleep(10);
long time1 = System.currentTimeMillis();
Thread.sleep(10);
Patient p2 = new Patient();
p2.addName().setFamily(methodName+"2");
IIdType pid2 = ourClient.create().resource(p2).execute().getId().toUnqualifiedVersionless();
HttpGet get = new HttpGet(ourServerBase + "/Patient?_lastUpdated=lt" + new InstantType(new Date(time1)).getValueAsString());
CloseableHttpResponse response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
List<IIdType> ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pid1));
} finally {
response.close();
}
get = new HttpGet(ourServerBase + "/Patient?_lastUpdated=gt" + new InstantType(new Date(time1)).getValueAsString());
response = ourHttpClient.execute(get);
try {
assertEquals(200, response.getStatusLine().getStatusCode());
String output = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8);
IOUtils.closeQuietly(response.getEntity().getContent());
ourLog.info(output);
List<IIdType> ids = toUnqualifiedVersionlessIds(myFhirCtx.newXmlParser().parseResource(Bundle.class, output));
ourLog.info(ids.toString());
assertThat(ids, containsInAnyOrder(pid2));
} finally {
response.close();
}
}
@Test
public void testSearchByReferenceIds() {
Organization o1 = new Organization();
@ -2587,6 +2628,28 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testSearchInvalidParam() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("0");
patient.addName().setFamily("testSearchWithMixedParams").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
// should be subject._id
HttpGet httpPost = new HttpGet(ourServerBase + "/Observation?subject.id=FOO");
CloseableHttpResponse resp = ourHttpClient.execute(httpPost);
try {
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(respString);
assertThat(respString, containsString("Invalid parameter chain: subject.id"));
assertEquals(400, resp.getStatusLine().getStatusCode());
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
ourLog.info("Outgoing post: {}", httpPost);
}
@Test
public void testSearchLastUpdatedParamRp() throws InterruptedException {
String methodName = "testSearchLastUpdatedParamRp";
@ -3047,6 +3110,34 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals(2, response.getEntry().size());
}
@Test
public void testSearchWithEmptyParameter() throws Exception {
Observation obs= new Observation();
obs.setStatus(ObservationStatus.FINAL);
obs.getCode().addCoding().setSystem("foo").setCode("bar");
ourClient.create().resource(obs).execute();
testSearchWithEmptyParameter("/Observation?value-quantity=");
testSearchWithEmptyParameter("/Observation?code=bar&value-quantity=");
testSearchWithEmptyParameter("/Observation?value-date=");
testSearchWithEmptyParameter("/Observation?code=bar&value-date=");
testSearchWithEmptyParameter("/Observation?value-concept=");
testSearchWithEmptyParameter("/Observation?code=bar&value-concept=");
}
private void testSearchWithEmptyParameter(String url) throws IOException, ClientProtocolException {
HttpGet get = new HttpGet(ourServerBase + url);
CloseableHttpResponse resp = ourHttpClient.execute(get);
try {
assertEquals(200, resp.getStatusLine().getStatusCode());
String respString = IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8);
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, respString);
assertEquals(1, bundle.getEntry().size());
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
}
}
@Test
public void testSearchWithInclude() throws Exception {
Organization org = new Organization();
@ -3211,25 +3302,28 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
}
@Test
public void testSearchInvalidParam() throws Exception {
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("0");
patient.addName().setFamily("testSearchWithMixedParams").addGiven("Joe");
myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
public void testSearchWithMissingDate2() throws Exception {
MedicationRequest mr1 = new MedicationRequest();
mr1.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
mr1.addDosageInstruction().getTiming().addEventElement().setValueAsString("2017-01-01");
IIdType id1 = myMedicationRequestDao.create(mr1).getId().toUnqualifiedVersionless();
// should be subject._id
HttpGet httpPost = new HttpGet(ourServerBase + "/Observation?subject.id=FOO");
MedicationRequest mr2 = new MedicationRequest();
mr2.getCategory().addCoding().setSystem("urn:medicationroute").setCode("oral");
IIdType id2 = myMedicationRequestDao.create(mr2).getId().toUnqualifiedVersionless();
CloseableHttpResponse resp = ourHttpClient.execute(httpPost);
HttpGet get = new HttpGet(ourServerBase + "/MedicationRequest?date:missing=false");
CloseableHttpResponse resp = ourHttpClient.execute(get);
try {
String respString = IOUtils.toString(resp.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(respString);
assertThat(respString, containsString("Invalid parameter chain: subject.id"));
assertEquals(400, resp.getStatusLine().getStatusCode());
assertEquals(200, resp.getStatusLine().getStatusCode());
Bundle bundle = myFhirCtx.newXmlParser().parseResource(Bundle.class, IOUtils.toString(resp.getEntity().getContent(), Constants.CHARSET_UTF8));
List<String> ids = toUnqualifiedVersionlessIdValues(bundle);
assertThat(ids, contains(id1.getValue()));
} finally {
IOUtils.closeQuietly(resp.getEntity().getContent());
IOUtils.closeQuietly(resp);
}
ourLog.info("Outgoing post: {}", httpPost);
}
/**

View File

@ -42,8 +42,6 @@ public class PagingMultinodeProviderDstu3Test extends BaseResourceProviderDstu3T
myDaoConfig.setAllowMultipleDelete(true);
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
// mySearchCoordinatorSvcRaw = (SearchCoordinatorSvcImpl)mySearchCoordinatorSvc;
}
@Test

View File

@ -66,6 +66,15 @@
JPA search now uses hibernate ScrollableResults instead of plain JPA List. This
should improve performance over large search results.
</action>
<action type="add">
JPA servers with no paging provider configured, or with a paging provider other than
DatabaseBackedPagingProvider will load all results in a single pass and keep them
in memory. Using this setup is not a good idea unless you know for sure that you
will never have very large queries since it means that all results will be loaded into
memory, but there are valid reasons to need this and it will perform better than
paging to the database in that case. This fix also resolves a NullPointerException
when performing an $everything search. Thanks to Kamal Othman for reporting!
</action>
</release>
<release version="2.5" date="2017-06-08">
<action type="fix">