Partition aware search cleanup (#4706)
* Partition aware search cleanup * Compile fixes * Build fixes * HAPI FHIR version bump * License * License header * Tests
This commit is contained in:
parent
4fbeeccda4
commit
a2bc9a7212
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,16 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-bom</artifactId>
|
<artifactId>hapi-fhir-bom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>HAPI FHIR BOM</name>
|
<name>HAPI FHIR BOM</name>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-cli</artifactId>
|
<artifactId>hapi-fhir-cli</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,6 @@ public class SearchConfig {
|
||||||
mySearchBuilderFactory,
|
mySearchBuilderFactory,
|
||||||
mySynchronousSearchSvc,
|
mySynchronousSearchSvc,
|
||||||
myPersistedJpaBundleProviderFactory,
|
myPersistedJpaBundleProviderFactory,
|
||||||
myRequestPartitionHelperService,
|
|
||||||
mySearchParamRegistry,
|
mySearchParamRegistry,
|
||||||
mySearchStrategyFactory,
|
mySearchStrategyFactory,
|
||||||
exceptionService(),
|
exceptionService(),
|
||||||
|
|
|
@ -249,7 +249,7 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
|
||||||
Optional<Search> searchOpt = myTxService
|
Optional<Search> searchOpt = myTxService
|
||||||
.withRequest(myRequest)
|
.withRequest(myRequest)
|
||||||
.withRequestPartitionId(myRequestPartitionId)
|
.withRequestPartitionId(myRequestPartitionId)
|
||||||
.execute(() -> mySearchCacheSvc.fetchByUuid(myUuid));
|
.execute(() -> mySearchCacheSvc.fetchByUuid(myUuid, myRequestPartitionId));
|
||||||
if (!searchOpt.isPresent()) {
|
if (!searchOpt.isPresent()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -404,7 +404,7 @@ public class PersistedJpaBundleProvider implements IBundleProvider {
|
||||||
if (mySearchEntity.getSearchType() == SearchTypeEnum.HISTORY) {
|
if (mySearchEntity.getSearchType() == SearchTypeEnum.HISTORY) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return mySearchCoordinatorSvc.getSearchTotal(myUuid, myRequest).orElse(null);
|
return mySearchCoordinatorSvc.getSearchTotal(myUuid, myRequest, myRequestPartitionId).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
import ca.uhn.fhir.jpa.model.dao.JpaPid;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
||||||
import ca.uhn.fhir.jpa.partition.IRequestPartitionHelperSvc;
|
|
||||||
import ca.uhn.fhir.jpa.search.builder.StorageInterceptorHooksFacade;
|
import ca.uhn.fhir.jpa.search.builder.StorageInterceptorHooksFacade;
|
||||||
import ca.uhn.fhir.jpa.search.builder.tasks.SearchContinuationTask;
|
import ca.uhn.fhir.jpa.search.builder.tasks.SearchContinuationTask;
|
||||||
import ca.uhn.fhir.jpa.search.builder.tasks.SearchTask;
|
import ca.uhn.fhir.jpa.search.builder.tasks.SearchTask;
|
||||||
|
@ -113,7 +112,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
private final BeanFactory myBeanFactory;
|
private final BeanFactory myBeanFactory;
|
||||||
private final ConcurrentHashMap<String, SearchTask> myIdToSearchTask = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, SearchTask> myIdToSearchTask = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final Consumer<String> myOnRemoveSearchTask = (theId) -> myIdToSearchTask.remove(theId);
|
private final Consumer<String> myOnRemoveSearchTask = myIdToSearchTask::remove;
|
||||||
|
|
||||||
private final StorageInterceptorHooksFacade myStorageInterceptorHooks;
|
private final StorageInterceptorHooksFacade myStorageInterceptorHooks;
|
||||||
private Integer myLoadingThrottleForUnitTests = null;
|
private Integer myLoadingThrottleForUnitTests = null;
|
||||||
|
@ -135,7 +134,6 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
SearchBuilderFactory<JpaPid> theSearchBuilderFactory,
|
SearchBuilderFactory<JpaPid> theSearchBuilderFactory,
|
||||||
ISynchronousSearchSvc theSynchronousSearchSvc,
|
ISynchronousSearchSvc theSynchronousSearchSvc,
|
||||||
PersistedJpaBundleProviderFactory thePersistedJpaBundleProviderFactory,
|
PersistedJpaBundleProviderFactory thePersistedJpaBundleProviderFactory,
|
||||||
IRequestPartitionHelperSvc theRequestPartitionHelperService,
|
|
||||||
ISearchParamRegistry theSearchParamRegistry,
|
ISearchParamRegistry theSearchParamRegistry,
|
||||||
SearchStrategyFactory theSearchStrategyFactory,
|
SearchStrategyFactory theSearchStrategyFactory,
|
||||||
ExceptionService theExceptionSvc,
|
ExceptionService theExceptionSvc,
|
||||||
|
@ -245,7 +243,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Callable<Search> searchCallback = () -> mySearchCacheSvc
|
Callable<Search> searchCallback = () -> mySearchCacheSvc
|
||||||
.fetchByUuid(theUuid)
|
.fetchByUuid(theUuid, theRequestPartitionId)
|
||||||
.orElseThrow(() -> myExceptionSvc.newUnknownSearchException(theUuid));
|
.orElseThrow(() -> myExceptionSvc.newUnknownSearchException(theUuid));
|
||||||
search = myTxService
|
search = myTxService
|
||||||
.withRequest(theRequestDetails)
|
.withRequest(theRequestDetails)
|
||||||
|
@ -271,7 +269,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
// start a new pass
|
// start a new pass
|
||||||
if (search.getStatus() == SearchStatusEnum.PASSCMPLET) {
|
if (search.getStatus() == SearchStatusEnum.PASSCMPLET) {
|
||||||
ourLog.trace("Going to try to start next search");
|
ourLog.trace("Going to try to start next search");
|
||||||
Optional<Search> newSearch = mySearchCacheSvc.tryToMarkSearchAsInProgress(search);
|
Optional<Search> newSearch = mySearchCacheSvc.tryToMarkSearchAsInProgress(search, theRequestPartitionId);
|
||||||
if (newSearch.isPresent()) {
|
if (newSearch.isPresent()) {
|
||||||
ourLog.trace("Launching new search");
|
ourLog.trace("Launching new search");
|
||||||
search = newSearch.get();
|
search = newSearch.get();
|
||||||
|
@ -440,7 +438,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Integer> getSearchTotal(String theUuid, @Nullable RequestDetails theRequestDetails) {
|
public Optional<Integer> getSearchTotal(String theUuid, @Nullable RequestDetails theRequestDetails, RequestPartitionId theRequestPartitionId) {
|
||||||
SearchTask task = myIdToSearchTask.get(theUuid);
|
SearchTask task = myIdToSearchTask.get(theUuid);
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
return Optional.ofNullable(task.awaitInitialSync());
|
return Optional.ofNullable(task.awaitInitialSync());
|
||||||
|
@ -450,7 +448,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
* In case there is no running search, if the total is listed as accurate we know one is coming
|
* In case there is no running search, if the total is listed as accurate we know one is coming
|
||||||
* so let's wait a bit for it to show up
|
* so let's wait a bit for it to show up
|
||||||
*/
|
*/
|
||||||
Optional<Search> search = myTxService.withRequest(theRequestDetails).execute(() -> mySearchCacheSvc.fetchByUuid(theUuid));
|
Optional<Search> search = myTxService.withRequest(theRequestDetails).execute(() -> mySearchCacheSvc.fetchByUuid(theUuid, theRequestPartitionId));
|
||||||
if (search.isPresent()) {
|
if (search.isPresent()) {
|
||||||
Optional<SearchParameterMap> searchParameterMap = search.get().getSearchParameterMap();
|
Optional<SearchParameterMap> searchParameterMap = search.get().getSearchParameterMap();
|
||||||
if (searchParameterMap.isPresent() && searchParameterMap.get().getSearchTotalMode() == SearchTotalModeEnum.ACCURATE) {
|
if (searchParameterMap.isPresent() && searchParameterMap.get().getSearchTotalMode() == SearchTotalModeEnum.ACCURATE) {
|
||||||
|
@ -461,7 +459,7 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc<JpaPid> {
|
||||||
return Optional.of(search.get().getTotalCount());
|
return Optional.of(search.get().getTotalCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
search = mySearchCacheSvc.fetchByUuid(theUuid);
|
search = mySearchCacheSvc.fetchByUuid(theUuid, theRequestPartitionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
package ca.uhn.fhir.jpa.search;
|
package ca.uhn.fhir.jpa.search;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||||
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||||
import ca.uhn.fhir.jpa.model.sched.HapiJob;
|
import ca.uhn.fhir.jpa.model.sched.HapiJob;
|
||||||
import ca.uhn.fhir.jpa.model.sched.IHasScheduledJobs;
|
import ca.uhn.fhir.jpa.model.sched.IHasScheduledJobs;
|
||||||
|
@ -50,7 +51,7 @@ public class StaleSearchDeletingSvcImpl implements IStaleSearchDeletingSvc, IHas
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.NEVER)
|
@Transactional(propagation = Propagation.NEVER)
|
||||||
public void pollForStaleSearchesAndDeleteThem() {
|
public void pollForStaleSearchesAndDeleteThem() {
|
||||||
mySearchCacheSvc.pollForStaleSearchesAndDeleteThem();
|
mySearchCacheSvc.pollForStaleSearchesAndDeleteThem(RequestPartitionId.allPartitions());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -474,7 +474,7 @@ public class SearchTask implements Callable<Void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doSaveSearch() {
|
private void doSaveSearch() {
|
||||||
Search newSearch = mySearchCacheSvc.save(mySearch);
|
Search newSearch = mySearchCacheSvc.save(mySearch, myRequestPartitionId);
|
||||||
|
|
||||||
// mySearchDao.save is not supposed to return null, but in unit tests
|
// mySearchDao.save is not supposed to return null, but in unit tests
|
||||||
// it can if the mock search dao isn't set up to handle that
|
// it can if the mock search dao isn't set up to handle that
|
||||||
|
|
|
@ -25,6 +25,8 @@ import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchIncludeDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
|
||||||
|
import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
||||||
import ca.uhn.fhir.system.HapiSystemProperties;
|
import ca.uhn.fhir.system.HapiSystemProperties;
|
||||||
|
@ -38,11 +40,8 @@ import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionTemplate;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
@ -58,7 +57,7 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
*/
|
*/
|
||||||
public static final int DEFAULT_MAX_RESULTS_TO_DELETE_IN_ONE_STMT = 500;
|
public static final int DEFAULT_MAX_RESULTS_TO_DELETE_IN_ONE_STMT = 500;
|
||||||
public static final int DEFAULT_MAX_RESULTS_TO_DELETE_IN_ONE_PAS = 20000;
|
public static final int DEFAULT_MAX_RESULTS_TO_DELETE_IN_ONE_PAS = 20000;
|
||||||
public static final long SEARCH_CLEANUP_JOB_INTERVAL_MILLIS = 10 * DateUtils.MILLIS_PER_SECOND;
|
public static final long SEARCH_CLEANUP_JOB_INTERVAL_MILLIS = DateUtils.MILLIS_PER_MINUTE;
|
||||||
public static final int DEFAULT_MAX_DELETE_CANDIDATES_TO_FIND = 2000;
|
public static final int DEFAULT_MAX_DELETE_CANDIDATES_TO_FIND = 2000;
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(DatabaseSearchCacheSvcImpl.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(DatabaseSearchCacheSvcImpl.class);
|
||||||
private static int ourMaximumResultsToDeleteInOneStatement = DEFAULT_MAX_RESULTS_TO_DELETE_IN_ONE_STMT;
|
private static int ourMaximumResultsToDeleteInOneStatement = DEFAULT_MAX_RESULTS_TO_DELETE_IN_ONE_STMT;
|
||||||
|
@ -78,7 +77,7 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ISearchIncludeDao mySearchIncludeDao;
|
private ISearchIncludeDao mySearchIncludeDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PlatformTransactionManager myTxManager;
|
private IHapiTransactionService myTransactionService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private JpaStorageSettings myStorageSettings;
|
private JpaStorageSettings myStorageSettings;
|
||||||
|
|
||||||
|
@ -87,36 +86,40 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
myCutoffSlack = theCutoffSlack;
|
myCutoffSlack = theCutoffSlack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
|
||||||
@Override
|
@Override
|
||||||
public Search save(Search theSearch) {
|
public Search save(Search theSearch, RequestPartitionId theRequestPartitionId) {
|
||||||
Search newSearch = mySearchDao.save(theSearch);
|
return myTransactionService
|
||||||
return newSearch;
|
.withSystemRequestOnPartition(theRequestPartitionId)
|
||||||
|
.execute(() -> mySearchDao.save(theSearch));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.REQUIRED)
|
@Transactional(propagation = Propagation.REQUIRED)
|
||||||
public Optional<Search> fetchByUuid(String theUuid) {
|
public Optional<Search> fetchByUuid(String theUuid, RequestPartitionId theRequestPartitionId) {
|
||||||
Validate.notBlank(theUuid);
|
Validate.notBlank(theUuid);
|
||||||
return mySearchDao.findByUuidAndFetchIncludes(theUuid);
|
return myTransactionService
|
||||||
|
.withSystemRequestOnPartition(theRequestPartitionId)
|
||||||
|
.execute(() -> mySearchDao.findByUuidAndFetchIncludes(theUuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSearchDaoForUnitTest(ISearchDao theSearchDao) {
|
void setSearchDaoForUnitTest(ISearchDao theSearchDao) {
|
||||||
mySearchDao = theSearchDao;
|
mySearchDao = theSearchDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTxManagerForUnitTest(PlatformTransactionManager theTxManager) {
|
void setTransactionServiceForUnitTest(IHapiTransactionService theTransactionService) {
|
||||||
myTxManager = theTxManager;
|
myTransactionService = theTransactionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Search> tryToMarkSearchAsInProgress(Search theSearch) {
|
public Optional<Search> tryToMarkSearchAsInProgress(Search theSearch, RequestPartitionId theRequestPartitionId) {
|
||||||
ourLog.trace("Going to try to change search status from {} to {}", theSearch.getStatus(), SearchStatusEnum.LOADING);
|
ourLog.trace("Going to try to change search status from {} to {}", theSearch.getStatus(), SearchStatusEnum.LOADING);
|
||||||
try {
|
try {
|
||||||
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
|
|
||||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
return myTransactionService
|
||||||
txTemplate.afterPropertiesSet();
|
.withSystemRequest()
|
||||||
return txTemplate.execute(t -> {
|
.withRequestPartitionId(theRequestPartitionId)
|
||||||
|
.withPropagation(Propagation.REQUIRES_NEW)
|
||||||
|
.execute(t -> {
|
||||||
Search search = mySearchDao.findById(theSearch.getId()).orElse(theSearch);
|
Search search = mySearchDao.findById(theSearch.getId()).orElse(theSearch);
|
||||||
|
|
||||||
if (search.getStatus() != SearchStatusEnum.PASSCMPLET) {
|
if (search.getStatus() != SearchStatusEnum.PASSCMPLET) {
|
||||||
|
@ -135,6 +138,8 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Search> findCandidatesForReuse(String theResourceType, String theQueryString, Instant theCreatedAfter, RequestPartitionId theRequestPartitionId) {
|
public Optional<Search> findCandidatesForReuse(String theResourceType, String theQueryString, Instant theCreatedAfter, RequestPartitionId theRequestPartitionId) {
|
||||||
|
HapiTransactionService.requireTransaction();
|
||||||
|
|
||||||
String queryString = Search.createSearchQueryStringForStorage(theQueryString, theRequestPartitionId);
|
String queryString = Search.createSearchQueryStringForStorage(theQueryString, theRequestPartitionId);
|
||||||
|
|
||||||
int hashCode = queryString.hashCode();
|
int hashCode = queryString.hashCode();
|
||||||
|
@ -151,9 +156,10 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(propagation = Propagation.NEVER)
|
|
||||||
@Override
|
@Override
|
||||||
public void pollForStaleSearchesAndDeleteThem() {
|
public void pollForStaleSearchesAndDeleteThem(RequestPartitionId theRequestPartitionId) {
|
||||||
|
HapiTransactionService.noTransactionAllowed();
|
||||||
|
|
||||||
if (!myStorageSettings.isExpireSearchResults()) {
|
if (!myStorageSettings.isExpireSearchResults()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -170,29 +176,37 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
|
|
||||||
ourLog.debug("Searching for searches which are before {}", cutoff);
|
ourLog.debug("Searching for searches which are before {}", cutoff);
|
||||||
|
|
||||||
TransactionTemplate tt = new TransactionTemplate(myTxManager);
|
|
||||||
|
|
||||||
// Mark searches as deleted if they should be
|
// Mark searches as deleted if they should be
|
||||||
final Slice<Long> toMarkDeleted = tt.execute(theStatus ->
|
final Slice<Long> toMarkDeleted = myTransactionService
|
||||||
|
.withSystemRequestOnPartition(theRequestPartitionId)
|
||||||
|
.execute(theStatus ->
|
||||||
mySearchDao.findWhereCreatedBefore(cutoff, new Date(), PageRequest.of(0, ourMaximumSearchesToCheckForDeletionCandidacy))
|
mySearchDao.findWhereCreatedBefore(cutoff, new Date(), PageRequest.of(0, ourMaximumSearchesToCheckForDeletionCandidacy))
|
||||||
);
|
);
|
||||||
assert toMarkDeleted != null;
|
assert toMarkDeleted != null;
|
||||||
for (final Long nextSearchToDelete : toMarkDeleted) {
|
for (final Long nextSearchToDelete : toMarkDeleted) {
|
||||||
ourLog.debug("Deleting search with PID {}", nextSearchToDelete);
|
ourLog.debug("Deleting search with PID {}", nextSearchToDelete);
|
||||||
tt.execute(t -> {
|
myTransactionService
|
||||||
|
.withSystemRequest()
|
||||||
|
.withRequestPartitionId(theRequestPartitionId)
|
||||||
|
.execute(t -> {
|
||||||
mySearchDao.updateDeleted(nextSearchToDelete, true);
|
mySearchDao.updateDeleted(nextSearchToDelete, true);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete searches that are marked as deleted
|
// Delete searches that are marked as deleted
|
||||||
final Slice<Long> toDelete = tt.execute(theStatus ->
|
final Slice<Long> toDelete = myTransactionService
|
||||||
|
.withSystemRequestOnPartition(theRequestPartitionId)
|
||||||
|
.execute(theStatus ->
|
||||||
mySearchDao.findDeleted(PageRequest.of(0, ourMaximumSearchesToCheckForDeletionCandidacy))
|
mySearchDao.findDeleted(PageRequest.of(0, ourMaximumSearchesToCheckForDeletionCandidacy))
|
||||||
);
|
);
|
||||||
assert toDelete != null;
|
assert toDelete != null;
|
||||||
for (final Long nextSearchToDelete : toDelete) {
|
for (final Long nextSearchToDelete : toDelete) {
|
||||||
ourLog.debug("Deleting search with PID {}", nextSearchToDelete);
|
ourLog.debug("Deleting search with PID {}", nextSearchToDelete);
|
||||||
tt.execute(t -> {
|
myTransactionService
|
||||||
|
.withSystemRequest()
|
||||||
|
.withRequestPartitionId(theRequestPartitionId)
|
||||||
|
.execute(t -> {
|
||||||
deleteSearch(nextSearchToDelete);
|
deleteSearch(nextSearchToDelete);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
@ -201,7 +215,10 @@ public class DatabaseSearchCacheSvcImpl implements ISearchCacheSvc {
|
||||||
int count = toDelete.getContent().size();
|
int count = toDelete.getContent().size();
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
if (ourLog.isDebugEnabled() || HapiSystemProperties.isTestModeEnabled()) {
|
if (ourLog.isDebugEnabled() || HapiSystemProperties.isTestModeEnabled()) {
|
||||||
Long total = tt.execute(t -> mySearchDao.count());
|
Long total = myTransactionService
|
||||||
|
.withSystemRequest()
|
||||||
|
.withRequestPartitionId(theRequestPartitionId)
|
||||||
|
.execute(t -> mySearchDao.count());
|
||||||
ourLog.debug("Deleted {} searches, {} remaining", count, total);
|
ourLog.debug("Deleted {} searches, {} remaining", count, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public interface ISearchCacheSvc {
|
||||||
* @param theSearch The search to store
|
* @param theSearch The search to store
|
||||||
* @return Returns a copy of the search as it was saved. Callers should use the returned Search object for any further processing.
|
* @return Returns a copy of the search as it was saved. Callers should use the returned Search object for any further processing.
|
||||||
*/
|
*/
|
||||||
Search save(Search theSearch);
|
Search save(Search theSearch, RequestPartitionId theRequestPartitionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a search using its UUID. The search should be fully loaded when it is returned (i.e. includes are fetched, so that access to its
|
* Fetch a search using its UUID. The search should be fully loaded when it is returned (i.e. includes are fetched, so that access to its
|
||||||
|
@ -43,7 +43,7 @@ public interface ISearchCacheSvc {
|
||||||
* @param theUuid The search UUID
|
* @param theUuid The search UUID
|
||||||
* @return The search if it exists
|
* @return The search if it exists
|
||||||
*/
|
*/
|
||||||
Optional<Search> fetchByUuid(String theUuid);
|
Optional<Search> fetchByUuid(String theUuid, RequestPartitionId theRequestPartitionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: this is perhaps an inappropriate responsibility for this service
|
* TODO: this is perhaps an inappropriate responsibility for this service
|
||||||
|
@ -59,7 +59,7 @@ public interface ISearchCacheSvc {
|
||||||
* succeeded in marking it). If the search doesn't exist or some other error occurred, an exception will be thrown
|
* succeeded in marking it). If the search doesn't exist or some other error occurred, an exception will be thrown
|
||||||
* instead of {@link Optional#empty()}
|
* instead of {@link Optional#empty()}
|
||||||
*/
|
*/
|
||||||
Optional<Search> tryToMarkSearchAsInProgress(Search theSearch);
|
Optional<Search> tryToMarkSearchAsInProgress(Search theSearch, RequestPartitionId theRequestPartitionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look for any existing searches matching the given resource type and query string.
|
* Look for any existing searches matching the given resource type and query string.
|
||||||
|
@ -82,5 +82,5 @@ public interface ISearchCacheSvc {
|
||||||
* if they have some other mechanism for expiring stale results other than manually looking for them
|
* if they have some other mechanism for expiring stale results other than manually looking for them
|
||||||
* and deleting them.
|
* and deleting them.
|
||||||
*/
|
*/
|
||||||
void pollForStaleSearchesAndDeleteThem();
|
void pollForStaleSearchesAndDeleteThem(RequestPartitionId theRequestPartitionId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,6 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
mySearchBuilderFactory,
|
mySearchBuilderFactory,
|
||||||
mySynchronousSearchSvc,
|
mySynchronousSearchSvc,
|
||||||
myPersistedJpaBundleProviderFactory,
|
myPersistedJpaBundleProviderFactory,
|
||||||
myPartitionHelperSvc,
|
|
||||||
null, // search param registry
|
null, // search param registry
|
||||||
mySearchStrategyFactory,
|
mySearchStrategyFactory,
|
||||||
myExceptionSvc,
|
myExceptionSvc,
|
||||||
|
@ -187,7 +186,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
when(mySearchBuilder.createQuery(any(), any(), any(), nullable(RequestPartitionId.class))).thenReturn(iter);
|
when(mySearchBuilder.createQuery(any(), any(), any(), nullable(RequestPartitionId.class))).thenReturn(iter);
|
||||||
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
|
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
|
||||||
|
|
||||||
when(mySearchCacheSvc.save(any())).thenAnswer(t -> {
|
when(mySearchCacheSvc.save(any(), any())).thenAnswer(t -> {
|
||||||
Search search = t.getArgument(0, Search.class);
|
Search search = t.getArgument(0, Search.class);
|
||||||
myCurrentSearch = search;
|
myCurrentSearch = search;
|
||||||
return search;
|
return search;
|
||||||
|
@ -207,7 +206,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
assertEquals("799", resources.get(789).getIdElement().getValueAsString());
|
assertEquals("799", resources.get(789).getIdElement().getValueAsString());
|
||||||
|
|
||||||
ArgumentCaptor<Search> searchCaptor = ArgumentCaptor.forClass(Search.class);
|
ArgumentCaptor<Search> searchCaptor = ArgumentCaptor.forClass(Search.class);
|
||||||
verify(mySearchCacheSvc, atLeastOnce()).save(searchCaptor.capture());
|
verify(mySearchCacheSvc, atLeastOnce()).save(searchCaptor.capture(), any());
|
||||||
|
|
||||||
assertEquals(790, allResults.size());
|
assertEquals(790, allResults.size());
|
||||||
assertEquals(10, allResults.get(0).getId());
|
assertEquals(10, allResults.get(0).getId());
|
||||||
|
@ -224,10 +223,10 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
myCurrentSearch.setStatus(SearchStatusEnum.PASSCMPLET);
|
myCurrentSearch.setStatus(SearchStatusEnum.PASSCMPLET);
|
||||||
myCurrentSearch.setNumFound(10);
|
myCurrentSearch.setNumFound(10);
|
||||||
|
|
||||||
when(mySearchCacheSvc.fetchByUuid(any())).thenAnswer(t -> Optional.ofNullable(myCurrentSearch));
|
when(mySearchCacheSvc.fetchByUuid(any(), any())).thenAnswer(t -> Optional.ofNullable(myCurrentSearch));
|
||||||
|
|
||||||
when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any())).thenAnswer(t -> {
|
when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any(), any())).thenAnswer(t -> {
|
||||||
when(mySearchCacheSvc.fetchByUuid(any())).thenAnswer(t2 -> Optional.empty());
|
when(mySearchCacheSvc.fetchByUuid(any(), any())).thenAnswer(t2 -> Optional.empty());
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -248,7 +247,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
myCurrentSearch.setStatus(SearchStatusEnum.PASSCMPLET);
|
myCurrentSearch.setStatus(SearchStatusEnum.PASSCMPLET);
|
||||||
myCurrentSearch.setNumFound(10);
|
myCurrentSearch.setNumFound(10);
|
||||||
|
|
||||||
when(mySearchCacheSvc.fetchByUuid(any())).thenAnswer(t -> {
|
when(mySearchCacheSvc.fetchByUuid(any(), any())).thenAnswer(t -> {
|
||||||
sleepAtLeast(100);
|
sleepAtLeast(100);
|
||||||
return Optional.ofNullable(myCurrentSearch);
|
return Optional.ofNullable(myCurrentSearch);
|
||||||
});
|
});
|
||||||
|
@ -373,7 +372,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
List<JpaPid> pids = createPidSequence(800);
|
List<JpaPid> pids = createPidSequence(800);
|
||||||
IResultIterator iter = new SlowIterator(pids.iterator(), 2);
|
IResultIterator iter = new SlowIterator(pids.iterator(), 2);
|
||||||
when(mySearchBuilder.createQuery(same(params), any(), any(), nullable(RequestPartitionId.class))).thenReturn(iter);
|
when(mySearchBuilder.createQuery(same(params), any(), any(), nullable(RequestPartitionId.class))).thenReturn(iter);
|
||||||
when(mySearchCacheSvc.save(any())).thenAnswer(t -> {
|
when(mySearchCacheSvc.save(any(), any())).thenAnswer(t -> {
|
||||||
ourLog.info("Saving search");
|
ourLog.info("Saving search");
|
||||||
return t.getArgument(0, Search.class);
|
return t.getArgument(0, Search.class);
|
||||||
});
|
});
|
||||||
|
@ -386,7 +385,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
assertEquals(790, result.size());
|
assertEquals(790, result.size());
|
||||||
|
|
||||||
ArgumentCaptor<Search> searchCaptor = ArgumentCaptor.forClass(Search.class);
|
ArgumentCaptor<Search> searchCaptor = ArgumentCaptor.forClass(Search.class);
|
||||||
verify(mySearchCacheSvc, atLeast(1)).save(searchCaptor.capture());
|
verify(mySearchCacheSvc, atLeast(1)).save(searchCaptor.capture(), any());
|
||||||
Search search = searchCaptor.getValue();
|
Search search = searchCaptor.getValue();
|
||||||
assertEquals(SearchTypeEnum.SEARCH, search.getSearchType());
|
assertEquals(SearchTypeEnum.SEARCH, search.getSearchType());
|
||||||
|
|
||||||
|
@ -450,7 +449,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
search.setStatus(SearchStatusEnum.LOADING);
|
search.setStatus(SearchStatusEnum.LOADING);
|
||||||
search.setSearchParameterMap(new SearchParameterMap());
|
search.setSearchParameterMap(new SearchParameterMap());
|
||||||
|
|
||||||
when(mySearchCacheSvc.fetchByUuid(eq(uuid))).thenReturn(Optional.of(search));
|
when(mySearchCacheSvc.fetchByUuid(eq(uuid), any())).thenReturn(Optional.of(search));
|
||||||
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
|
doAnswer(loadPids()).when(mySearchBuilder).loadResourcesByPid(any(Collection.class), any(Collection.class), any(List.class), anyBoolean(), any());
|
||||||
|
|
||||||
PersistedJpaBundleProvider provider;
|
PersistedJpaBundleProvider provider;
|
||||||
|
@ -567,7 +566,7 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
search.setStatus(SearchStatusEnum.FINISHED);
|
search.setStatus(SearchStatusEnum.FINISHED);
|
||||||
search.setNumFound(100);
|
search.setNumFound(100);
|
||||||
search.setTotalCount(100);
|
search.setTotalCount(100);
|
||||||
when(mySearchCacheSvc.fetchByUuid(eq("0000-1111"))).thenReturn(Optional.of(search));
|
when(mySearchCacheSvc.fetchByUuid(eq("0000-1111"), any())).thenReturn(Optional.of(search));
|
||||||
|
|
||||||
when(mySearchResultCacheSvc.fetchResultPids(any(), anyInt(), anyInt(), any(), any())).thenReturn(null);
|
when(mySearchResultCacheSvc.fetchResultPids(any(), anyInt(), anyInt(), any(), any())).thenReturn(null);
|
||||||
|
|
||||||
|
@ -594,9 +593,9 @@ public class SearchCoordinatorSvcImplTest extends BaseSearchSvc {
|
||||||
search.setStatus(SearchStatusEnum.PASSCMPLET);
|
search.setStatus(SearchStatusEnum.PASSCMPLET);
|
||||||
search.setNumFound(5);
|
search.setNumFound(5);
|
||||||
search.setSearchParameterMap(new SearchParameterMap());
|
search.setSearchParameterMap(new SearchParameterMap());
|
||||||
when(mySearchCacheSvc.fetchByUuid(eq("0000-1111"))).thenReturn(Optional.of(search));
|
when(mySearchCacheSvc.fetchByUuid(eq("0000-1111"), any())).thenReturn(Optional.of(search));
|
||||||
|
|
||||||
when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any())).thenAnswer(t -> {
|
when(mySearchCacheSvc.tryToMarkSearchAsInProgress(any(), any())).thenAnswer(t -> {
|
||||||
search.setStatus(SearchStatusEnum.LOADING);
|
search.setStatus(SearchStatusEnum.LOADING);
|
||||||
return Optional.of(search);
|
return Optional.of(search);
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4281,7 +4281,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
||||||
search.setStatus(SearchStatusEnum.FAILED);
|
search.setStatus(SearchStatusEnum.FAILED);
|
||||||
search.setFailureCode(500);
|
search.setFailureCode(500);
|
||||||
search.setFailureMessage("FOO");
|
search.setFailureMessage("FOO");
|
||||||
mySearchCacheSvc.save(search);
|
mySearchCacheSvc.save(search, RequestPartitionId.defaultPartition());
|
||||||
});
|
});
|
||||||
|
|
||||||
IBundleProvider results = myEncounterDao.search(map);
|
IBundleProvider results = myEncounterDao.search(map);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ca.uhn.fhir.jpa.dao.r4;
|
package ca.uhn.fhir.jpa.dao.r4;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||||
import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
|
import ca.uhn.fhir.jpa.api.svc.ISearchCoordinatorSvc;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchResultDao;
|
||||||
|
@ -85,7 +86,7 @@ public class SearchCoordinatorSvcImplTest extends BaseJpaR4Test {
|
||||||
assertEquals(30, mySearchResultDao.count());
|
assertEquals(30, mySearchResultDao.count());
|
||||||
});
|
});
|
||||||
|
|
||||||
myDatabaseCacheSvc.pollForStaleSearchesAndDeleteThem();
|
myDatabaseCacheSvc.pollForStaleSearchesAndDeleteThem(RequestPartitionId.allPartitions());
|
||||||
runInTransaction(()->{
|
runInTransaction(()->{
|
||||||
// We should delete up to 10, but 3 don't get deleted since they have too many results to delete in one pass
|
// We should delete up to 10, but 3 don't get deleted since they have too many results to delete in one pass
|
||||||
assertEquals(13, mySearchDao.count());
|
assertEquals(13, mySearchDao.count());
|
||||||
|
@ -94,7 +95,7 @@ public class SearchCoordinatorSvcImplTest extends BaseJpaR4Test {
|
||||||
assertEquals(15, mySearchResultDao.count());
|
assertEquals(15, mySearchResultDao.count());
|
||||||
});
|
});
|
||||||
|
|
||||||
myDatabaseCacheSvc.pollForStaleSearchesAndDeleteThem();
|
myDatabaseCacheSvc.pollForStaleSearchesAndDeleteThem(RequestPartitionId.allPartitions());
|
||||||
runInTransaction(()->{
|
runInTransaction(()->{
|
||||||
// Once again we attempt to delete 10, but the first 3 don't get deleted and still remain
|
// Once again we attempt to delete 10, but the first 3 don't get deleted and still remain
|
||||||
// (total is 6 because 3 weren't deleted, and they blocked another 3 that might have been)
|
// (total is 6 because 3 weren't deleted, and they blocked another 3 that might have been)
|
||||||
|
@ -103,7 +104,7 @@ public class SearchCoordinatorSvcImplTest extends BaseJpaR4Test {
|
||||||
assertEquals(0, mySearchResultDao.count());
|
assertEquals(0, mySearchResultDao.count());
|
||||||
});
|
});
|
||||||
|
|
||||||
myDatabaseCacheSvc.pollForStaleSearchesAndDeleteThem();
|
myDatabaseCacheSvc.pollForStaleSearchesAndDeleteThem(RequestPartitionId.allPartitions());
|
||||||
runInTransaction(()->{
|
runInTransaction(()->{
|
||||||
assertEquals(0, mySearchDao.count());
|
assertEquals(0, mySearchDao.count());
|
||||||
assertEquals(0, mySearchDao.countDeleted());
|
assertEquals(0, mySearchDao.countDeleted());
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,22 @@
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server Test Utilities
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
package ca.uhn.fhir.jpa.test;
|
package ca.uhn.fhir.jpa.test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
|
|
@ -1,3 +1,22 @@
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR JPA Server Test Utilities
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
package ca.uhn.fhir.jpa.test;
|
package ca.uhn.fhir.jpa.test;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package ca.uhn.fhir.jpa.search.cache;
|
package ca.uhn.fhir.jpa.search.cache;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||||
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
import ca.uhn.fhir.jpa.dao.data.ISearchDao;
|
||||||
|
import ca.uhn.fhir.jpa.dao.tx.NonTransactionalHapiTransactionService;
|
||||||
import ca.uhn.fhir.jpa.entity.Search;
|
import ca.uhn.fhir.jpa.entity.Search;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
import ca.uhn.fhir.jpa.model.search.SearchStatusEnum;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
@ -9,7 +11,6 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -30,14 +31,11 @@ public class DatabaseSearchCacheSvcImplTest {
|
||||||
@Mock
|
@Mock
|
||||||
private ISearchDao mySearchDao;
|
private ISearchDao mySearchDao;
|
||||||
|
|
||||||
@Mock
|
|
||||||
private PlatformTransactionManager myTxManager;
|
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() {
|
public void before() {
|
||||||
mySvc = new DatabaseSearchCacheSvcImpl();
|
mySvc = new DatabaseSearchCacheSvcImpl();
|
||||||
mySvc.setSearchDaoForUnitTest(mySearchDao);
|
mySvc.setSearchDaoForUnitTest(mySearchDao);
|
||||||
mySvc.setTxManagerForUnitTest(myTxManager);
|
mySvc.setTransactionServiceForUnitTest(new NonTransactionalHapiTransactionService());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -48,7 +46,7 @@ public class DatabaseSearchCacheSvcImplTest {
|
||||||
when(mySearchDao.save(any())).thenReturn(updated);
|
when(mySearchDao.save(any())).thenReturn(updated);
|
||||||
|
|
||||||
Search search = new Search();
|
Search search = new Search();
|
||||||
Optional<Search> outcome = mySvc.tryToMarkSearchAsInProgress(search);
|
Optional<Search> outcome = mySvc.tryToMarkSearchAsInProgress(search, RequestPartitionId.allPartitions());
|
||||||
assertTrue(outcome.isPresent());
|
assertTrue(outcome.isPresent());
|
||||||
|
|
||||||
verify(mySearchDao, times(1)).save(any());
|
verify(mySearchDao, times(1)).save(any());
|
||||||
|
@ -63,7 +61,7 @@ public class DatabaseSearchCacheSvcImplTest {
|
||||||
when(mySearchDao.save(any())).thenThrow(new HibernateException("FOO"));
|
when(mySearchDao.save(any())).thenThrow(new HibernateException("FOO"));
|
||||||
|
|
||||||
Search search = new Search();
|
Search search = new Search();
|
||||||
Optional<Search> outcome = mySvc.tryToMarkSearchAsInProgress(search);
|
Optional<Search> outcome = mySvc.tryToMarkSearchAsInProgress(search, RequestPartitionId.allPartitions());
|
||||||
assertFalse(outcome.isPresent());
|
assertFalse(outcome.isPresent());
|
||||||
verify(mySearchDao, times(1)).save(any());
|
verify(mySearchDao, times(1)).save(any());
|
||||||
}
|
}
|
||||||
|
@ -75,7 +73,7 @@ public class DatabaseSearchCacheSvcImplTest {
|
||||||
when(mySearchDao.findById(any())).thenReturn(Optional.of(updated));
|
when(mySearchDao.findById(any())).thenReturn(Optional.of(updated));
|
||||||
|
|
||||||
Search search = new Search();
|
Search search = new Search();
|
||||||
Optional<Search> outcome = mySvc.tryToMarkSearchAsInProgress(search);
|
Optional<Search> outcome = mySvc.tryToMarkSearchAsInProgress(search, RequestPartitionId.allPartitions());
|
||||||
assertFalse(outcome.isPresent());
|
assertFalse(outcome.isPresent());
|
||||||
verify(mySearchDao, never()).save(any());
|
verify(mySearchDao, never()).save(any());
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -44,6 +44,11 @@
|
||||||
<artifactId>httpcore</artifactId>
|
<artifactId>httpcore</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
|
||||||
|
<artifactId>owasp-java-html-sanitizer</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Spring is added as an optional dependency just so that it
|
Spring is added as an optional dependency just so that it
|
||||||
can be used for CORS
|
can be used for CORS
|
||||||
|
|
|
@ -39,6 +39,7 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
import ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding;
|
import ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding;
|
||||||
|
import ca.uhn.fhir.rest.server.util.NarrativeUtil;
|
||||||
import ca.uhn.fhir.util.ClasspathUtil;
|
import ca.uhn.fhir.util.ClasspathUtil;
|
||||||
import ca.uhn.fhir.util.FhirTerser;
|
import ca.uhn.fhir.util.FhirTerser;
|
||||||
import ca.uhn.fhir.util.StopWatch;
|
import ca.uhn.fhir.util.StopWatch;
|
||||||
|
@ -800,28 +801,11 @@ public class ResponseHighlighterInterceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FHIR only allows a pretty restricted set of HTML tags and attributes, in order
|
* Sanitize the narrative so that it's safe to render (strip any
|
||||||
* to avoid any risk of injection attacks. If anything that isn't explicitly allowed
|
* links, potentially unsafe CSS, etc.)
|
||||||
* by FHIR is present in the narrative we won't render it and instead we'll explain
|
|
||||||
* what validation problems we found.
|
|
||||||
*/
|
*/
|
||||||
if (xhtmlNode != null) {
|
if (xhtmlNode != null) {
|
||||||
List<String> errors = new ArrayList<>();
|
xhtmlNode = NarrativeUtil.sanitize(xhtmlNode);
|
||||||
Validate.isTrue(xhtmlNode.getName() == null);
|
|
||||||
xhtmlNode.getFirstElement().validate(errors, "", true, false, false);
|
|
||||||
if (errors.size() > 0) {
|
|
||||||
StringBuilder errorNarrative = new StringBuilder();
|
|
||||||
errorNarrative.append("Can not render narrative due to validation errors:");
|
|
||||||
errorNarrative.append("<ul>");
|
|
||||||
errors.forEach(next -> {
|
|
||||||
errorNarrative.append("<li>");
|
|
||||||
errorNarrative.append(sanitizeUrlPart(next));
|
|
||||||
errorNarrative.append("</li>");
|
|
||||||
});
|
|
||||||
errorNarrative.append("</ul>");
|
|
||||||
return errorNarrative.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return xhtmlNode.getValueAsString();
|
return xhtmlNode.getValueAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*-
|
||||||
|
* #%L
|
||||||
|
* HAPI FHIR - Server Framework
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2014 - 2023 Smile CDR, Inc.
|
||||||
|
* %%
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package ca.uhn.fhir.rest.server.util;
|
||||||
|
|
||||||
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
|
import org.owasp.html.HtmlPolicyBuilder;
|
||||||
|
import org.owasp.html.PolicyFactory;
|
||||||
|
import org.owasp.html.Sanitizers;
|
||||||
|
|
||||||
|
public class NarrativeUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non instantiable
|
||||||
|
*/
|
||||||
|
private NarrativeUtil() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method accepts an Xhtml (generally a narrative) and sanitizes it,
|
||||||
|
* removing unsafe elements. This method leverages the
|
||||||
|
* <a href="https://github.com/OWASP/java-html-sanitizer/blob/master/pom.xml">OWASP Java HTML Sanitizer</a>
|
||||||
|
* to perform this task. The policy allows the following:
|
||||||
|
* <ul>
|
||||||
|
* <li>Block tags are allowed</li>
|
||||||
|
* <li>Tables are allowed</li>
|
||||||
|
* <li>Basic styles are allowed but any styles considered unsafe are removed from the document (e.g. any style declarations that could be used to load external content)</li>
|
||||||
|
* <li>Attributes considered safe are allowed</li>
|
||||||
|
* <li>Any links (<a href="....") are removed although any text inside the link is retained</li>
|
||||||
|
* <li>All other elements and attributes are removed</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static String sanitize(String theHtml) {
|
||||||
|
XhtmlNode node = new XhtmlNode();
|
||||||
|
node.setValueAsString(theHtml);
|
||||||
|
return sanitize(node).getValueAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method accepts an Xhtml (generally a narrative) and sanitizes it,
|
||||||
|
* removing unsafe elements. This method leverages the
|
||||||
|
* <a href="https://github.com/OWASP/java-html-sanitizer/blob/master/pom.xml">OWASP Java HTML Sanitizer</a>
|
||||||
|
* to perform this task. The policy allows the following:
|
||||||
|
* <ul>
|
||||||
|
* <li>Block tags are allowed</li>
|
||||||
|
* <li>Tables are allowed</li>
|
||||||
|
* <li>Basic styles are allowed but any styles considered unsafe are removed from the document (e.g. any style declarations that could be used to load external content)</li>
|
||||||
|
* <li>Attributes considered safe are allowed</li>
|
||||||
|
* <li>Any links (<a href="....") are removed although any text inside the link is retained</li>
|
||||||
|
* <li>All other elements and attributes are removed</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static XhtmlNode sanitize(XhtmlNode theNode) {
|
||||||
|
String html = theNode.getValueAsString();
|
||||||
|
|
||||||
|
PolicyFactory idPolicy = new HtmlPolicyBuilder()
|
||||||
|
.allowAttributes("id").globally()
|
||||||
|
.toFactory();
|
||||||
|
|
||||||
|
PolicyFactory policy = Sanitizers.FORMATTING
|
||||||
|
.and(Sanitizers.BLOCKS)
|
||||||
|
.and(Sanitizers.TABLES)
|
||||||
|
.and(Sanitizers.STYLES)
|
||||||
|
.and(idPolicy);
|
||||||
|
String safeHTML = policy.sanitize(html);
|
||||||
|
|
||||||
|
XhtmlNode retVal = new XhtmlNode();
|
||||||
|
retVal.setValueAsString(safeHTML);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package ca.uhn.fhir.rest.server.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class NarrativeUtilTest {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource({
|
||||||
|
"<div><SPAN ID=\"foo\">hello</SPAN></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\"><span id=\"foo\">hello</span></div>",
|
||||||
|
"<div><span id=\"foo\">hello</span></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\"><span id=\"foo\">hello</span></div>",
|
||||||
|
"<div><SPAN ONCLICK=\"hello()\">hello</SPAN></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\">hello</div>",
|
||||||
|
"<div><span onclick=\"hello()\">hello</span></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\">hello</div>",
|
||||||
|
"<div><a href=\"http://goodbye\">hello</a></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\">hello</div>",
|
||||||
|
"<div><table><tr><td>hello</td></tr></table></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\"><table><tbody><tr><td>hello</td></tr></tbody></table></div>",
|
||||||
|
"<div><span style=\"font-size: 100px;\">hello</span></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\"><span style=\"font-size:100px\">hello</span></div>",
|
||||||
|
"<div><span style=\"background: url('test.jpg')\">hello</span></div> , <div xmlns=\"http://www.w3.org/1999/xhtml\">hello</div>",
|
||||||
|
"hello , <div xmlns=\"http://www.w3.org/1999/xhtml\">hello</div>",
|
||||||
|
"empty , null",
|
||||||
|
"null , null"
|
||||||
|
})
|
||||||
|
public void testValidateIsCaseInsensitive(String theHtml, String theExpected) {
|
||||||
|
String output = NarrativeUtil.sanitize(fixNull(theHtml));
|
||||||
|
assertEquals(fixNull(theExpected), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String fixNull(String theExpected) {
|
||||||
|
if ("null".equals(theExpected)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ("empty".equals(theExpected)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return theExpected;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -20,7 +21,8 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,6 @@ public interface ISearchCoordinatorSvc<T extends IResourcePersistentId> {
|
||||||
* Fetch the total number of search results for the given currently executing search, if one is currently executing and
|
* Fetch the total number of search results for the given currently executing search, if one is currently executing and
|
||||||
* the total is known. Will return empty otherwise
|
* the total is known. Will return empty otherwise
|
||||||
*/
|
*/
|
||||||
Optional<Integer> getSearchTotal(String theUuid, @Nullable RequestDetails theRequestDetails);
|
Optional<Integer> getSearchTotal(String theUuid, @Nullable RequestDetails theRequestDetails, RequestPartitionId theRequestPartitionId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,22 @@ public interface IHapiTransactionService {
|
||||||
*/
|
*/
|
||||||
IExecutionBuilder withSystemRequest();
|
IExecutionBuilder withSystemRequest();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fluent builder for internal system requests with no external
|
||||||
|
* {@link RequestDetails} associated and a pre-specified partition ID.
|
||||||
|
* This method is sugar for
|
||||||
|
* <pre>
|
||||||
|
* withSystemRequest()
|
||||||
|
* .withRequestPartitionId(thePartitionId);
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @since 6.6.0
|
||||||
|
*/
|
||||||
|
default IExecutionBuilder withSystemRequestOnPartition(RequestPartitionId theRequestPartitionId) {
|
||||||
|
return withSystemRequest()
|
||||||
|
.withRequestPartitionId(theRequestPartitionId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated It is highly recommended to use {@link #withRequest(RequestDetails)} instead of this method, for increased visibility.
|
* @deprecated It is highly recommended to use {@link #withRequest(RequestDetails)} instead of this method, for increased visibility.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -990,8 +990,7 @@ public class ResponseHighlightingInterceptorTest {
|
||||||
HttpGet httpGet = new HttpGet(url);
|
HttpGet httpGet = new HttpGet(url);
|
||||||
try (CloseableHttpResponse response = ourClient.execute(httpGet)) {
|
try (CloseableHttpResponse response = ourClient.execute(httpGet)) {
|
||||||
String resp = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
String resp = IOUtils.toString(response.getEntity().getContent(), Charsets.UTF_8);
|
||||||
assertThat(resp, not(containsString("<thead><tr><th>Header1</th><th>Header2</th></tr></thead>")));
|
assertThat(resp, containsString("<table><thead><tr><th>Header1</th>"));
|
||||||
assertThat(resp, containsString("Error at div/table: Found attribute table.onclick in a resource"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import ca.uhn.fhir.rest.client.api.IClientInterceptor;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
import ca.uhn.fhir.rest.client.api.IHttpRequest;
|
||||||
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
import ca.uhn.fhir.rest.client.api.IHttpResponse;
|
||||||
import ca.uhn.fhir.rest.client.impl.GenericClient;
|
import ca.uhn.fhir.rest.client.impl.GenericClient;
|
||||||
|
import ca.uhn.fhir.rest.server.util.NarrativeUtil;
|
||||||
import ca.uhn.fhir.to.model.HomeRequest;
|
import ca.uhn.fhir.to.model.HomeRequest;
|
||||||
import ca.uhn.fhir.util.BundleUtil;
|
import ca.uhn.fhir.util.BundleUtil;
|
||||||
import ca.uhn.fhir.util.ExtensionConstants;
|
import ca.uhn.fhir.util.ExtensionConstants;
|
||||||
|
@ -522,7 +523,7 @@ public class BaseController {
|
||||||
theModelMap.put("resultBodyIsLong", resultBodyText.length() > 1000);
|
theModelMap.put("resultBodyIsLong", resultBodyText.length() > 1000);
|
||||||
theModelMap.put("requestHeaders", requestHeaders);
|
theModelMap.put("requestHeaders", requestHeaders);
|
||||||
theModelMap.put("responseHeaders", responseHeaders);
|
theModelMap.put("responseHeaders", responseHeaders);
|
||||||
theModelMap.put("narrative", narrativeString);
|
theModelMap.put("narrative", NarrativeUtil.sanitize(narrativeString));
|
||||||
theModelMap.put("latencyMs", theLatency);
|
theModelMap.put("latencyMs", theLatency);
|
||||||
|
|
||||||
theModelMap.put("config", myConfig);
|
theModelMap.put("config", myConfig);
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-deployable-pom</artifactId>
|
<artifactId>hapi-deployable-pom</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
8
pom.xml
8
pom.xml
|
@ -7,7 +7,8 @@
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<name>HAPI-FHIR</name>
|
<name>HAPI-FHIR</name>
|
||||||
<description>An open-source implementation of the FHIR specification in Java.</description>
|
<description>An open-source implementation of the FHIR specification in Java.</description>
|
||||||
<url>https://hapifhir.io</url>
|
<url>https://hapifhir.io</url>
|
||||||
|
@ -1059,6 +1060,11 @@
|
||||||
<artifactId>caffeine</artifactId>
|
<artifactId>caffeine</artifactId>
|
||||||
<version>${caffeine_version}</version>
|
<version>${caffeine_version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
|
||||||
|
<artifactId>owasp-java-html-sanitizer</artifactId>
|
||||||
|
<version>20211018.2</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.graphql-java</groupId>
|
<groupId>com.graphql-java</groupId>
|
||||||
<artifactId>graphql-java</artifactId>
|
<artifactId>graphql-java</artifactId>
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||||
<artifactId>hapi-fhir</artifactId>
|
<artifactId>hapi-fhir</artifactId>
|
||||||
<version>6.5.10-SNAPSHOT</version>
|
<version>6.5.11-SNAPSHOT</version>
|
||||||
|
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue