Reject nvalid SearchParameter wiith no path expression (#2043)

* Fix some changelog typos

* Reject SearchParameter with invalid path

* Add changelog

* Test fix

* Test fixes

* Test fixes

* Test fix

* One more test fix
This commit is contained in:
James Agnew 2020-08-17 11:21:55 -04:00 committed by GitHub
parent eab828f47a
commit 1fadaeeff5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 236 additions and 58 deletions

View File

@ -0,0 +1,6 @@
---
type: fix
issue: 2043
title: "The JPA SearchParameetr validator did not reject custom Search Parameetrs with an invalid path
expression consisting of only a resource type and no element name. Creating such a search parameter could cause
strange indexing issues, so this has been added to the validator."

View File

@ -30,16 +30,22 @@ import ca.uhn.fhir.model.dstu2.resource.SearchParameter;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
import ca.uhn.fhir.model.dstu2.valueset.SearchParamTypeEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import org.hl7.fhir.convertors.conv10_40.SearchParameter10_40;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
public class FhirResourceDaoSearchParameterDstu2 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
private FhirContext myDstu2Hl7OrgContext = FhirContext.forDstu2Hl7Org();
protected void markAffectedResources(SearchParameter theResource) {
Boolean reindex = theResource != null ? CURRENTLY_REINDEXING.get(theResource) : null;
@ -70,17 +76,16 @@ public class FhirResourceDaoSearchParameterDstu2 extends BaseHapiFhirResourceDao
protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
Enum<?> status = theResource.getStatusElement().getValueAsEnum();
List<BoundCodeDt<ResourceTypeEnum>> base = Collections.emptyList();
if (theResource.getBase() != null) {
base = Arrays.asList(theResource.getBaseElement());
}
String expression = theResource.getXpath();
FhirContext context = getContext();
SearchParamTypeEnum type = theResource.getTypeElement().getValueAsEnum();
String code = theResource.getCode();
String encoded = getContext().newJsonParser().encodeResourceToString(theResource);
org.hl7.fhir.dstu2.model.SearchParameter hl7Org = myDstu2Hl7OrgContext.newJsonParser().parseResource(org.hl7.fhir.dstu2.model.SearchParameter.class, encoded);
org.hl7.fhir.r4.model.SearchParameter convertedSp = SearchParameter10_40.convertSearchParameter(hl7Org);
if (isBlank(convertedSp.getExpression()) && isNotBlank(hl7Org.getXpath())) {
convertedSp.setExpression(hl7Org.getXpath());
}
FhirResourceDaoSearchParameterR4.validateSearchParam(convertedSp, getContext(), getConfig(), mySearchParamRegistry, mySearchParamExtractor);
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
}

View File

@ -6,6 +6,8 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import org.hl7.fhir.convertors.conv10_40.SearchParameter10_40;
import org.hl7.fhir.convertors.conv30_40.SearchParameter30_40;
import org.hl7.fhir.dstu3.model.CodeType;
import org.hl7.fhir.dstu3.model.Enumerations;
import org.hl7.fhir.dstu3.model.SearchParameter;
@ -67,14 +69,7 @@ public class FhirResourceDaoSearchParameterDstu3 extends BaseHapiFhirResourceDao
protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
Enum<?> status = theResource.getStatus();
List<CodeType> base = theResource.getBase();
String expression = theResource.getExpression();
FhirContext context = getContext();
Enumerations.SearchParamType type = theResource.getType();
String code = theResource.getCode();
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
FhirResourceDaoSearchParameterR4.validateSearchParam(SearchParameter30_40.convertSearchParameter(theResource), getContext(), getConfig(), mySearchParamRegistry, mySearchParamExtractor);
}
}

View File

@ -10,8 +10,10 @@ import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.ElementUtil;
import ca.uhn.fhir.util.HapiExtensions;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
@ -21,6 +23,7 @@ import org.hl7.fhir.r4.model.SearchParameter;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.regex.Pattern;
import static org.apache.commons.lang3.StringUtils.isBlank;
@ -46,6 +49,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<SearchParameter> implements IFhirResourceDaoSearchParameter<SearchParameter> {
private static final Pattern REGEX_SP_EXPRESSION_HAS_PATH = Pattern.compile("[( ]*([A-Z][a-zA-Z]+\\.)?[a-z].*");
@Autowired
private ISearchParamExtractor mySearchParamExtractor;
@ -78,27 +82,21 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<Se
protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
Enum<?> status = theResource.getStatus();
List<CodeType> base = theResource.getBase();
String code = theResource.getCode();
String expression = theResource.getExpression();
FhirContext context = getContext();
Enum<?> type = theResource.getType();
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
validateSearchParam(theResource, getContext(), getConfig(), mySearchParamRegistry, mySearchParamExtractor);
}
public static void validateSearchParam(ISearchParamRegistry theSearchParamRegistry, ISearchParamExtractor theSearchParamExtractor, String theCode, Enum<?> theType, Enum<?> theStatus, List<? extends IPrimitiveType> theBase, String theExpression, FhirContext theContext, DaoConfig theDaoConfig) {
public static void validateSearchParam(SearchParameter theResource, FhirContext theContext, DaoConfig theDaoConfig, ISearchParamRegistry theSearchParamRegistry, ISearchParamExtractor theSearchParamExtractor) {
/*
* If overriding built-in SPs is disabled on this server, make sure we aren't
* doing that
*/
if (theDaoConfig.getModelConfig().isDefaultSearchParamsCanBeOverridden() == false) {
for (IPrimitiveType<?> nextBaseType : theBase) {
for (IPrimitiveType<?> nextBaseType : theResource.getBase()) {
String nextBase = nextBaseType.getValueAsString();
RuntimeSearchParam existingSearchParam = theSearchParamRegistry.getActiveSearchParam(nextBase, theCode);
RuntimeSearchParam existingSearchParam = theSearchParamRegistry.getActiveSearchParam(nextBase, theResource.getCode());
if (existingSearchParam != null && existingSearchParam.getId() == null) {
throw new UnprocessableEntityException("Can not override built-in search parameter " + nextBase + ":" + theCode + " because overriding is disabled on this server");
throw new UnprocessableEntityException("Can not override built-in search parameter " + nextBase + ":" + theResource.getCode() + " because overriding is disabled on this server");
}
}
}
@ -107,37 +105,52 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<Se
* Everything below is validating that the SP is actually valid. We'll only do that if the
* SPO is active, so that we don't block people from uploading works-in-progress
*/
if (theStatus == null) {
if (theResource.getStatus() == null) {
throw new UnprocessableEntityException("SearchParameter.status is missing or invalid");
}
if (!theStatus.name().equals("ACTIVE")) {
if (!theResource.getStatus().name().equals("ACTIVE")) {
return;
}
if (ElementUtil.isEmpty(theBase) && (theType == null || !Enumerations.SearchParamType.COMPOSITE.name().equals(theType.name()))) {
if (ElementUtil.isEmpty(theResource.getBase()) && (theResource.getType() == null || !Enumerations.SearchParamType.COMPOSITE.name().equals(theResource.getType().name()))) {
throw new UnprocessableEntityException("SearchParameter.base is missing");
}
if (theType != null && theType.name().equals(Enumerations.SearchParamType.COMPOSITE.name()) && isBlank(theExpression)) {
boolean isUnique = theResource.getExtensionsByUrl(HapiExtensions.EXT_SP_UNIQUE).stream().anyMatch(t-> "true".equals(t.getValueAsPrimitive().getValueAsString()));
if (theResource.getType() != null && theResource.getType().name().equals(Enumerations.SearchParamType.COMPOSITE.name()) && isBlank(theResource.getExpression())) {
// this is ok
} else if (isBlank(theExpression)) {
} else if (isBlank(theResource.getExpression())) {
throw new UnprocessableEntityException("SearchParameter.expression is missing");
} else {
theExpression = theExpression.trim();
String expression = theResource.getExpression().trim();
if (isUnique) {
if (theResource.getComponent().size() == 0) {
throw new UnprocessableEntityException("SearchParameter is marked as unique but has no components");
}
for (SearchParameter.SearchParameterComponentComponent next : theResource.getComponent()) {
if (isBlank(next.getDefinition())) {
throw new UnprocessableEntityException("SearchParameter is marked as unique but is missing component.definition");
}
}
}
if (!theContext.getVersion().getVersion().isEqualOrNewerThan(FhirVersionEnum.R4)) {
String[] expressionSplit = theSearchParamExtractor.split(theExpression);
// DSTU3 and below
String[] expressionSplit = theSearchParamExtractor.split(expression);
for (String nextPath : expressionSplit) {
nextPath = nextPath.trim();
int dotIdx = nextPath.indexOf('.');
if (dotIdx == -1) {
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". Must start with a resource name");
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + nextPath + "\". Must start with a resource name.");
}
String resourceName = nextPath.substring(0, dotIdx);
@ -162,10 +175,15 @@ public class FhirResourceDaoSearchParameterR4 extends BaseHapiFhirResourceDao<Se
} else {
if (!isUnique && theResource.getType() != Enumerations.SearchParamType.COMPOSITE && theResource.getType() != Enumerations.SearchParamType.SPECIAL && !REGEX_SP_EXPRESSION_HAS_PATH.matcher(expression).matches()) {
throw new UnprocessableEntityException("SearchParameter.expression value \"" + expression + "\" is invalid");
}
// R4 and above
try {
theContext.newFluentPath().parse(theExpression);
theContext.newFluentPath().parse(expression);
} catch (Exception e) {
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + theExpression + "\": " + e.getMessage());
throw new UnprocessableEntityException("Invalid SearchParameter.expression value \"" + expression + "\": " + e.getMessage());
}
}

View File

@ -6,6 +6,8 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirResourceDao;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoSearchParameterR4;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
import org.hl7.fhir.convertors.conv30_40.SearchParameter30_40;
import org.hl7.fhir.convertors.conv40_50.SearchParameter40_50;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.SearchParameter;
import org.springframework.beans.factory.annotation.Autowired;
@ -66,14 +68,7 @@ public class FhirResourceDaoSearchParameterR5 extends BaseHapiFhirResourceDao<Se
protected void validateResourceForStorage(SearchParameter theResource, ResourceTable theEntityToSave) {
super.validateResourceForStorage(theResource, theEntityToSave);
Enum<?> status = theResource.getStatus();
List<CodeType> base = theResource.getBase();
String code = theResource.getCode();
String expression = theResource.getExpression();
FhirContext context = getContext();
Enum<?> type = theResource.getType();
FhirResourceDaoSearchParameterR4.validateSearchParam(mySearchParamRegistry, mySearchParamExtractor, code, type, status, base, expression, context, getConfig());
FhirResourceDaoSearchParameterR4.validateSearchParam(SearchParameter40_50.convertSearchParameter(theResource), getContext(), getConfig(), mySearchParamRegistry, mySearchParamExtractor);
}

View File

@ -161,7 +161,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
mySearchParameterDao.create(fooSp, mySrd);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name", e.getMessage());
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name.", e.getMessage());
}
}

View File

@ -114,7 +114,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
mySearchParameterDao.create(fooSp, mySrd);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name", e.getMessage());
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name.", e.getMessage());
}
}

View File

@ -288,7 +288,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
mySearchParameterDao.create(fooSp, mySrd);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name", e.getMessage());
assertEquals("Invalid SearchParameter.expression value \"gender\". Must start with a resource name.", e.getMessage());
}
}

View File

@ -1316,7 +1316,9 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
SearchParameterMap params = new SearchParameterMap();
params.setLoadSynchronous(true);
myCaptureQueriesListener.clear();
List<IBaseResource> patients = toList(myPatientDao.search(params));
myCaptureQueriesListener.logAllQueriesForCurrentThread();
assertTrue(patients.size() >= 2);
}

View File

@ -21,6 +21,7 @@ import ca.uhn.fhir.rest.param.TokenAndListParam;
import ca.uhn.fhir.rest.param.TokenParam;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.HapiExtensions;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
@ -230,7 +231,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
sp = new SearchParameter();
sp.setId("SearchParameter/patient-uniq-identifier");
sp.setCode("patient-uniq-identifier");
sp.setExpression("Patient.identifier");
sp.setExpression("Patient");
sp.setType(Enumerations.SearchParamType.COMPOSITE);
sp.setStatus(PublicationStatus.ACTIVE);
sp.addBase("Patient");
@ -362,6 +363,50 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
mySearchParamRegistry.forceRefresh();
}
@Test
public void testCreateUniqueSpWithNoComponent() {
SearchParameter sp = new SearchParameter();
sp.setId("SearchParameter/patient-uniq-identifier");
sp.setCode("patient-uniq-identifier");
sp.setExpression("Patient");
sp.setType(Enumerations.SearchParamType.COMPOSITE);
sp.setStatus(PublicationStatus.ACTIVE);
sp.addBase("Patient");
sp.addExtension()
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
try {
mySearchParameterDao.create(sp);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("SearchParameter is marked as unique but has no components", e.getMessage());
}
}
@Test
public void testCreateUniqueSpWithNoComponentDefinition() {
SearchParameter sp = new SearchParameter();
sp.setId("SearchParameter/patient-uniq-identifier");
sp.setCode("patient-uniq-identifier");
sp.setExpression("Patient");
sp.setType(Enumerations.SearchParamType.COMPOSITE);
sp.setStatus(PublicationStatus.ACTIVE);
sp.addBase("Patient");
sp.addComponent() .setExpression("Patient");
sp.addExtension()
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
try {
mySearchParameterDao.create(sp);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("SearchParameter is marked as unique but is missing component.definition", e.getMessage());
}
}
@Test
public void testDoubleMatchingOnAnd_Search() {
createUniqueIndexPatientIdentifier();

View File

@ -75,7 +75,7 @@ public class FhirResourceDaoSearchParameterR4Test {
@Test
public void testValidateInvalidExpression() {
SearchParameter nextSearchParameter = new SearchParameter();
nextSearchParameter.setExpression("Patient////");
nextSearchParameter.setExpression("Patient.ex////");
nextSearchParameter.setStatus(Enumerations.PublicationStatus.ACTIVE);
nextSearchParameter.setType(Enumerations.SearchParamType.STRING);
nextSearchParameter.addBase("Patient");
@ -84,7 +84,7 @@ public class FhirResourceDaoSearchParameterR4Test {
myDao.validateResourceForStorage(nextSearchParameter, null);
fail();
} catch (UnprocessableEntityException e) {
assertEquals("Invalid SearchParameter.expression value \"Patient////\": Error in ?? at 1, 1: Premature ExpressionNode termination at unexpected token \"////\"", e.getMessage());
assertEquals("Invalid SearchParameter.expression value \"Patient.ex////\": Error in ?? at 1, 1: Premature ExpressionNode termination at unexpected token \"////\"", e.getMessage());
}
}

View File

@ -29,6 +29,7 @@ import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestComponen
import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.r4.model.CodeType;
import org.hl7.fhir.r4.model.Enumerations;
import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
import org.hl7.fhir.r4.model.Observation;
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
@ -118,6 +119,23 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
}
}
@Test
public void saveCreateSearchParamInvalidWithPathMissingElementName() {
SearchParameter sp = new SearchParameter();
sp.setCode("foo");
sp.setExpression("Patient");
sp.addBase("Patient");
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
sp.setTitle("Foo Param");
try {
myClient.create().resource(sp).execute();
fail();
} catch (UnprocessableEntityException e) {
assertEquals("HTTP 422 Unprocessable Entity: SearchParameter.expression value \"Patient\" is invalid", e.getMessage());
}
}
@Test
public void testConformanceOverrideAllowed() {
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);

View File

@ -1,5 +1,6 @@
package ca.uhn.fhirtest.config;
import ca.uhn.fhir.interceptor.api.IInterceptorService;
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
import ca.uhn.fhir.jpa.subscription.match.config.WebsocketDispatcherConfig;
import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
@ -76,6 +77,13 @@ public class CommonConfig {
return new PartitionSettings();
}
@Bean
public SqlCaptureInterceptor sqlCaptureInterceptor(IInterceptorService theInterceptorService) {
SqlCaptureInterceptor retVal = new SqlCaptureInterceptor();
theInterceptorService.registerInterceptor(retVal);
return retVal;
}
public static boolean isLocalTestMode() {
return "true".equalsIgnoreCase(System.getProperty("testmode.local"));
}

View File

@ -0,0 +1,37 @@
package ca.uhn.fhirtest.config;
import ca.uhn.fhir.interceptor.api.Hook;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.util.SqlQuery;
import ca.uhn.fhir.jpa.util.SqlQueryList;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.UrlUtil;
/**
* At some point we should move this to somewhere accessible to other projects,
* and document it.
*/
public class SqlCaptureInterceptor {
@Hook(Pointcut.JPA_PERFTRACE_RAW_SQL)
public void captureSql(ServletRequestDetails theRequestDetails, SqlQueryList theQueries) {
if (theRequestDetails != null) {
String[] captureSqls = theRequestDetails.getParameters().get("_captureSql");
if (captureSqls == null || !captureSqls[0].equals("true")) {
return;
}
for (int i = 0; i < theQueries.size(); i++) {
SqlQuery nextQuery = theQueries.get(i);
String sql = nextQuery.getSql(true, false);
sql = UrlUtil.sanitizeUrlPart(sql);
theRequestDetails.getResponse().addHeader("X-Executed-SQL", sql);
theRequestDetails.getResponse().addHeader("X-Executed-SQL-Outcome", "Returned " + nextQuery.getSize() + " in " + StopWatch.formatMillis(nextQuery.getElapsedTime()));
}
}
}
}

View File

@ -4,11 +4,13 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory;
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
import ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.PostgreSQL94Dialect;
@ -27,6 +29,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@Configuration
@Import(CommonConfig.class)
@ -91,7 +94,16 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
retVal.setPassword(myDbPassword);
retVal.setDefaultQueryTimeout(20);
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
return retVal;
DataSource dataSource = ProxyDataSourceBuilder
.create(retVal)
// .logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
.logSlowQueryBySlf4j(10000, TimeUnit.MILLISECONDS)
.afterQuery(new CurrentThreadCaptureQueriesListener())
.countQuery()
.build();
return dataSource;
}
@Primary

View File

@ -5,10 +5,12 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu3;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory;
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
import ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.PostgreSQL94Dialect;
@ -28,6 +30,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@Configuration
@Import(CommonConfig.class)
@ -105,7 +108,16 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
retVal.setPassword(myDbPassword);
retVal.setDefaultQueryTimeout(20);
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
return retVal;
DataSource dataSource = ProxyDataSourceBuilder
.create(retVal)
// .logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
.logSlowQueryBySlf4j(10000, TimeUnit.MILLISECONDS)
.afterQuery(new CurrentThreadCaptureQueriesListener())
.countQuery()
.build();
return dataSource;
}
@Override

View File

@ -5,10 +5,13 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigR4;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory;
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
import ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect;
import ca.uhn.fhir.rest.client.interceptor.ThreadLocalCapturingInterceptor;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.PostgreSQL94Dialect;
@ -28,6 +31,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@Configuration
@Import(CommonConfig.class)
@ -90,7 +94,16 @@ public class TestR4Config extends BaseJavaConfigR4 {
retVal.setPassword(myDbPassword);
retVal.setDefaultQueryTimeout(20);
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
return retVal;
DataSource dataSource = ProxyDataSourceBuilder
.create(retVal)
// .logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
.logSlowQueryBySlf4j(10000, TimeUnit.MILLISECONDS)
.afterQuery(new CurrentThreadCaptureQueriesListener())
.countQuery()
.build();
return dataSource;
}
@Override

View File

@ -5,10 +5,12 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigR5;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.LuceneSearchMappingFactory;
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener;
import ca.uhn.fhir.jpa.util.DerbyTenSevenHapiFhirDialect;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.validation.ResultSeverityEnum;
import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.dialect.PostgreSQL94Dialect;
@ -28,6 +30,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
@Configuration
@Import(CommonConfig.class)
@ -90,7 +93,16 @@ public class TestR5Config extends BaseJavaConfigR5 {
retVal.setPassword(myDbPassword);
retVal.setDefaultQueryTimeout(20);
retVal.setMaxConnLifetimeMillis(5 * DateUtils.MILLIS_PER_MINUTE);
return retVal;
DataSource dataSource = ProxyDataSourceBuilder
.create(retVal)
// .logQueryBySlf4j(SLF4JLogLevel.INFO, "SQL")
.logSlowQueryBySlf4j(10000, TimeUnit.MILLISECONDS)
.afterQuery(new CurrentThreadCaptureQueriesListener())
.countQuery()
.build();
return dataSource;
}
@Override