perf enhancements finally working
This commit is contained in:
parent
fbbe792726
commit
5adc09ad56
|
@ -63,6 +63,7 @@ public abstract class RequestDetails {
|
|||
private IRestfulResponse myResponse;
|
||||
private RestOperationTypeEnum myRestOperationType;
|
||||
private String mySecondaryOperation;
|
||||
private boolean mySubRequest;
|
||||
private Map<String, List<String>> myUnqualifiedToQualifiedNames;
|
||||
private Map<Object, Object> myUserData;
|
||||
protected abstract byte[] getByteStreamRequestContents();
|
||||
|
@ -71,6 +72,7 @@ public abstract class RequestDetails {
|
|||
* Return the charset as defined by the header contenttype. Return null if it is not set.
|
||||
*/
|
||||
public abstract Charset getCharset();
|
||||
|
||||
public String getCompartmentName() {
|
||||
return myCompartmentName;
|
||||
}
|
||||
|
@ -78,7 +80,6 @@ public abstract class RequestDetails {
|
|||
public String getCompleteUrl() {
|
||||
return myCompleteUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <b>conditional URL</b> if this request has one, or <code>null</code> otherwise. For an
|
||||
* update or delete method, this is the part of the URL after the <code>?</code>. For a create, this
|
||||
|
@ -248,6 +249,19 @@ public abstract class RequestDetails {
|
|||
return myRespondGzip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this request a sub-request (i.e. a request within a batch or transaction)? This
|
||||
* flag is used internally by hapi-fhir-jpaserver-base, but not used in the plain server
|
||||
* library. You may use it in your client code as a hint when implementing transaction logic in the plain
|
||||
* server.
|
||||
* <p>
|
||||
* Defaults to {@literal false}
|
||||
* </p>
|
||||
*/
|
||||
public boolean isSubRequest() {
|
||||
return mySubRequest;
|
||||
}
|
||||
|
||||
public final byte[] loadRequestContents() {
|
||||
if (myRequestContents == null) {
|
||||
myRequestContents = getByteStreamRequestContents();
|
||||
|
@ -327,10 +341,23 @@ public abstract class RequestDetails {
|
|||
public void setRestOperationType(RestOperationTypeEnum theRestOperationType) {
|
||||
myRestOperationType = theRestOperationType;
|
||||
}
|
||||
|
||||
|
||||
public void setSecondaryOperation(String theSecondaryOperation) {
|
||||
mySecondaryOperation = theSecondaryOperation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this request a sub-request (i.e. a request within a batch or transaction)? This
|
||||
* flag is used internally by hapi-fhir-jpaserver-base, but not used in the plain server
|
||||
* library. You may use it in your client code as a hint when implementing transaction logic in the plain
|
||||
* server.
|
||||
* <p>
|
||||
* Defaults to {@literal false}
|
||||
* </p>
|
||||
*/
|
||||
public void setSubRequest(boolean theSubRequest) {
|
||||
mySubRequest = theSubRequest;
|
||||
}
|
||||
|
||||
private class RequestOperationCallback implements IRequestOperationCallback {
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ package ca.uhn.fhir.rest.server.servlet;
|
|||
* you may not use this file except in compliance with the License.
|
||||
* 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
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
@ -94,7 +94,7 @@ public class ServletRequestDetails extends RequestDetails {
|
|||
try {
|
||||
InputStream inputStream = reader.getInputStream(this);
|
||||
requestContents = IOUtils.toByteArray(inputStream);
|
||||
|
||||
|
||||
if (myServer.isUncompressIncomingContents()) {
|
||||
String contentEncoding = myServletRequest.getHeader(Constants.HEADER_CONTENT_ENCODING);
|
||||
if ("gzip".equals(contentEncoding)) {
|
||||
|
@ -105,7 +105,7 @@ public class ServletRequestDetails extends RequestDetails {
|
|||
}
|
||||
}
|
||||
}
|
||||
//FIXME resource leak
|
||||
// FIXME resource leak
|
||||
return requestContents;
|
||||
} catch (IOException e) {
|
||||
ourLog.error("Could not load request resource", e);
|
||||
|
@ -164,7 +164,6 @@ public class ServletRequestDetails extends RequestDetails {
|
|||
this.myServletResponse = myServletResponse;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Charset getCharset() {
|
||||
String ct = getHeader(Constants.HEADER_CONTENT_TYPE);
|
||||
|
|
|
@ -871,6 +871,12 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
if (theRequestDetails != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), getResourceName(), null);
|
||||
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
|
||||
|
||||
if (theRequestDetails.isSubRequest()) {
|
||||
theParams.setLoadSynchronous(true);
|
||||
theParams.setLoadSynchronousUpTo(myDaoConfig.getMaximumSearchResultCountInTransaction());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mySearchCoordinatorSvc.registerSearch(this, theParams, getResourceName());
|
||||
|
|
|
@ -48,6 +48,13 @@ public class DaoConfig {
|
|||
"http://hl7.org/fhir/codesystem-*",
|
||||
"http://hl7.org/fhir/StructureDefinition/*")));
|
||||
|
||||
/**
|
||||
* Default value for {@link #setMaximumSearchResultCountInTransaction(int)}
|
||||
*
|
||||
* @see #setMaximumSearchResultCountInTransaction(int)
|
||||
*/
|
||||
private static final int DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION = 500;
|
||||
|
||||
// ***
|
||||
// update setter javadoc if default changes
|
||||
// ***
|
||||
|
@ -86,12 +93,14 @@ public class DaoConfig {
|
|||
// update setter javadoc if default changes
|
||||
// ***
|
||||
private int myMaximumExpansionSize = 5000;
|
||||
private int myMaximumSearchResultCountInTransaction = DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT_IN_TRANSACTION;
|
||||
private ResourceEncodingEnum myResourceEncoding = ResourceEncodingEnum.JSONC;
|
||||
private boolean mySchedulingDisabled;
|
||||
private boolean mySubscriptionEnabled;
|
||||
private long mySubscriptionPollDelay = 1000;
|
||||
private Long mySubscriptionPurgeInactiveAfterMillis;
|
||||
private Set<String> myTreatBaseUrlsAsLocal = new HashSet<String>();
|
||||
|
||||
private Set<String> myTreatReferencesAsLogical = new HashSet<String>(DEFAULT_LOGICAL_BASE_URLS);
|
||||
|
||||
/**
|
||||
|
@ -173,6 +182,18 @@ public class DaoConfig {
|
|||
return myMaximumExpansionSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the maximum number of results which may be returned by a search within a FHIR <code>transaction</code>
|
||||
* operation. For example, if this value is set to <code>100</code> and a FHIR transaction is processed with a sub-request
|
||||
* for <code>Patient?gender=male</code>, the server will throw an error (and the transaction will fail) if there are more than
|
||||
* 100 resources on the server which match this query.
|
||||
*
|
||||
* @see #DEFAULT_LOGICAL_BASE_URLS The default value for this setting
|
||||
*/
|
||||
public int getMaximumSearchResultCountInTransaction() {
|
||||
return myMaximumSearchResultCountInTransaction;
|
||||
}
|
||||
|
||||
public ResourceEncodingEnum getResourceEncoding() {
|
||||
return myResourceEncoding;
|
||||
}
|
||||
|
@ -499,6 +520,18 @@ public class DaoConfig {
|
|||
myMaximumExpansionSize = theMaximumExpansionSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the maximum number of results which may be returned by a search within a FHIR <code>transaction</code>
|
||||
* operation. For example, if this value is set to <code>100</code> and a FHIR transaction is processed with a sub-request
|
||||
* for <code>Patient?gender=male</code>, the server will throw an error (and the transaction will fail) if there are more than
|
||||
* 100 resources on the server which match this query.
|
||||
*
|
||||
* @see #DEFAULT_LOGICAL_BASE_URLS The default value for this setting
|
||||
*/
|
||||
public void setMaximumSearchResultCountInTransaction(int theMaximumSearchResultCountInTransaction) {
|
||||
myMaximumSearchResultCountInTransaction = theMaximumSearchResultCountInTransaction;
|
||||
}
|
||||
|
||||
public void setResourceEncoding(ResourceEncodingEnum theResourceEncoding) {
|
||||
myResourceEncoding = theResourceEncoding;
|
||||
}
|
||||
|
|
|
@ -1264,19 +1264,23 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
List<Long> pids = myFulltextSearchSvc.everything(myResourceName, myParams);
|
||||
if (pids.isEmpty()) {
|
||||
// Will never match
|
||||
pids = Collections.singletonList((Long) null);
|
||||
pids = Collections.singletonList(-1L);
|
||||
}
|
||||
|
||||
myPredicates.add(myResourceTableRoot.get("myId").as(Long.class).in(pids));
|
||||
}
|
||||
|
||||
myResourceTableQuery.where(myBuilder.and(SearchBuilder.toArray(myPredicates)));
|
||||
|
||||
|
||||
/*
|
||||
* Now perform the search
|
||||
*/
|
||||
final TypedQuery<Long> query = myEntityManager.createQuery(outerQuery);
|
||||
|
||||
|
||||
// FIXME: remove
|
||||
query.getResultList();
|
||||
|
||||
return new Iterator<Long>() {
|
||||
|
||||
private Long myNext;
|
||||
|
|
|
@ -28,6 +28,11 @@ import org.hl7.fhir.dstu3.model.Meta;
|
|||
import org.hl7.fhir.dstu3.model.SearchParameter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.BaseSearchParamExtractor;
|
||||
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter;
|
||||
|
@ -51,9 +56,18 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3<Se
|
|||
protected void markAffectedResources(SearchParameter theResource) {
|
||||
if (theResource != null) {
|
||||
String expression = theResource.getExpression();
|
||||
String resourceType = expression.substring(0, expression.indexOf('.'));
|
||||
final String resourceType = expression.substring(0, expression.indexOf('.'));
|
||||
ourLog.info("Marking all resources of type {} for reindexing due to updated search parameter with path: {}", expression);
|
||||
int updatedCount = myResourceTableDao.markResourcesOfTypeAsRequiringReindexing(resourceType);
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
int updatedCount = txTemplate.execute(new TransactionCallback<Integer>() {
|
||||
@Override
|
||||
public Integer doInTransaction(TransactionStatus theStatus) {
|
||||
return myResourceTableDao.markResourcesOfTypeAsRequiringReindexing(resourceType);
|
||||
}
|
||||
});
|
||||
|
||||
ourLog.info("Marked {} resources for reindexing", updatedCount);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,10 @@ public class SearchParamRegistryDstu3 extends BaseSearchParamRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
IBundleProvider allSearchParamsBp = mySpDao.search(new SearchParameterMap());
|
||||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.setLoadSynchronous(true);
|
||||
|
||||
IBundleProvider allSearchParamsBp = mySpDao.search(params);
|
||||
int size = allSearchParamsBp.size();
|
||||
|
||||
// Just in case..
|
||||
|
|
|
@ -54,6 +54,9 @@ public class Search implements Serializable {
|
|||
@Column(name="CREATED", nullable=false, updatable=false)
|
||||
private Date myCreated;
|
||||
|
||||
@Column(name="FAILURE_CODE", nullable=true)
|
||||
private Integer myFailureCode;
|
||||
|
||||
@Column(name="FAILURE_MESSAGE", length=FAILURE_MESSAGE_LENGTH, nullable=true)
|
||||
private String myFailureMessage;
|
||||
|
||||
|
@ -65,7 +68,7 @@ public class Search implements Serializable {
|
|||
|
||||
@OneToMany(mappedBy="mySearch")
|
||||
private Collection<SearchInclude> myIncludes;
|
||||
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name="LAST_UPDATED_HIGH", nullable=true, insertable=true, updatable=false)
|
||||
private Date myLastUpdatedHigh;
|
||||
|
@ -73,7 +76,7 @@ public class Search implements Serializable {
|
|||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name="LAST_UPDATED_LOW", nullable=true, insertable=true, updatable=false)
|
||||
private Date myLastUpdatedLow;
|
||||
|
||||
|
||||
@Column(name="NUM_FOUND", nullable=false)
|
||||
private int myNumFound;
|
||||
|
||||
|
@ -88,18 +91,18 @@ public class Search implements Serializable {
|
|||
|
||||
@OneToMany(mappedBy="mySearch")
|
||||
private Collection<SearchResult> myResults;
|
||||
|
||||
|
||||
@Column(name="SEARCH_STRING", length=1000, nullable=true)
|
||||
private String mySearchString;
|
||||
|
||||
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
@Column(name="SEARCH_TYPE", nullable=false)
|
||||
private SearchTypeEnum mySearchType;
|
||||
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name="SEARCH_STATUS", nullable=false, length=10)
|
||||
private SearchStatusEnum myStatus;
|
||||
|
||||
|
||||
@Column(name="TOTAL_COUNT", nullable=true)
|
||||
private Integer myTotalCount;
|
||||
|
||||
|
@ -110,6 +113,10 @@ public class Search implements Serializable {
|
|||
return myCreated;
|
||||
}
|
||||
|
||||
public Integer getFailureCode() {
|
||||
return myFailureCode;
|
||||
}
|
||||
|
||||
public String getFailureMessage() {
|
||||
return myFailureMessage;
|
||||
}
|
||||
|
@ -152,11 +159,11 @@ public class Search implements Serializable {
|
|||
public Long getResourceId() {
|
||||
return myResourceId;
|
||||
}
|
||||
|
||||
|
||||
public String getResourceType() {
|
||||
return myResourceType;
|
||||
}
|
||||
|
||||
|
||||
public SearchTypeEnum getSearchType() {
|
||||
return mySearchType;
|
||||
}
|
||||
|
@ -177,6 +184,10 @@ public class Search implements Serializable {
|
|||
myCreated = theCreated;
|
||||
}
|
||||
|
||||
public void setFailureCode(Integer theFailureCode) {
|
||||
myFailureCode = theFailureCode;
|
||||
}
|
||||
|
||||
|
||||
public void setFailureMessage(String theFailureMessage) {
|
||||
myFailureMessage = left(theFailureMessage, FAILURE_MESSAGE_LENGTH);
|
||||
|
|
|
@ -30,6 +30,16 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
|||
public class ServletSubRequestDetails extends ServletRequestDetails {
|
||||
|
||||
private Map<String, ArrayList<String>> myHeaders = new HashMap<String, ArrayList<String>>();
|
||||
|
||||
public void addHeader(String theName, String theValue) {
|
||||
String lowerCase = theName.toLowerCase();
|
||||
ArrayList<String> list = myHeaders.get(lowerCase);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
myHeaders.put(lowerCase, list);
|
||||
}
|
||||
list.add(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String theName) {
|
||||
|
@ -49,14 +59,9 @@ public class ServletSubRequestDetails extends ServletRequestDetails {
|
|||
return list;
|
||||
}
|
||||
|
||||
public void addHeader(String theName, String theValue) {
|
||||
String lowerCase = theName.toLowerCase();
|
||||
ArrayList<String> list = myHeaders.get(lowerCase);
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
myHeaders.put(lowerCase, list);
|
||||
}
|
||||
list.add(theValue);
|
||||
@Override
|
||||
public boolean isSubRequest() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class PersistedJpaSearchFirstPageBundleProvider extends PersistedJpaBundl
|
|||
|
||||
@Override
|
||||
public List<IBaseResource> getResources(int theFromIndex, int theToIndex) {
|
||||
checkForFailedSearch();
|
||||
SearchCoordinatorSvcImpl.verifySearchHasntFailedOrThrowInternalErrorException(mySearch);
|
||||
final List<Long> pids = mySearchTask.getResourcePids(theFromIndex, theToIndex);
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
||||
|
@ -48,15 +48,8 @@ public class PersistedJpaSearchFirstPageBundleProvider extends PersistedJpaBundl
|
|||
@Override
|
||||
public Integer size() {
|
||||
mySearchTask.awaitInitialSync();
|
||||
checkForFailedSearch();
|
||||
SearchCoordinatorSvcImpl.verifySearchHasntFailedOrThrowInternalErrorException(mySearch);
|
||||
return super.size();
|
||||
}
|
||||
|
||||
private void checkForFailedSearch() {
|
||||
if (mySearch.getStatus() == SearchStatusEnum.FAILED) {
|
||||
throw new InternalErrorException("Failure while loading search results");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import javax.persistence.EntityManager;
|
|||
import javax.transaction.Transactional;
|
||||
import javax.transaction.Transactional.TxType;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
|
@ -14,6 +15,7 @@ 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.http.HttpStatus;
|
||||
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
|
@ -37,8 +39,10 @@ import ca.uhn.fhir.model.api.Include;
|
|||
import ca.uhn.fhir.rest.method.PageMethodBinding;
|
||||
import ca.uhn.fhir.rest.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
|
||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
||||
static final int DEFAULT_SYNC_SIZE = 250;
|
||||
|
@ -143,12 +147,13 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
Class<? extends IBaseResource> resourceTypeClass = myContext.getResourceDefinition(theResourceType).getImplementingClass();
|
||||
ISearchBuilder sb = theCallingDao.newSearchBuilder();
|
||||
sb.setType(resourceTypeClass, theResourceType);
|
||||
Iterator<Long> resultIter = sb.createQuery(theParams);
|
||||
|
||||
if (theParams.isLoadSynchronous()) {
|
||||
|
||||
// Load the results synchronously
|
||||
List<Long> pids = new ArrayList<Long>();
|
||||
|
||||
Iterator<Long> resultIter = sb.createQuery(theParams);
|
||||
while (resultIter.hasNext()) {
|
||||
pids.add(resultIter.next());
|
||||
if (theParams.getLoadSynchronousUpTo() != null && pids.size() >= theParams.getLoadSynchronousUpTo()) {
|
||||
|
@ -246,7 +251,11 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
|
||||
static void verifySearchHasntFailedOrThrowInternalErrorException(Search theSearch) {
|
||||
if (theSearch.getStatus() == SearchStatusEnum.FAILED) {
|
||||
throw new InternalErrorException(theSearch.getFailureMessage());
|
||||
Integer status = theSearch.getFailureCode();
|
||||
status = ObjectUtils.defaultIfNull(status, 500);
|
||||
|
||||
String message = theSearch.getFailureMessage();
|
||||
throw BaseServerResponseException.newInstance(status, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,9 +327,20 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
|
|||
ourLog.error("Failed during search loading after {}ms", sw.getMillis(), t);
|
||||
myUnsyncedPids.clear();
|
||||
|
||||
mySearch.setStatus(SearchStatusEnum.FAILED);
|
||||
String failureMessage = ExceptionUtils.getRootCauseMessage(t);
|
||||
Throwable rootCause = ExceptionUtils.getRootCause(t);
|
||||
rootCause = ObjectUtils.defaultIfNull(rootCause, t);
|
||||
|
||||
String failureMessage = rootCause.getMessage();
|
||||
|
||||
int failureCode = InternalErrorException.STATUS_CODE;
|
||||
if (t instanceof BaseServerResponseException) {
|
||||
failureCode = ((BaseServerResponseException) t).getStatusCode();
|
||||
}
|
||||
|
||||
mySearch.setFailureMessage(failureMessage);
|
||||
mySearch.setFailureCode(failureCode);
|
||||
mySearch.setStatus(SearchStatusEnum.FAILED);
|
||||
|
||||
saveSearch();
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
|
||||
import ca.uhn.fhir.jpa.dao.FulltextSearchSvcImpl.Suggestion;
|
||||
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
|
||||
|
@ -150,13 +153,18 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
|
|||
|
||||
@Test
|
||||
public void testSearchAndReindex() {
|
||||
Patient patient;
|
||||
SearchParameterMap map;
|
||||
|
||||
patient = new Patient();
|
||||
patient.getText().setDiv("<div>DIVAAA</div>");
|
||||
patient.addName().addGiven("NAMEAAA");
|
||||
IIdType pId1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||
final IIdType pId1= newTxTemplate().execute(new TransactionCallback<IIdType>() {
|
||||
@Override
|
||||
public IIdType doInTransaction(TransactionStatus theStatus) {
|
||||
// TODO Auto-generated method stub
|
||||
Patient patient = new Patient();
|
||||
patient.getText().setDiv("<div>DIVAAA</div>");
|
||||
patient.addName().addGiven("NAMEAAA");
|
||||
return myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
|
||||
}
|
||||
});
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
@ -169,12 +177,21 @@ public class FhirResourceDaoDstu2SearchFtTest extends BaseJpaDstu2Test {
|
|||
/*
|
||||
* Reindex
|
||||
*/
|
||||
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
|
||||
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
|
||||
Patient patient = new Patient();
|
||||
patient.setId(pId1);
|
||||
patient.getText().setDiv("<div>DIVBBB</div>");
|
||||
patient.addName().addGiven("NAMEBBB");
|
||||
myPatientDao.update(patient, mySrd);
|
||||
}
|
||||
});
|
||||
|
||||
patient = new Patient();
|
||||
patient.setId(pId1);
|
||||
patient.getText().setDiv("<div>DIVBBB</div>");
|
||||
patient.addName().addGiven("NAMEBBB");
|
||||
myPatientDao.update(patient, mySrd);
|
||||
map = new SearchParameterMap();
|
||||
map.add(Patient.SP_NAME, new StringParam("NAMEAAA"));
|
||||
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), empty());
|
||||
|
||||
map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam("NAMEAAA"));
|
||||
|
|
|
@ -230,7 +230,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
Observation o2 = new Observation();
|
||||
o2.getCode().addCoding().setSystem("foo").setCode("testChoiceParamDateAlt02");
|
||||
o2.setEffective(new DateTimeDt("2015-03-08T11:11:11"));
|
||||
IIdType id2 = myObservationDao.create(o2, mySrd).getId();
|
||||
IIdType id2 = myObservationDao.create(o2, mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
{
|
||||
IBundleProvider found = myObservationDao.search(new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_DATE, new DateParam(">2001-01-02")));
|
||||
|
@ -2225,7 +2225,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
|
|||
SearchParameterMap pm = new SearchParameterMap();
|
||||
pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_CONCEPT));
|
||||
try {
|
||||
myObservationDao.search(pm);
|
||||
myObservationDao.search(pm).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-concept", e.getMessage());
|
||||
|
|
|
@ -244,7 +244,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
map = new SearchParameterMap();
|
||||
map.add("foo", new TokenParam(null, "male"));
|
||||
try {
|
||||
myPatientDao.search(map);
|
||||
myPatientDao.search(map).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unknown search parameter foo for resource type Patient", e.getMessage());
|
||||
|
@ -282,7 +282,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
|
|||
map = new SearchParameterMap();
|
||||
map.add("foo", new TokenParam(null, "male"));
|
||||
try {
|
||||
myPatientDao.search(map);
|
||||
myPatientDao.search(map).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Unknown search parameter foo for resource type Patient", e.getMessage());
|
||||
|
|
|
@ -191,7 +191,7 @@ public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTes
|
|||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_CONTENT, new StringParam(methodName));
|
||||
try {
|
||||
myOrganizationDao.search(map);
|
||||
myOrganizationDao.search(map).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Fulltext search is not enabled on this service, can not process parameter: _content", e.getMessage());
|
||||
|
@ -209,7 +209,7 @@ public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTes
|
|||
SearchParameterMap map = new SearchParameterMap();
|
||||
map.add(Constants.PARAM_TEXT, new StringParam(methodName));
|
||||
try {
|
||||
myOrganizationDao.search(map);
|
||||
myOrganizationDao.search(map).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Fulltext search is not enabled on this service, can not process parameter: _text", e.getMessage());
|
||||
|
|
|
@ -722,7 +722,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test {
|
|||
SearchParameterMap params = new SearchParameterMap();
|
||||
params.add(Observation.SP_CODE, new TokenParam(URL_MY_CODE_SYSTEM, "AAA").setModifier(TokenParamModifier.ABOVE));
|
||||
try {
|
||||
myObservationDao.search(params);
|
||||
myObservationDao.search(params).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("Expansion of ValueSet produced too many codes (maximum 1) - Operation aborted!", e.getMessage());
|
||||
|
|
|
@ -2679,7 +2679,7 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
|
|||
SearchParameterMap pm = new SearchParameterMap();
|
||||
pm.setSort(new SortSpec(Observation.SP_CODE_VALUE_CONCEPT));
|
||||
try {
|
||||
myObservationDao.search(pm);
|
||||
myObservationDao.search(pm).size();
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("This server does not support _sort specifications of type COMPOSITE - Can't serve _sort=code-value-concept", e.getMessage());
|
||||
|
|
|
@ -64,7 +64,7 @@ public class SearchCoordinatorSvcImplTest {
|
|||
private IDao myCallingDao;
|
||||
@Mock
|
||||
private EntityManager myEntityManager;
|
||||
private int myExpectedNumberOfSearchBuildersCreated = 1;
|
||||
private int myExpectedNumberOfSearchBuildersCreated = 2;
|
||||
@Mock
|
||||
private ISearchBuilder mySearchBuider;
|
||||
@Mock
|
||||
|
@ -156,7 +156,7 @@ public class SearchCoordinatorSvcImplTest {
|
|||
try {
|
||||
result.getResources(0, 100000);
|
||||
} catch (InternalErrorException e) {
|
||||
assertEquals("NullPointerException: FAILED", e.getMessage());
|
||||
assertEquals("FAILED", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ public class SearchCoordinatorSvcImplTest {
|
|||
assertEquals("30", resources.get(0).getIdElement().getValueAsString());
|
||||
assertEquals("799", resources.get(769).getIdElement().getValueAsString());
|
||||
|
||||
myExpectedNumberOfSearchBuildersCreated = 3;
|
||||
myExpectedNumberOfSearchBuildersCreated = 4;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -20,17 +20,6 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
The JPA project uses a newer API but we'll try to hold to this version
|
||||
as much as possible. See #283.
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>xmlunit</groupId>
|
||||
|
@ -150,6 +139,22 @@
|
|||
<artifactId>guava</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
The JPA project uses a newer API but we'll try to hold to this version
|
||||
as much as possible. See #283.
|
||||
|
||||
This dependency comes last so that the newer version brought in by
|
||||
Jetty for unit tests comes first on the classpath (since jetty
|
||||
needs that newer version. The unit tests are slooooow otherwise.
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
Loading…
Reference in New Issue