Reuse bundle ID when returning query cache results

This commit is contained in:
James 2017-10-11 06:05:14 -04:00
parent 432c511a30
commit 31fb1236a1
20 changed files with 1009 additions and 891 deletions

View File

@ -176,6 +176,7 @@ public class Constants {
public static final String URL_TOKEN_METADATA = "metadata";
public static final String OO_INFOSTATUS_PROCESSING = "processing";
public static final String PARAM_GRAPHQL_QUERY = "query";
public static final String HEADER_X_CACHE = "X-Cache";
static {
CHARSET_UTF8 = Charset.forName(CHARSET_NAME_UTF8);

View File

@ -35,7 +35,7 @@ public interface IVersionSpecificBundleFactory {
void addResourcesToBundle(List<IBaseResource> theResult, BundleTypeEnum theBundleType, String theServerBase, BundleInclusionRule theBundleInclusionRule, Set<Include> theIncludes);
void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated);
void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated);
IBaseResource getResourceBundle();

View File

@ -125,6 +125,11 @@
<artifactId>datasource-proxy</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.exparity</groupId>
<artifactId>hamcrest-date</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>

View File

@ -29,7 +29,6 @@ import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;

View File

@ -30,6 +30,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.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.util.DeleteConflict;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils;
@ -61,6 +62,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@ -894,6 +896,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public IBundleProvider search(final SearchParameterMap theParams, RequestDetails theRequestDetails) {
return search(theParams, theRequestDetails, null);
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public IBundleProvider search(final SearchParameterMap theParams, RequestDetails theRequestDetails, HttpServletResponse theServletResponse) {
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.DISABLED) {
for (List<List<? extends IQueryParameterType>> nextAnds : theParams.values()) {
@ -930,7 +938,19 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
cacheControlDirective.parse(theRequestDetails.getHeaders(Constants.HEADER_CACHE_CONTROL));
}
return mySearchCoordinatorSvc.registerSearch(this, theParams, getResourceName(), cacheControlDirective);
IBundleProvider retVal = mySearchCoordinatorSvc.registerSearch(this, theParams, getResourceName(), cacheControlDirective);
if (retVal instanceof PersistedJpaBundleProvider) {
PersistedJpaBundleProvider provider = (PersistedJpaBundleProvider) retVal;
if (provider.isCacheHit()) {
if (theServletResponse != null && theRequestDetails != null) {
String value = "HIT from " + theRequestDetails.getFhirServerBase();
theServletResponse.addHeader(Constants.HEADER_X_CACHE, value);
}
}
}
return retVal;
}
@Override

View File

@ -33,6 +33,10 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
@ -179,6 +183,9 @@ public interface IFhirResourceDao<T extends IBaseResource> extends IDao {
IBundleProvider search(SearchParameterMap theParams, RequestDetails theRequestDetails);
@Transactional(propagation = Propagation.SUPPORTS)
IBundleProvider search(SearchParameterMap theParams, RequestDetails theRequestDetails, HttpServletResponse theServletResponse);
Set<Long> searchForIds(SearchParameterMap theParams);
/**

View File

@ -274,14 +274,6 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
return this;
}
/**
* @deprecated As of HAPI FHIR 2.4 this method no longer does anything
*/
@Deprecated
public void setPersistResults(boolean thePersistResults) {
// does nothing as of HAPI FHIR 2.4
}
public void setRevIncludes(Set<Include> theRevIncludes) {
myRevIncludes = theRevIncludes;
}

View File

@ -19,23 +19,32 @@ package ca.uhn.fhir.jpa.search;
* limitations under the License.
* #L%
*/
import java.util.*;
import javax.persistence.*;
import javax.persistence.criteria.*;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IDao;
import ca.uhn.fhir.jpa.dao.ISearchBuilder;
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.BaseHasResource;
import ca.uhn.fhir.jpa.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchTypeEnum;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
public class PersistedJpaBundleProvider implements IBundleProvider {
@ -47,6 +56,7 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
private ISearchDao mySearchDao;
private Search mySearchEntity;
private String myUuid;
private boolean myCacheHit;
public PersistedJpaBundleProvider(String theSearchUuid, IDao theDao) {
myUuid = theSearchUuid;
@ -197,6 +207,14 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
return myUuid;
}
public boolean isCacheHit() {
return myCacheHit;
}
public void setCacheHit(boolean theCacheHit) {
myCacheHit = theCacheHit;
}
@Override
public Integer preferredPageSize() {
ensureSearchEntityLoaded();

View File

@ -281,6 +281,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
mySearchDao.updateSearchLastReturned(searchToUse.getId(), new Date());
retVal = new PersistedJpaBundleProvider(searchToUse.getUuid(), theCallingDao);
retVal.setCacheHit(true);
populateBundleProvider(retVal);
}

View File

@ -4,8 +4,11 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.TestUtil;
import org.exparity.hamcrest.date.DateMatchers;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Patient;
import org.junit.After;
@ -14,13 +17,18 @@ import org.junit.Test;
import org.springframework.test.util.AopTestUtils;
import java.io.IOException;
import java.util.Date;
import static org.hamcrest.Matchers.blankOrNullString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.*;
public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4CacheTest.class);
private SearchCoordinatorSvcImpl mySearchCoordinatorSvcRaw;
private CapturingInterceptor myCapturingInterceptor;
@Override
@After
@ -28,6 +36,8 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
super.after();
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
myDaoConfig.setCacheControlNoStoreMaxResultsUpperLimit(new DaoConfig().getCacheControlNoStoreMaxResultsUpperLimit());
ourClient.unregisterInterceptor(myCapturingInterceptor);
}
@Override
@ -35,6 +45,9 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
super.before();
myFhirCtx.setParserErrorHandler(new StrictErrorHandler());
mySearchCoordinatorSvcRaw = AopTestUtils.getTargetObject(mySearchCoordinatorSvc);
myCapturingInterceptor = new CapturingInterceptor();
ourClient.registerInterceptor(myCapturingInterceptor);
}
@Test
@ -53,6 +66,7 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
.execute();
assertEquals(1, results.getEntry().size());
assertEquals(0, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
Patient pt2 = new Patient();
pt2.addName().setFamily("FAM");
@ -67,6 +81,7 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
.execute();
assertEquals(2, results.getEntry().size());
assertEquals(0, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
}
@ -88,6 +103,7 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
.execute();
assertEquals(5, results.getEntry().size());
assertEquals(0, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
}
@ -118,6 +134,7 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
Bundle results = ourClient.search().forResource("Patient").where(Patient.FAMILY.matches().value("FAM")).returnBundle(Bundle.class).execute();
assertEquals(1, results.getEntry().size());
assertEquals(1, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
Patient pt2 = new Patient();
pt2.addName().setFamily("FAM");
@ -132,6 +149,7 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
.execute();
assertEquals(2, results.getEntry().size());
assertEquals(2, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
}
@ -142,18 +160,26 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
pt1.addName().setFamily("FAM");
ourClient.create().resource(pt1).execute();
Bundle results = ourClient.search().forResource("Patient").where(Patient.FAMILY.matches().value("FAM")).returnBundle(Bundle.class).execute();
assertEquals(1, results.getEntry().size());
Date beforeFirst = new Date();
Bundle results1 = ourClient.search().forResource("Patient").where(Patient.FAMILY.matches().value("FAM")).returnBundle(Bundle.class).execute();
assertEquals(1, results1.getEntry().size());
assertEquals(1, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
assertThat(results1.getMeta().getLastUpdated(), DateMatchers.after(beforeFirst));
assertThat(results1.getMeta().getLastUpdated(), DateMatchers.before(new Date()));
assertThat(results1.getId(), not(blankOrNullString()));
Patient pt2 = new Patient();
pt2.addName().setFamily("FAM");
ourClient.create().resource(pt2).execute();
results = ourClient.search().forResource("Patient").where(Patient.FAMILY.matches().value("FAM")).returnBundle(Bundle.class).execute();
assertEquals(1, results.getEntry().size());
Bundle results2 = ourClient.search().forResource("Patient").where(Patient.FAMILY.matches().value("FAM")).returnBundle(Bundle.class).execute();
assertEquals(1, results2.getEntry().size());
assertEquals(1, mySearchEntityDao.count());
assertEquals("HIT from " + ourServerBase, myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE).get(0));
assertEquals(results1.getMeta().getLastUpdated(), results2.getMeta().getLastUpdated());
assertEquals(results1.getId(), results2.getId());
}
@AfterClass

View File

@ -349,7 +349,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
}
}
bundleFactory.addRootPropertiesToBundle(null, serverBase, theLinkSelf, linkPrev, linkNext, theResult.size(), theBundleType, theResult.getPublished());
bundleFactory.addRootPropertiesToBundle(theResult.getUuid(), serverBase, theLinkSelf, linkPrev, linkNext, theResult.size(), theBundleType, theResult.getPublished());
bundleFactory.addResourcesToBundle(new ArrayList<IBaseResource>(resourceList), theBundleType, serverBase, theServer.getBundleInclusionRule(), theIncludes);
if (theServer.getPagingProvider() != null) {

View File

@ -226,12 +226,15 @@ public class Dstu2_1BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
IPrimitiveType<Date> theLastUpdated) {
ensureBundle();
myBase = theServerBase;
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(theId);
}
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString());
}

View File

@ -219,12 +219,15 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
IPrimitiveType<Date> theLastUpdated) {
ensureBundle();
myBase = theServerBase;
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(theId);
}
if (myBundle.getId().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString());
}

View File

@ -19,13 +19,6 @@ package org.hl7.fhir.dstu3.hapi.rest.server;
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.*;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.*;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.api.BundleInclusionRule;
@ -35,6 +28,19 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Bundle.BundleLinkComponent;
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
import org.hl7.fhir.dstu3.model.Bundle.SearchEntryMode;
import org.hl7.fhir.dstu3.model.DomainResource;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.*;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
private String myBase;
@ -225,12 +231,15 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
IPrimitiveType<Date> theLastUpdated) {
ensureBundle();
myBase = theServerBase;
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(theId);
}
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString());
}

View File

@ -19,14 +19,6 @@ package ca.uhn.fhir.rest.server.provider.dstu2hl7org;
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.*;
import org.hl7.fhir.instance.model.*;
import org.hl7.fhir.instance.model.Bundle.*;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.api.BundleInclusionRule;
@ -35,6 +27,20 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import org.hl7.fhir.instance.model.Bundle;
import org.hl7.fhir.instance.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.instance.model.Bundle.BundleLinkComponent;
import org.hl7.fhir.instance.model.Bundle.HTTPVerb;
import org.hl7.fhir.instance.model.Bundle.SearchEntryMode;
import org.hl7.fhir.instance.model.IdType;
import org.hl7.fhir.instance.model.InstantType;
import org.hl7.fhir.instance.model.Resource;
import org.hl7.fhir.instance.model.api.*;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
@ -212,10 +218,13 @@ public class Dstu2Hl7OrgBundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext,
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext,
Integer theTotalResults, BundleTypeEnum theBundleType, IPrimitiveType<Date> theLastUpdated) {
ensureBundle();
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(theId);
}
if (isBlank(myBundle.getId())) {
myBundle.setId(UUID.randomUUID().toString());
}

View File

@ -19,13 +19,6 @@ package org.hl7.fhir.r4.hapi.rest.server;
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import java.util.*;
import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.api.BundleInclusionRule;
@ -35,6 +28,19 @@ import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.IVersionSpecificBundleFactory;
import ca.uhn.fhir.util.ResourceReferenceInfo;
import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r4.model.Bundle.BundleLinkComponent;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.hl7.fhir.r4.model.Bundle.SearchEntryMode;
import org.hl7.fhir.r4.model.DomainResource;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Resource;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class R4BundleFactory implements IVersionSpecificBundleFactory {
private String myBase;
@ -225,12 +231,15 @@ public class R4BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
IPrimitiveType<Date> theLastUpdated) {
ensureBundle();
myBase = theServerBase;
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(theId);
}
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString());
}

View File

@ -233,11 +233,14 @@ public class Dstu2BundleFactory implements IVersionSpecificBundleFactory {
}
@Override
public void addRootPropertiesToBundle(String theAuthor, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
public void addRootPropertiesToBundle(String theId, String theServerBase, String theLinkSelf, String theLinkPrev, String theLinkNext, Integer theTotalResults, BundleTypeEnum theBundleType,
IPrimitiveType<Date> theLastUpdated) {
myBase = theServerBase;
if (myBundle.getIdElement().isEmpty()) {
myBundle.setId(theId);
}
if (myBundle.getId().isEmpty()) {
myBundle.setId(UUID.randomUUID().toString());
}

View File

@ -41,6 +41,7 @@ public class ${className}ResourceProvider extends
@Search(allowUnknownParams=true)
public ca.uhn.fhir.rest.api.server.IBundleProvider search(
javax.servlet.http.HttpServletRequest theServletRequest,
javax.servlet.http.HttpServletResponse theServletResponse,
ca.uhn.fhir.rest.api.server.RequestDetails theRequestDetails,
@ -154,7 +155,7 @@ public class ${className}ResourceProvider extends
getDao().translateRawParameters(theAdditionalRawParams, paramMap);
ca.uhn.fhir.rest.api.server.IBundleProvider retVal = getDao().search(paramMap, theRequestDetails);
ca.uhn.fhir.rest.api.server.IBundleProvider retVal = getDao().search(paramMap, theRequestDetails, theServletResponse);
return retVal;
} finally {
endRequest(theServletRequest);

View File

@ -808,6 +808,11 @@
<artifactId>websocket-server</artifactId>
<version>${jetty_version}</version>
</dependency>
<dependency>
<groupId>org.exparity</groupId>
<artifactId>hamcrest-date</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.fusesource.jansi</groupId>
<artifactId>jansi</artifactId>

View File

@ -9,8 +9,9 @@
<release version="3.1.0" date="TBD">
<action type="add">
A performance to the JPA server has been made which reduces the number
of changes to index tables when updating a resource with contents that
only make minor changes
of writes to index tables when updating a resource with contents that
only make minor changes to the resource content. In many cases this can
noticeably improve update performance.
</action>
<action type="fix">
In FHIR DSTU3 the
@ -49,6 +50,11 @@
failure when trying to update this resource further. This has been
resolved.
</action>
<action type="add">
JPA Server search/history results now set the ID of the returned Bundle to
the ID of the search, meaning that if a search returns results from the Query
cache, it will reuse the ID of the previously returned Bundle
</action>
</release>
<release version="3.0.0" date="2017-09-27">
<action type="add">