diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4934-validation-doesnt-consider-loaded-ig-immedieately.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4934-validation-doesnt-consider-loaded-ig-immedieately.yaml new file mode 100644 index 00000000000..681c9c18a17 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/4934-validation-doesnt-consider-loaded-ig-immedieately.yaml @@ -0,0 +1,4 @@ +--- +type: fix +issue: 4934 +title: "Previously, installing or uninstalling an implementation guide does not refresh the validation cache. This problem has been fixed." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java index 1b4033b5f95..1aba8fa12dd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImpl.java @@ -129,7 +129,9 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc { @Override public PackageDeleteOutcomeJson uninstall(PackageInstallationSpec theInstallationSpec) { - return myPackageCacheManager.uninstallPackage(theInstallationSpec.getName(), theInstallationSpec.getVersion()); + PackageDeleteOutcomeJson outcome = myPackageCacheManager.uninstallPackage(theInstallationSpec.getName(), theInstallationSpec.getVersion()); + validationSupport.invalidateCaches(); + return outcome; } /** @@ -178,6 +180,8 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc { mySearchParamRegistryController.refreshCacheIfNecessary(); } + validationSupport.invalidateCaches(); + } catch (IOException e) { throw new ImplementationGuideInstallationException(Msg.code(1285) + "Could not load NPM package " + theInstallationSpec.getName() + "#" + theInstallationSpec.getVersion(), e); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImplTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImplTest.java index 52e4b33b7f9..2e2528697ce 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImplTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/packages/PackageInstallerSvcImplTest.java @@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.packages; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirVersionEnum; +import ca.uhn.fhir.context.support.IValidationSupport; import ca.uhn.fhir.jpa.api.dao.DaoRegistry; import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome; @@ -63,6 +64,8 @@ public class PackageInstallerSvcImplTest { private DaoRegistry myDaoRegistry; @Mock private IFhirResourceDao myCodeSystemDao; + @Mock + private IValidationSupport myIValidationSupport; @Spy private FhirContext myCtx = FhirContext.forR4Cached(); @Spy diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java index 70c3cd3110f..799e6133124 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/packages/NpmR4Test.java @@ -28,6 +28,7 @@ import ca.uhn.fhir.test.utilities.JettyUtil; import ca.uhn.fhir.test.utilities.ProxyUtil; import ca.uhn.fhir.util.ClasspathUtil; import ca.uhn.fhir.util.JsonUtil; +import ca.uhn.fhir.validation.ValidationResult; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHolder; @@ -35,7 +36,9 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Enumerations; import org.hl7.fhir.r4.model.ImplementationGuide; +import org.hl7.fhir.r4.model.Meta; import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.PractitionerRole; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.SearchParameter; @@ -165,6 +168,47 @@ public class NpmR4Test extends BaseJpaR4Test { myPackageInstallerSvc.install(spec); } + @Test + public void testValidationCache_whenInstallingIG_isRefreshed() { + Patient patient = new Patient(); + patient.setMeta(new Meta().addProfile("https://fhir.nhs.uk/R4/StructureDefinition/UKCore-Patient")); + + ValidationResult validationResultBefore = validateWithResult(patient); + assertFalse(validationResultBefore.isSuccessful()); + + byte[] bytes = ClasspathUtil.loadResourceAsByteArray("/packages/UK.Core.r4-1.1.0.tgz"); + myFakeNpmServlet.responses.put("/UK.Core.r4/1.1.0", bytes); + + PackageInstallationSpec spec = new PackageInstallationSpec().setName("UK.Core.r4").setVersion("1.1.0") + .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + + myPackageInstallerSvc.install(spec); + + ValidationResult validationResultAfter = validateWithResult(patient); + assertTrue(validationResultAfter.isSuccessful()); + } + + @Test + public void testValidationCache_whenUnInstallingIG_isRefreshed() { + byte[] bytes = ClasspathUtil.loadResourceAsByteArray("/packages/UK.Core.r4-1.1.0.tgz"); + myFakeNpmServlet.responses.put("/UK.Core.r4/1.1.0", bytes); + + PackageInstallationSpec spec = new PackageInstallationSpec().setName("UK.Core.r4").setVersion("1.1.0") + .setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL); + + myPackageInstallerSvc.install(spec); + + Patient patient = new Patient(); + patient.setMeta(new Meta().addProfile("https://fhir.nhs.uk/R4/StructureDefinition/UKCore-Patient")); + + ValidationResult validationResultBefore = validateWithResult(patient); + assertTrue(validationResultBefore.isSuccessful()); + + myPackageInstallerSvc.uninstall(spec); + + ValidationResult validationResultAfter = validateWithResult(patient); + assertFalse(validationResultAfter.isSuccessful()); + } @Test public void testCacheDstu3Package() throws Exception { diff --git a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java index f6ec41098cc..09b9d81d833 100644 --- a/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java +++ b/hapi-fhir-jpaserver-test-utilities/src/main/java/ca/uhn/fhir/jpa/test/BaseJpaR4Test.java @@ -625,13 +625,16 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil return myTxManager; } - protected void validate(IBaseResource theResource) { + protected ValidationResult validateWithResult(IBaseResource theResource) { FhirValidator validatorModule = myFhirContext.newValidator(); FhirInstanceValidator instanceValidator = new FhirInstanceValidator(myValidationSupport); instanceValidator.setBestPracticeWarningLevel(BestPracticeWarningLevel.Ignore); instanceValidator.setValidatorPolicyAdvisor(new ValidationPolicyAdvisor()); validatorModule.registerValidatorModule(instanceValidator); - ValidationResult result = validatorModule.validateWithResult(theResource); + return validatorModule.validateWithResult(theResource); + } + protected void validate(IBaseResource theResource) { + ValidationResult result = validateWithResult(theResource); if (!result.isSuccessful()) { fail(myFhirContext.newXmlParser().setPrettyPrint(true).encodeResourceToString(result.toOperationOutcome())); }