Improve TX scoping for validation (#1925)
* Improve TX scoping for validation * Test fix * Test fix * Some cleanup * Test fixes * Test fix
This commit is contained in:
parent
0d4e12fe58
commit
b6540064ea
|
@ -6,9 +6,9 @@
|
|||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.1.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-elasticsearch-6</artifactId>
|
||||
|
|
|
@ -150,6 +150,12 @@
|
|||
<artifactId>hapi-fhir-elasticsearch-6</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>shaded6</classifier>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
|
|
@ -1395,6 +1395,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequest) {
|
||||
if (theRequest != null) {
|
||||
ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, theResource, null, theId);
|
||||
|
|
|
@ -412,8 +412,4 @@ public class TermConcept implements Serializable {
|
|||
return getChildren().stream().map(t -> t.getChild()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
public VersionIndependentConcept toVersionIndependentConcept() {
|
||||
return new VersionIndependentConcept(myCodeSystem.getCodeSystem().getCodeSystemUri(), myCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ public class JpaPackageCache extends BasePackageCacheManager implements IHapiPac
|
|||
.build()
|
||||
.execute(new HttpGet(thePackageUrl))) {
|
||||
if (request.getStatusLine().getStatusCode() != 200) {
|
||||
throw new IOException("Received HTTP " + request.getStatusLine().getStatusCode());
|
||||
throw new ResourceNotFoundException("Received HTTP " + request.getStatusLine().getStatusCode() + " from URL: " + thePackageUrl);
|
||||
}
|
||||
return IOUtils.toByteArray(request.getEntity().getContent());
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -89,6 +89,7 @@ import com.github.benmanes.caffeine.cache.Cache;
|
|||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import net.bytebuddy.implementation.bytecode.Throw;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
|
@ -177,6 +178,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
private static final TermCodeSystemVersion NO_CURRENT_VERSION = new TermCodeSystemVersion().setId(-1L);
|
||||
private static boolean ourLastResultsFromTranslationCache; // For testing.
|
||||
private static boolean ourLastResultsFromTranslationWithReverseCache; // For testing.
|
||||
private static Runnable myInvokeOnNextCallForUnitTest;
|
||||
private final int myFetchSize = DEFAULT_FETCH_SIZE;
|
||||
private final Cache<String, TermCodeSystemVersion> myCodeSystemCurrentVersionCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build();
|
||||
@Autowired
|
||||
|
@ -1299,7 +1301,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
|
||||
@Nullable
|
||||
private TermCodeSystemVersion getCurrentCodeSystemVersion(String theUri) {
|
||||
TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(theUri, uri -> {
|
||||
TermCodeSystemVersion retVal = myCodeSystemCurrentVersionCache.get(theUri, uri -> myTxTemplate.execute(tx -> {
|
||||
TermCodeSystemVersion csv = null;
|
||||
TermCodeSystem cs = myCodeSystemDao.findByCodeSystemUri(uri);
|
||||
if (cs != null && cs.getCurrentVersion() != null) {
|
||||
|
@ -1310,7 +1312,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
} else {
|
||||
return NO_CURRENT_VERSION;
|
||||
}
|
||||
});
|
||||
}));
|
||||
if (retVal == NO_CURRENT_VERSION) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1935,8 +1937,15 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CodeValidationResult validateCodeInValueSet(ValidationSupportContext theValidationSupportContext, ConceptValidationOptions theOptions, String theCodeSystem, String theCode, String theDisplay, @Nonnull IBaseResource theValueSet) {
|
||||
|
||||
if (myInvokeOnNextCallForUnitTest != null) {
|
||||
Runnable invokeOnNextCallForUnitTest = myInvokeOnNextCallForUnitTest;
|
||||
myInvokeOnNextCallForUnitTest = null;
|
||||
invokeOnNextCallForUnitTest.run();
|
||||
}
|
||||
|
||||
IPrimitiveType<?> urlPrimitive = myContext.newTerser().getSingleValueOrNull(theValueSet, "url", IPrimitiveType.class);
|
||||
String url = urlPrimitive.getValueAsString();
|
||||
if (isNotBlank(url)) {
|
||||
|
@ -2106,6 +2115,11 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
|||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static void setInvokeOnNextCallForUnitTest(Runnable theInvokeOnNextCallForUnitTest) {
|
||||
myInvokeOnNextCallForUnitTest = theInvokeOnNextCallForUnitTest;
|
||||
}
|
||||
|
||||
static List<TermConcept> toPersistedConcepts(List<CodeSystem.ConceptDefinitionComponent> theConcept, TermCodeSystemVersion theCodeSystemVersion) {
|
||||
ArrayList<TermConcept> retVal = new ArrayList<>();
|
||||
|
||||
|
|
|
@ -447,16 +447,19 @@ public class TermCodeSystemStorageSvcImpl implements ITermCodeSystemStorageSvc {
|
|||
doDelete(descriptor, loader, counter, myConceptDao);
|
||||
}
|
||||
|
||||
Optional<TermCodeSystem> codeSystemOpt = myCodeSystemDao.findWithCodeSystemVersionAsCurrentVersion(theCodeSystemVersionPid);
|
||||
if (codeSystemOpt.isPresent()) {
|
||||
TermCodeSystem codeSystem = codeSystemOpt.get();
|
||||
ourLog.info(" * Removing code system version {} as current version of code system {}", theCodeSystemVersionPid, codeSystem.getPid());
|
||||
codeSystem.setCurrentVersion(null);
|
||||
myCodeSystemDao.save(codeSystem);
|
||||
}
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.executeWithoutResult(tx -> {
|
||||
Optional<TermCodeSystem> codeSystemOpt = myCodeSystemDao.findWithCodeSystemVersionAsCurrentVersion(theCodeSystemVersionPid);
|
||||
if (codeSystemOpt.isPresent()) {
|
||||
TermCodeSystem codeSystem = codeSystemOpt.get();
|
||||
ourLog.info(" * Removing code system version {} as current version of code system {}", theCodeSystemVersionPid, codeSystem.getPid());
|
||||
codeSystem.setCurrentVersion(null);
|
||||
myCodeSystemDao.save(codeSystem);
|
||||
}
|
||||
|
||||
ourLog.info(" * Deleting code system version");
|
||||
myCodeSystemVersionDao.deleteById(theCodeSystemVersionPid);
|
||||
ourLog.info(" * Deleting code system version");
|
||||
myCodeSystemVersionDao.deleteById(theCodeSystemVersionPid);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ public class TermReadSvcDstu3 extends BaseTermReadSvcImpl implements IValidation
|
|||
if (!haveValidated) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> c.toVersionIndependentConcept()));
|
||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
||||
}
|
||||
|
||||
if (codeOpt != null && codeOpt.isPresent()) {
|
||||
|
|
|
@ -112,7 +112,7 @@ public class TermReadSvcR4 extends BaseTermReadSvcImpl implements ITermReadSvcR4
|
|||
if (!haveValidated) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> c.toVersionIndependentConcept()));
|
||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
||||
}
|
||||
|
||||
if (codeOpt != null && codeOpt.isPresent()) {
|
||||
|
|
|
@ -99,7 +99,7 @@ public class TermReadSvcR5 extends BaseTermReadSvcImpl implements IValidationSup
|
|||
if (!haveValidated) {
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
|
||||
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
|
||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> c.toVersionIndependentConcept()));
|
||||
codeOpt = txTemplate.execute(t -> findCode(theCodeSystem, theCode).map(c -> new VersionIndependentConcept(theCodeSystem, c.getCode())));
|
||||
}
|
||||
|
||||
if (codeOpt != null && codeOpt.isPresent()) {
|
||||
|
|
|
@ -41,6 +41,11 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
|
|||
* starvation
|
||||
*/
|
||||
ourMaxThreads = (int) (Math.random() * 6.0) + 1;
|
||||
|
||||
if ("true".equals(System.getProperty("single_db_connection"))) {
|
||||
ourMaxThreads = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Exception myLastStackTrace;
|
||||
|
|
|
@ -94,6 +94,11 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
|
|||
* starvation
|
||||
*/
|
||||
int maxThreads = (int) (Math.random() * 6.0) + 1;
|
||||
|
||||
if ("true".equals(System.getProperty("single_db_connection"))) {
|
||||
maxThreads = 1;
|
||||
}
|
||||
|
||||
retVal.setMaxTotal(maxThreads);
|
||||
|
||||
return retVal;
|
||||
|
|
|
@ -43,6 +43,10 @@ public class TestR4Config extends BaseJavaConfigR4 {
|
|||
*/
|
||||
if (ourMaxThreads == null) {
|
||||
ourMaxThreads = (int) (Math.random() * 6.0) + 1;
|
||||
|
||||
if ("true".equals(System.getProperty("single_db_connection"))) {
|
||||
ourMaxThreads = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,11 @@ public class TestR5Config extends BaseJavaConfigR5 {
|
|||
*/
|
||||
if (ourMaxThreads == null) {
|
||||
ourMaxThreads = (int) (Math.random() * 6.0) + 1;
|
||||
|
||||
if ("true".equals(System.getProperty("single_db_connection"))) {
|
||||
ourMaxThreads = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.dstu3.model.Resource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
|
@ -133,7 +134,8 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
@Qualifier(BaseConfig.JPA_VALIDATION_SUPPORT)
|
||||
@Autowired
|
||||
private IValidationSupport myJpaPersistedValidationSupport;
|
||||
|
||||
@Autowired
|
||||
private FhirInstanceValidator myFhirInstanceValidator;
|
||||
|
||||
@After
|
||||
public void afterPerformCleanup() {
|
||||
|
@ -150,7 +152,9 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
if (myJpaPersistedValidationSupport != null) {
|
||||
ProxyUtil.getSingletonTarget(myJpaPersistedValidationSupport, JpaPersistedResourceValidationSupport.class).clearCaches();
|
||||
}
|
||||
|
||||
if (myFhirInstanceValidator != null) {
|
||||
myFhirInstanceValidator.invalidateCaches();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ public class FhirResourceDaoR4QueryCountTest extends BaseJpaR4Test {
|
|||
// Validate once
|
||||
myCaptureQueriesListener.clear();
|
||||
myObservationDao.validate(obs, null, null, null, null, null, null);
|
||||
assertEquals(myCaptureQueriesListener.logSelectQueriesForCurrentThread(), 10, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||
assertEquals(myCaptureQueriesListener.logSelectQueriesForCurrentThread(), 9, myCaptureQueriesListener.getSelectQueriesForCurrentThread().size());
|
||||
assertEquals(myCaptureQueriesListener.logUpdateQueriesForCurrentThread(), 0, myCaptureQueriesListener.getUpdateQueriesForCurrentThread().size());
|
||||
assertEquals(myCaptureQueriesListener.logInsertQueriesForCurrentThread(), 0, myCaptureQueriesListener.getInsertQueriesForCurrentThread().size());
|
||||
assertEquals(myCaptureQueriesListener.logDeleteQueriesForCurrentThread(), 0, myCaptureQueriesListener.getDeleteQueriesForCurrentThread().size());
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.context.support.IValidationSupport;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.entity.TermCodeSystemVersion;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.term.BaseTermReadSvcImpl;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
||||
|
@ -23,9 +27,27 @@ import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
|||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.AllergyIntolerance;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
|
||||
import org.hl7.fhir.r4.model.CanonicalType;
|
||||
import org.hl7.fhir.r4.model.CodeSystem;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
import org.hl7.fhir.r4.model.Condition;
|
||||
import org.hl7.fhir.r4.model.DateTimeType;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Narrative;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
import org.hl7.fhir.r4.model.Observation.ObservationStatus;
|
||||
import org.hl7.fhir.r4.model.OperationOutcome;
|
||||
import org.hl7.fhir.r4.model.Organization;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Questionnaire;
|
||||
import org.hl7.fhir.r4.model.QuestionnaireResponse;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.hl7.fhir.r4.model.StringType;
|
||||
import org.hl7.fhir.r4.model.StructureDefinition;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r5.utils.IResourceValidator;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -33,6 +55,7 @@ import org.junit.Ignore;
|
|||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.util.AopTestUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -45,6 +68,9 @@ import static org.junit.Assert.assertEquals;
|
|||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4ValidateTest.class);
|
||||
|
@ -56,6 +82,10 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
private ITermCodeSystemStorageSvc myTermCodeSystemStorageSvcc;
|
||||
@Autowired
|
||||
private DaoRegistry myDaoRegistry;
|
||||
@Autowired
|
||||
private JpaValidationSupportChain myJpaValidationSupportChain;
|
||||
@Autowired
|
||||
private PlatformTransactionManager myTransactionManager;
|
||||
|
||||
/**
|
||||
* Create a loinc valueset that expands to more results than the expander is willing to do
|
||||
|
@ -155,13 +185,11 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
myCaptureQueriesListener.logSelectQueriesForCurrentThread();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Per: https://chat.fhir.org/#narrow/stream/179166-implementers/topic/Handling.20incomplete.20CodeSystems
|
||||
*
|
||||
* <p>
|
||||
* We should generate a warning if a code can't be found but the codesystem is a fragment
|
||||
*/
|
||||
@Test
|
||||
|
@ -219,7 +247,6 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a loinc valueset that expands to more results than the expander is willing to do
|
||||
* in memory, and make sure we can still validate correctly, even if we're using
|
||||
|
@ -303,6 +330,115 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that we do something sane when validating throws an unexpected exception
|
||||
*/
|
||||
@Test
|
||||
public void testValidate_ValidationSupportThrowsException() {
|
||||
IValidationSupport validationSupport = mock(IValidationSupport.class);
|
||||
when(validationSupport.validateCodeInValueSet(any(), any(), any(), any(), any(), any())).thenAnswer(t -> {
|
||||
// This will fail with a constraint error
|
||||
try {
|
||||
myResourceTableDao.save(new ResourceTable());
|
||||
myResourceTableDao.flush();
|
||||
} catch (Exception e) {
|
||||
ourLog.info("Hit expected exception: {}", e.toString());
|
||||
}
|
||||
return null;
|
||||
});
|
||||
when(validationSupport.getFhirContext()).thenReturn(myFhirCtx);
|
||||
|
||||
myJpaValidationSupportChain.addValidationSupport(0, validationSupport);
|
||||
try {
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getText().setDivAsString("<div>Hello</div>");
|
||||
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||
obs.setSubject(new Reference("Patient/123"));
|
||||
obs.addPerformer(new Reference("Practitioner/123"));
|
||||
obs.setEffective(DateTimeType.now());
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setValue(new StringType("This is the value"));
|
||||
|
||||
OperationOutcome oo;
|
||||
|
||||
// Valid code
|
||||
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||
obs.getCode().getCodingFirstRep().setSystem("http://loinc.org").setCode("CODE3").setDisplay("Display 3");
|
||||
oo = validateAndReturnOutcome(obs);
|
||||
assertEquals(encode(oo), "No issues detected during validation", oo.getIssueFirstRep().getDiagnostics());
|
||||
|
||||
} finally {
|
||||
myJpaValidationSupportChain.removeValidationSupport(validationSupport);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that we do something sane when validating throws an unexpected exception
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
public void testValidate_TermSvcHasDatabaseRollback() {
|
||||
BaseTermReadSvcImpl.setInvokeOnNextCallForUnitTest(() -> {
|
||||
try {
|
||||
myResourceTableDao.save(new ResourceTable());
|
||||
myResourceTableDao.flush();
|
||||
} catch (Exception e) {
|
||||
ourLog.info("Hit expected exception: {}", e.toString());
|
||||
}
|
||||
});
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getText().setDivAsString("<div>Hello</div>");
|
||||
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||
obs.setSubject(new Reference("Patient/123"));
|
||||
obs.addPerformer(new Reference("Practitioner/123"));
|
||||
obs.setEffective(DateTimeType.now());
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setValue(new StringType("This is the value"));
|
||||
|
||||
OperationOutcome oo;
|
||||
|
||||
// Valid code
|
||||
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||
obs.getCode().getCodingFirstRep().setSystem("http://loinc.org").setCode("CODE3").setDisplay("Display 3");
|
||||
oo = validateAndReturnOutcome(obs);
|
||||
assertEquals(encode(oo), "No issues detected during validation", oo.getIssueFirstRep().getDiagnostics());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that we do something sane when validating throws an unexpected exception
|
||||
*/
|
||||
@Test
|
||||
public void testValidate_TermSvcHasNpe() {
|
||||
BaseTermReadSvcImpl.setInvokeOnNextCallForUnitTest(() -> {
|
||||
throw new NullPointerException("MY ERROR");
|
||||
});
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getText().setDivAsString("<div>Hello</div>");
|
||||
obs.getCategoryFirstRep().addCoding().setSystem("http://terminology.hl7.org/CodeSystem/observation-category").setCode("vital-signs");
|
||||
obs.setSubject(new Reference("Patient/123"));
|
||||
obs.addPerformer(new Reference("Practitioner/123"));
|
||||
obs.setEffective(DateTimeType.now());
|
||||
obs.setStatus(ObservationStatus.FINAL);
|
||||
obs.setValue(new StringType("This is the value"));
|
||||
|
||||
OperationOutcome oo;
|
||||
|
||||
// Valid code
|
||||
obs.getText().setStatus(Narrative.NarrativeStatus.GENERATED);
|
||||
obs.getCode().getCodingFirstRep().setSystem("http://loinc.org").setCode("CODE99999").setDisplay("Display 3");
|
||||
try {
|
||||
validateAndReturnOutcome(obs);
|
||||
fail();
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals("MY ERROR", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateCodeableConceptWithNoSystem() {
|
||||
AllergyIntolerance allergy = new AllergyIntolerance();
|
||||
|
@ -605,6 +741,8 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
|
|||
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
||||
myDaoConfig.setMaximumExpansionSize(DaoConfig.DEFAULT_MAX_EXPANSION_SIZE);
|
||||
myDaoConfig.setPreExpandValueSets(new DaoConfig().isPreExpandValueSets());
|
||||
|
||||
BaseTermReadSvcImpl.setInvokeOnNextCallForUnitTest(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -4,6 +4,7 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
|||
import ca.uhn.fhir.jpa.dao.data.INpmPackageVersionDao;
|
||||
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.test.utilities.ProxyUtil;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
|
@ -30,9 +31,9 @@ import static org.junit.Assert.assertThat;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class IgInstallerTestDstu3 extends BaseJpaDstu3Test {
|
||||
public class IgInstallerDstu3Test extends BaseJpaDstu3Test {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(IgInstallerTestDstu3.class);
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(IgInstallerDstu3Test.class);
|
||||
@Autowired
|
||||
private DaoConfig daoConfig;
|
||||
@Autowired
|
||||
|
@ -185,7 +186,7 @@ public class IgInstallerTestDstu3 extends BaseJpaDstu3Test {
|
|||
);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("", e.getMessage());
|
||||
assertEquals("Package ID nictiz.fhir.nl.stu3.questionnaires doesn't match expected: blah", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -199,8 +200,8 @@ public class IgInstallerTestDstu3 extends BaseJpaDstu3Test {
|
|||
.setPackageUrl("http://localhost:" + myPort + "/foo.tgz")
|
||||
);
|
||||
fail();
|
||||
} catch (InvalidRequestException e) {
|
||||
assertEquals("", e.getMessage());
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertEquals("Received HTTP 404 from URL: http://localhost:" + myPort + "/foo.tgz", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,7 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
|
||||
@Test
|
||||
public void testSavePackage() throws IOException {
|
||||
try (InputStream stream = IgInstallerTestDstu3.class.getResourceAsStream("/packages/basisprofil.de.tar.gz")) {
|
||||
try (InputStream stream = IgInstallerDstu3Test.class.getResourceAsStream("/packages/basisprofil.de.tar.gz")) {
|
||||
myPackageCacheManager.addPackageToCache("basisprofil.de", "0.2.40", stream, "basisprofil.de");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class JpaClasspathTest {
|
||||
|
||||
/**
|
||||
* Make sure no dependencies start bringing in log4j - This makes hibernate decide to start using log4j instead of
|
||||
* slf4j which is super annoying..
|
||||
*/
|
||||
@Test
|
||||
public void testNoLog4jOnClasspath() {
|
||||
|
||||
try {
|
||||
Class.forName("org.apache.logging.log4j.status.StatusLogger");
|
||||
fail("org.apache.logging.log4j.status.StatusLogger" + " found on classpath - Make sure log4j isn't being introduced");
|
||||
} catch (ClassNotFoundException theE) {
|
||||
// good
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -122,6 +122,14 @@ public class ValidationSupportChain implements IValidationSupport {
|
|||
myChain.add(theIndex, theValidationSupport);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the chain. Note that this method is mostly intended for testing. Removing items from the chain while validation is
|
||||
* actually occurring is not an expected use case for this class.
|
||||
*/
|
||||
public void removeValidationSupport(IValidationSupport theValidationSupport) {
|
||||
myChain.remove(theValidationSupport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueSetExpansionOutcome expandValueSet(ValidationSupportContext theValidationSupportContext, ValueSetExpansionOptions theExpansionOptions, IBaseResource theValueSetToExpand) {
|
||||
for (IValidationSupport next : myChain) {
|
||||
|
|
|
@ -309,7 +309,9 @@ public class FhirInstanceValidator extends BaseValidatorBridge implements IInsta
|
|||
*/
|
||||
public void invalidateCaches() {
|
||||
myValidationSupport.invalidateCaches();
|
||||
myWrappedWorkerContext.invalidateCaches();
|
||||
if (myWrappedWorkerContext != null) {
|
||||
myWrappedWorkerContext.invalidateCaches();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue