mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-21 04:15:23 +00:00
Includes performance enhancement (#1702)
* Includes performance enhancement * Add changelog * Test fix * Fix typo * A few coverage cleanups * Test fix * Fix changelog
This commit is contained in:
parent
60f16dd91d
commit
64f07e4dc0
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
type: perf
|
||||||
|
issue: 1702
|
||||||
|
title: "Loading of _include and _revinclude values has been optimized to be slightly faster"
|
@ -29,17 +29,29 @@ import ca.uhn.fhir.interceptor.api.Pointcut;
|
|||||||
import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceSearchViewDao;
|
||||||
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
|
||||||
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
|
||||||
import ca.uhn.fhir.jpa.dao.predicate.*;
|
import ca.uhn.fhir.jpa.dao.predicate.PredicateBuilder;
|
||||||
|
import ca.uhn.fhir.jpa.dao.predicate.PredicateBuilderFactory;
|
||||||
|
import ca.uhn.fhir.jpa.dao.predicate.QueryRoot;
|
||||||
|
import ca.uhn.fhir.jpa.dao.predicate.SearchBuilderJoinEnum;
|
||||||
|
import ca.uhn.fhir.jpa.dao.predicate.SearchBuilderJoinKey;
|
||||||
import ca.uhn.fhir.jpa.entity.ResourceSearchView;
|
import ca.uhn.fhir.jpa.entity.ResourceSearchView;
|
||||||
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
|
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
|
||||||
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
|
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
|
||||||
import ca.uhn.fhir.jpa.model.entity.*;
|
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
|
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||||
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
import ca.uhn.fhir.jpa.model.search.SearchRuntimeDetails;
|
||||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||||
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
|
||||||
import ca.uhn.fhir.jpa.util.*;
|
import ca.uhn.fhir.jpa.util.BaseIterator;
|
||||||
|
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
|
||||||
|
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
|
||||||
|
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
|
||||||
|
import ca.uhn.fhir.jpa.util.SqlQueryList;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.api.Include;
|
import ca.uhn.fhir.model.api.Include;
|
||||||
@ -80,10 +92,27 @@ import javax.persistence.EntityManager;
|
|||||||
import javax.persistence.PersistenceContext;
|
import javax.persistence.PersistenceContext;
|
||||||
import javax.persistence.PersistenceContextType;
|
import javax.persistence.PersistenceContextType;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.*;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import java.util.*;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
|
import javax.persistence.criteria.From;
|
||||||
|
import javax.persistence.criteria.Join;
|
||||||
|
import javax.persistence.criteria.JoinType;
|
||||||
|
import javax.persistence.criteria.Order;
|
||||||
|
import javax.persistence.criteria.Predicate;
|
||||||
|
import javax.persistence.criteria.Root;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.*;
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SearchBuilder is responsible for actually forming the SQL query that handles
|
* The SearchBuilder is responsible for actually forming the SQL query that handles
|
||||||
@ -103,8 +132,9 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
private static final List<ResourcePersistentId> EMPTY_LONG_LIST = Collections.unmodifiableList(new ArrayList<>());
|
private static final List<ResourcePersistentId> EMPTY_LONG_LIST = Collections.unmodifiableList(new ArrayList<>());
|
||||||
private static final Logger ourLog = LoggerFactory.getLogger(SearchBuilder.class);
|
private static final Logger ourLog = LoggerFactory.getLogger(SearchBuilder.class);
|
||||||
private static ResourcePersistentId NO_MORE = new ResourcePersistentId(-1L);
|
private static ResourcePersistentId NO_MORE = new ResourcePersistentId(-1L);
|
||||||
@Autowired
|
private final QueryRoot myQueryRoot = new QueryRoot();
|
||||||
private DaoConfig myDaoConfig;
|
private final String myResourceName;
|
||||||
|
private final Class<? extends IBaseResource> myResourceType;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected IInterceptorBroadcaster myInterceptorBroadcaster;
|
protected IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -112,6 +142,8 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||||
protected EntityManager myEntityManager;
|
protected EntityManager myEntityManager;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private DaoConfig myDaoConfig;
|
||||||
|
@Autowired
|
||||||
private IResourceSearchViewDao myResourceSearchViewDao;
|
private IResourceSearchViewDao myResourceSearchViewDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private FhirContext myContext;
|
private FhirContext myContext;
|
||||||
@ -123,7 +155,6 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
private ISearchParamRegistry mySearchParamRegistry;
|
private ISearchParamRegistry mySearchParamRegistry;
|
||||||
@Autowired
|
@Autowired
|
||||||
private PredicateBuilderFactory myPredicateBuilderFactory;
|
private PredicateBuilderFactory myPredicateBuilderFactory;
|
||||||
|
|
||||||
private List<ResourcePersistentId> myAlsoIncludePids;
|
private List<ResourcePersistentId> myAlsoIncludePids;
|
||||||
private CriteriaBuilder myBuilder;
|
private CriteriaBuilder myBuilder;
|
||||||
private IDao myCallingDao;
|
private IDao myCallingDao;
|
||||||
@ -133,9 +164,6 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
private Integer myMaxResultsToFetch;
|
private Integer myMaxResultsToFetch;
|
||||||
private Set<ResourcePersistentId> myPidSet;
|
private Set<ResourcePersistentId> myPidSet;
|
||||||
private PredicateBuilder myPredicateBuilder;
|
private PredicateBuilder myPredicateBuilder;
|
||||||
private final QueryRoot myQueryRoot = new QueryRoot();
|
|
||||||
private final String myResourceName;
|
|
||||||
private final Class<? extends IBaseResource> myResourceType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -595,6 +623,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
String searchFieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid";
|
String searchFieldName = theReverseMode ? "myTargetResourcePid" : "mySourceResourcePid";
|
||||||
|
String findFieldName = theReverseMode ? "mySourceResourcePid" : "myTargetResourcePid";
|
||||||
|
|
||||||
Collection<ResourcePersistentId> nextRoundMatches = theMatches;
|
Collection<ResourcePersistentId> nextRoundMatches = theMatches;
|
||||||
HashSet<ResourcePersistentId> allAdded = new HashSet<>();
|
HashSet<ResourcePersistentId> allAdded = new HashSet<>();
|
||||||
@ -619,17 +648,17 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
boolean matchAll = "*".equals(nextInclude.getValue());
|
boolean matchAll = "*".equals(nextInclude.getValue());
|
||||||
if (matchAll) {
|
if (matchAll) {
|
||||||
String sql;
|
String sql;
|
||||||
sql = "SELECT r FROM ResourceLink r WHERE r." + searchFieldName + " IN (:target_pids) ";
|
sql = "SELECT r." + findFieldName + " FROM ResourceLink r WHERE r." + searchFieldName + " IN (:target_pids) ";
|
||||||
List<Collection<ResourcePersistentId>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE);
|
List<Collection<ResourcePersistentId>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE);
|
||||||
for (Collection<ResourcePersistentId> nextPartition : partitions) {
|
for (Collection<ResourcePersistentId> nextPartition : partitions) {
|
||||||
TypedQuery<ResourceLink> q = theEntityManager.createQuery(sql, ResourceLink.class);
|
TypedQuery<Long> q = theEntityManager.createQuery(sql, Long.class);
|
||||||
q.setParameter("target_pids", ResourcePersistentId.toLongList(nextPartition));
|
q.setParameter("target_pids", ResourcePersistentId.toLongList(nextPartition));
|
||||||
List<ResourceLink> results = q.getResultList();
|
List<Long> results = q.getResultList();
|
||||||
for (ResourceLink resourceLink : results) {
|
for (Long resourceLink : results) {
|
||||||
if (theReverseMode) {
|
if (theReverseMode) {
|
||||||
pidsToInclude.add(new ResourcePersistentId(resourceLink.getSourceResourcePid()));
|
pidsToInclude.add(new ResourcePersistentId(resourceLink));
|
||||||
} else {
|
} else {
|
||||||
pidsToInclude.add(new ResourcePersistentId(resourceLink.getTargetResourcePid()));
|
pidsToInclude.add(new ResourcePersistentId(resourceLink));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -666,16 +695,16 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
|
|
||||||
boolean haveTargetTypesDefinedByParam = param.hasTargets();
|
boolean haveTargetTypesDefinedByParam = param.hasTargets();
|
||||||
if (targetResourceType != null) {
|
if (targetResourceType != null) {
|
||||||
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids) AND r.myTargetResourceType = :target_resource_type";
|
sql = "SELECT r." + findFieldName + " FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids) AND r.myTargetResourceType = :target_resource_type";
|
||||||
} else if (haveTargetTypesDefinedByParam) {
|
} else if (haveTargetTypesDefinedByParam) {
|
||||||
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids) AND r.myTargetResourceType in (:target_resource_types)";
|
sql = "SELECT r." + findFieldName + " FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids) AND r.myTargetResourceType in (:target_resource_types)";
|
||||||
} else {
|
} else {
|
||||||
sql = "SELECT r FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)";
|
sql = "SELECT r." + findFieldName + " FROM ResourceLink r WHERE r.mySourcePath = :src_path AND r." + searchFieldName + " IN (:target_pids)";
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Collection<ResourcePersistentId>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE);
|
List<Collection<ResourcePersistentId>> partitions = partition(nextRoundMatches, MAXIMUM_PAGE_SIZE);
|
||||||
for (Collection<ResourcePersistentId> nextPartition : partitions) {
|
for (Collection<ResourcePersistentId> nextPartition : partitions) {
|
||||||
TypedQuery<ResourceLink> q = theEntityManager.createQuery(sql, ResourceLink.class);
|
TypedQuery<Long> q = theEntityManager.createQuery(sql, Long.class);
|
||||||
q.setParameter("src_path", nextPath);
|
q.setParameter("src_path", nextPath);
|
||||||
q.setParameter("target_pids", ResourcePersistentId.toLongList(nextPartition));
|
q.setParameter("target_pids", ResourcePersistentId.toLongList(nextPartition));
|
||||||
if (targetResourceType != null) {
|
if (targetResourceType != null) {
|
||||||
@ -683,18 +712,10 @@ public class SearchBuilder implements ISearchBuilder {
|
|||||||
} else if (haveTargetTypesDefinedByParam) {
|
} else if (haveTargetTypesDefinedByParam) {
|
||||||
q.setParameter("target_resource_types", param.getTargets());
|
q.setParameter("target_resource_types", param.getTargets());
|
||||||
}
|
}
|
||||||
List<ResourceLink> results = q.getResultList();
|
List<Long> results = q.getResultList();
|
||||||
for (ResourceLink resourceLink : results) {
|
for (Long resourceLink : results) {
|
||||||
if (theReverseMode) {
|
if (resourceLink != null) {
|
||||||
Long pid = resourceLink.getSourceResourcePid();
|
pidsToInclude.add(new ResourcePersistentId(resourceLink));
|
||||||
if (pid != null) {
|
|
||||||
pidsToInclude.add(new ResourcePersistentId(pid));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Long pid = resourceLink.getTargetResourcePid();
|
|
||||||
if (pid != null) {
|
|
||||||
pidsToInclude.add(new ResourcePersistentId(pid));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,10 @@ public class SearchBuilderTest {
|
|||||||
|
|
||||||
TypedQuery mockQuery = mock(TypedQuery.class);
|
TypedQuery mockQuery = mock(TypedQuery.class);
|
||||||
when(mockEntityManager.createQuery(any(), any())).thenReturn(mockQuery);
|
when(mockEntityManager.createQuery(any(), any())).thenReturn(mockQuery);
|
||||||
List<ResourceLink> resultList = new ArrayList<>();
|
List<Long> resultList = new ArrayList<>();
|
||||||
ResourceLink link = new ResourceLink();
|
Long link = 1L;
|
||||||
ResourceTable target = new ResourceTable();
|
ResourceTable target = new ResourceTable();
|
||||||
target.setId(1L);
|
target.setId(1L);
|
||||||
link.setTargetResource(target);
|
|
||||||
resultList.add(link);
|
resultList.add(link);
|
||||||
when(mockQuery.getResultList()).thenReturn(resultList);
|
when(mockQuery.getResultList()).thenReturn(resultList);
|
||||||
|
|
||||||
|
@ -162,6 +162,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
|
|||||||
@Qualifier("myConditionDaoR4")
|
@Qualifier("myConditionDaoR4")
|
||||||
protected IFhirResourceDao<Condition> myConditionDao;
|
protected IFhirResourceDao<Condition> myConditionDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myEpisodeOfCareDaoR4")
|
||||||
|
protected IFhirResourceDao<EpisodeOfCare> myEpisodeOfCareDao;
|
||||||
|
@Autowired
|
||||||
protected DaoConfig myDaoConfig;
|
protected DaoConfig myDaoConfig;
|
||||||
@Autowired
|
@Autowired
|
||||||
protected ModelConfig myModelConfig;
|
protected ModelConfig myModelConfig;
|
||||||
|
@ -4228,6 +4228,45 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCircularReferencesDontBreakRevIncludes() {
|
||||||
|
|
||||||
|
Patient p = new Patient();
|
||||||
|
p.setActive(true);
|
||||||
|
IIdType patientId = myPatientDao.create(p).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Encounter enc = new Encounter();
|
||||||
|
enc.setStatus(Encounter.EncounterStatus.ARRIVED);
|
||||||
|
enc.getSubject().setReference(patientId.getValue());
|
||||||
|
IIdType encId = myEncounterDao.create(enc).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
Condition cond = new Condition();
|
||||||
|
cond.addIdentifier().setSystem("http://foo").setValue("123");
|
||||||
|
IIdType conditionId = myConditionDao.create(cond).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
EpisodeOfCare ep = new EpisodeOfCare();
|
||||||
|
ep.setStatus(EpisodeOfCare.EpisodeOfCareStatus.ACTIVE);
|
||||||
|
IIdType epId = myEpisodeOfCareDao.create(ep).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
enc.getEpisodeOfCareFirstRep().setReference(ep.getId());
|
||||||
|
myEncounterDao.update(enc);
|
||||||
|
cond.getEncounter().setReference(enc.getId());
|
||||||
|
myConditionDao.update(cond);
|
||||||
|
ep.getDiagnosisFirstRep().getCondition().setReference(cond.getId());
|
||||||
|
myEpisodeOfCareDao.update(ep);
|
||||||
|
|
||||||
|
// Search time
|
||||||
|
SearchParameterMap params = new SearchParameterMap();
|
||||||
|
params.setLoadSynchronous(true);
|
||||||
|
params.addRevInclude(new Include("*").setRecurse(true));
|
||||||
|
IBundleProvider results = myPatientDao.search(params);
|
||||||
|
List<String> values = toUnqualifiedVersionlessIdValues(results);
|
||||||
|
assertThat(values.toString(), values, containsInAnyOrder(patientId.getValue(), encId.getValue(), conditionId.getValue(), epId.getValue()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private String toStringMultiline(List<?> theResults) {
|
private String toStringMultiline(List<?> theResults) {
|
||||||
StringBuilder b = new StringBuilder();
|
StringBuilder b = new StringBuilder();
|
||||||
for (Object next : theResults) {
|
for (Object next : theResults) {
|
||||||
|
@ -138,10 +138,6 @@ public class ResourceLink extends BaseResourceIndex {
|
|||||||
mySourceResourceType = theSourceResource.getResourceType();
|
mySourceResourceType = theSourceResource.getResourceType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSourceResourcePid() {
|
|
||||||
return mySourceResourcePid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceTable getTargetResource() {
|
public ResourceTable getTargetResource() {
|
||||||
return myTargetResource;
|
return myTargetResource;
|
||||||
}
|
}
|
||||||
@ -157,10 +153,6 @@ public class ResourceLink extends BaseResourceIndex {
|
|||||||
return myTargetResourcePid;
|
return myTargetResourcePid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTargetResourceUrl() {
|
|
||||||
return myTargetResourceUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTargetResourceUrl(IIdType theTargetResourceUrl) {
|
public void setTargetResourceUrl(IIdType theTargetResourceUrl) {
|
||||||
Validate.isTrue(theTargetResourceUrl.hasBaseUrl());
|
Validate.isTrue(theTargetResourceUrl.hasBaseUrl());
|
||||||
Validate.isTrue(theTargetResourceUrl.hasResourceType());
|
Validate.isTrue(theTargetResourceUrl.hasResourceType());
|
||||||
|
@ -160,7 +160,7 @@ public class ReadMethodBinding extends BaseResourceReturningMethodBinding {
|
|||||||
IBundleProvider retVal = toResourceList(response);
|
IBundleProvider retVal = toResourceList(response);
|
||||||
|
|
||||||
|
|
||||||
if (retVal.size() == 1) {
|
if (Integer.valueOf(1).equals(retVal.size())) {
|
||||||
List<IBaseResource> responseResources = retVal.getResources(0, 1);
|
List<IBaseResource> responseResources = retVal.getResources(0, 1);
|
||||||
IBaseResource responseResource = responseResources.get(0);
|
IBaseResource responseResource = responseResources.get(0);
|
||||||
|
|
||||||
|
@ -59,6 +59,11 @@ public class ReadMethodBindingTest {
|
|||||||
assertTrue(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
assertTrue(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
||||||
|
|
||||||
// VRead
|
// VRead
|
||||||
|
when(myRequestDetails.getId()).thenReturn(new IdDt("Patient/123/_history/123"));
|
||||||
|
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
||||||
|
|
||||||
|
// Type history
|
||||||
|
when(myRequestDetails.getId()).thenReturn(new IdDt("Patient/123"));
|
||||||
when(myRequestDetails.getResourceName()).thenReturn("Patient");
|
when(myRequestDetails.getResourceName()).thenReturn("Patient");
|
||||||
when(myRequestDetails.getOperation()).thenReturn("_history");
|
when(myRequestDetails.getOperation()).thenReturn("_history");
|
||||||
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
assertFalse(binding.incomingServerRequestMatchesMethod(myRequestDetails));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user