Reuse FHIRPath across JPA requests

This commit is contained in:
James Agnew 2019-08-29 14:13:31 -04:00
parent c5a88444b6
commit f59bdc4afe
3 changed files with 25 additions and 10 deletions

View File

@ -39,6 +39,7 @@ import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r4.context.IWorkerContext; import org.hl7.fhir.r4.context.IWorkerContext;
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r4.hapi.ctx.IValidationSupport; import org.hl7.fhir.r4.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Enumeration; import org.hl7.fhir.r4.model.Enumeration;
@ -48,6 +49,7 @@ import org.hl7.fhir.r4.model.Patient.PatientCommunicationComponent;
import org.hl7.fhir.r4.utils.FHIRPathEngine; import org.hl7.fhir.r4.utils.FHIRPathEngine;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.measure.unit.NonSI; import javax.measure.unit.NonSI;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -79,6 +81,8 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
@Autowired @Autowired
private org.hl7.fhir.r4.hapi.ctx.IValidationSupport myValidationSupport; private org.hl7.fhir.r4.hapi.ctx.IValidationSupport myValidationSupport;
private FHIRPathEngine myFhirPathEngine;
/** /**
* Constructor * Constructor
*/ */
@ -91,6 +95,14 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
public SearchParamExtractorR4(ModelConfig theModelConfig, FhirContext theCtx, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry) { public SearchParamExtractorR4(ModelConfig theModelConfig, FhirContext theCtx, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry) {
super(theCtx, theSearchParamRegistry); super(theCtx, theSearchParamRegistry);
myValidationSupport = theValidationSupport; myValidationSupport = theValidationSupport;
initFhirPath();
}
@PostConstruct
public void initFhirPath() {
IWorkerContext worker = new HapiWorkerContext(getContext(), myValidationSupport);
myFhirPathEngine = new FHIRPathEngine(worker);
myFhirPathEngine.setHostServices(new SearchParamExtractorR4HostServices());
} }
private void addQuantity(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, Quantity nextValue) { private void addQuantity(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, Quantity nextValue) {
@ -751,16 +763,12 @@ public class SearchParamExtractorR4 extends BaseSearchParamExtractor implements
*/ */
@Override @Override
protected List<Object> extractValues(String thePaths, IBaseResource theResource) { protected List<Object> extractValues(String thePaths, IBaseResource theResource) {
IWorkerContext worker = new org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext(getContext(), myValidationSupport);
FHIRPathEngine fp = new FHIRPathEngine(worker);
fp.setHostServices(new SearchParamExtractorR4HostServices());
List<Object> values = new ArrayList<>(); List<Object> values = new ArrayList<>();
String[] nextPathsSplit = SPLIT_R4.split(thePaths); String[] nextPathsSplit = SPLIT_R4.split(thePaths);
for (String nextPath : nextPathsSplit) { for (String nextPath : nextPathsSplit) {
List<Base> allValues; List<Base> allValues;
try { try {
allValues = fp.evaluate((Base) theResource, nextPath); allValues = myFhirPathEngine.evaluate((Base) theResource, nextPath);
} catch (FHIRException e) { } catch (FHIRException e) {
String msg = getContext().getLocalizer().getMessage(BaseSearchParamExtractor.class, "failedToExtractPaths", nextPath, e.toString()); String msg = getContext().getLocalizer().getMessage(BaseSearchParamExtractor.class, "failedToExtractPaths", nextPath, e.toString());
throw new InternalErrorException(msg, e); throw new InternalErrorException(msg, e);

View File

@ -39,6 +39,7 @@ import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.hapi.ctx.HapiWorkerContext;
import org.hl7.fhir.r5.hapi.ctx.IValidationSupport; import org.hl7.fhir.r5.hapi.ctx.IValidationSupport;
import org.hl7.fhir.r5.model.*; import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.model.Enumeration; import org.hl7.fhir.r5.model.Enumeration;
@ -48,6 +49,7 @@ import org.hl7.fhir.r5.model.Patient.PatientCommunicationComponent;
import org.hl7.fhir.r5.utils.FHIRPathEngine; import org.hl7.fhir.r5.utils.FHIRPathEngine;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.measure.unit.NonSI; import javax.measure.unit.NonSI;
import javax.measure.unit.Unit; import javax.measure.unit.Unit;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -78,6 +80,7 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
@Autowired @Autowired
private IValidationSupport myValidationSupport; private IValidationSupport myValidationSupport;
private FHIRPathEngine myFhirPathEngine;
/** /**
* Constructor * Constructor
@ -86,11 +89,11 @@ public class SearchParamExtractorR5 extends BaseSearchParamExtractor implements
super(); super();
} }
// This constructor is used by tests @PostConstruct
@VisibleForTesting public void initFhirPath() {
public SearchParamExtractorR5(ModelConfig theModelConfig, FhirContext theCtx, IValidationSupport theValidationSupport, ISearchParamRegistry theSearchParamRegistry) { IWorkerContext worker = new HapiWorkerContext(getContext(), myValidationSupport);
super(theCtx, theSearchParamRegistry); myFhirPathEngine = new FHIRPathEngine(worker);
myValidationSupport = theValidationSupport; myFhirPathEngine.setHostServices(new SearchParamExtractorR5HostServices());
} }
private void addQuantity(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, Quantity nextValue) { private void addQuantity(ResourceTable theEntity, HashSet<ResourceIndexedSearchParamQuantity> retVal, String resourceName, Quantity nextValue) {

View File

@ -78,6 +78,10 @@
checker. This regex was causing a noticable performance drop when feeding large numbers of transactions checker. This regex was causing a noticable performance drop when feeding large numbers of transactions
into the JPA server at the same time (i.e. when loading Synthea data). into the JPA server at the same time (i.e. when loading Synthea data).
</action> </action>
<action type="fix">
The FHIRPath engine used to parse search parameters in the JPA R4/R5 server is now reused across
requests, as it is somewhat expensive to create and is thread safe.
</action>
<action type="add"> <action type="add">
It is now possible to submit a PATCH request as a part of a FHIR transaction in DSTU3 (previously this It is now possible to submit a PATCH request as a part of a FHIR transaction in DSTU3 (previously this
was only supported in R4+). This is not officially part of the DSTU3 spec, but it can now be performed by was only supported in R4+). This is not officially part of the DSTU3 spec, but it can now be performed by