diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java index 1f7fc768972..a42f359a19c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java @@ -225,6 +225,11 @@ public abstract class BaseHapiFhirDao implements IDao { } protected ExpungeOutcome doExpunge(String theResourceName, Long theResourceId, Long theVersion, ExpungeOptions theExpungeOptions) { + + if (!getConfig().isExpungeEnabled()) { + throw new MethodNotAllowedException("$expunge is not enabled on this server"); + } + AtomicInteger remainingCount = new AtomicInteger(theExpungeOptions.getLimit()); if (theResourceName == null && theResourceId == null && theVersion == null) { @@ -295,75 +300,68 @@ public abstract class BaseHapiFhirDao implements IDao { return toExpungeOutcome(theExpungeOptions, remainingCount); } + private void doExpungeEverythingQuery(String theQuery) { + StopWatch sw = new StopWatch(); + int outcome = myEntityManager.createQuery(theQuery).executeUpdate(); + ourLog.info("Query affected {} rows in {}: {}", outcome, sw.toString(), theQuery); + } + private void doExpungeEverything() { - ourLog.info("** BEGINNING GLOBAL OPERATION_NAME_EXPUNGE **"); + ourLog.info("** BEGINNING GLOBAL $expunge **"); TransactionTemplate txTemplate = new TransactionTemplate(myPlatformTransactionManager); txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED); - txTemplate.execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus theStatus) { - myEntityManager.createQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate(); - myEntityManager.createQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null").executeUpdate(); - myEntityManager.createQuery("UPDATE " + TermCodeSystem.class.getSimpleName() + " d SET d.myCurrentVersion = null").executeUpdate(); - return null; - } + txTemplate.execute(t -> { + doExpungeEverythingQuery("UPDATE " + ResourceHistoryTable.class.getSimpleName() + " d SET d.myForcedId = null"); + doExpungeEverythingQuery("UPDATE " + ResourceTable.class.getSimpleName() + " d SET d.myForcedId = null"); + doExpungeEverythingQuery("UPDATE " + TermCodeSystem.class.getSimpleName() + " d SET d.myCurrentVersion = null"); + return null; }); - txTemplate.execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus theStatus) { - myEntityManager.createQuery("DELETE from " + SearchParamPresent.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + SearchParam.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ForcedId.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamUri.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedSearchParamCoords.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceIndexedCompositeStringUnique.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + SearchResult.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + SearchInclude.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + TermConceptParentChildLink.class.getSimpleName() + " d").executeUpdate(); - return null; - } + txTemplate.execute(t -> { + doExpungeEverythingQuery("DELETE from " + SearchParamPresent.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + SearchParam.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ForcedId.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamDate.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamNumber.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamQuantity.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamString.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamToken.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamUri.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedSearchParamCoords.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceIndexedCompositeStringUnique.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceLink.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + SearchResult.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + SearchInclude.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + TermConceptParentChildLink.class.getSimpleName() + " d"); + return null; }); - txTemplate.execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus theStatus) { - myEntityManager.createQuery("DELETE from " + TermConceptProperty.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + TermConceptDesignation.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + TermConcept.class.getSimpleName() + " d").executeUpdate(); - for (TermCodeSystem next : myEntityManager.createQuery("SELECT c FROM " + TermCodeSystem.class.getName() + " c", TermCodeSystem.class).getResultList()) { - next.setCurrentVersion(null); - myEntityManager.merge(next); - } - return null; + txTemplate.execute(t -> { + doExpungeEverythingQuery("DELETE from " + TermConceptProperty.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + TermConceptDesignation.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + TermConcept.class.getSimpleName() + " d"); + for (TermCodeSystem next : myEntityManager.createQuery("SELECT c FROM " + TermCodeSystem.class.getName() + " c", TermCodeSystem.class).getResultList()) { + next.setCurrentVersion(null); + myEntityManager.merge(next); } + return null; }); - txTemplate.execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus theStatus) { - myEntityManager.createQuery("DELETE from " + TermCodeSystemVersion.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + TermCodeSystem.class.getSimpleName() + " d").executeUpdate(); - return null; - } + txTemplate.execute(t -> { + doExpungeEverythingQuery("DELETE from " + TermCodeSystemVersion.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + TermCodeSystem.class.getSimpleName() + " d"); + return null; }); - txTemplate.execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus theStatus) { - myEntityManager.createQuery("DELETE from " + SubscriptionTable.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d").executeUpdate(); - myEntityManager.createQuery("DELETE from " + org.hibernate.search.jpa.Search.class.getSimpleName() + " d").executeUpdate(); - return null; - } + txTemplate.execute(t -> { + doExpungeEverythingQuery("DELETE from " + SubscriptionTable.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceHistoryTag.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceTag.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + TagDefinition.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceHistoryTable.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + ResourceTable.class.getSimpleName() + " d"); + doExpungeEverythingQuery("DELETE from " + org.hibernate.search.jpa.Search.class.getSimpleName() + " d"); + return null; }); + + ourLog.info("** COMPLETED GLOBAL $expunge **"); } private void expungeCurrentVersionOfResource(Long theResourceId) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java index b804e2fa6cb..efa2021cb6f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java @@ -1,6 +1,7 @@ package ca.uhn.fhir.jpa.dao; import ca.uhn.fhir.jpa.entity.ResourceEncodingEnum; +import ca.uhn.fhir.jpa.util.JpaConstants; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.Validate; @@ -115,6 +116,7 @@ public class DaoConfig { private Integer myCountSearchResultsUpTo = null; private IdStrategyEnum myResourceServerIdStrategy = IdStrategyEnum.SEQUENTIAL_NUMERIC; private boolean myMarkResourcesForReindexingUponSearchParameterChange; + private boolean myExpungeEnabled; /** * Constructor @@ -405,8 +407,11 @@ public class DaoConfig { /** * This may be used to optionally register server interceptors directly against the DAOs. */ - public void setInterceptors(List theInterceptors) { - myInterceptors = theInterceptors; + public void setInterceptors(IServerInterceptor... theInterceptor) { + setInterceptors(new ArrayList()); + if (theInterceptor != null && theInterceptor.length != 0) { + getInterceptors().addAll(Arrays.asList(theInterceptor)); + } } /** @@ -657,7 +662,7 @@ public class DaoConfig { /** * If enabled, the server will support the use of :contains searches, * which are helpful but can have adverse effects on performance. - * + *

* Default is true */ public boolean isAllowContainsSearches() { @@ -667,7 +672,7 @@ public class DaoConfig { /** * If enabled, the server will support the use of :contains searches, * which are helpful but can have adverse effects on performance. - * + *

* Default is true */ public void setAllowContainsSearches(boolean theAllowContainsSearches) { @@ -924,6 +929,36 @@ public class DaoConfig { myDeleteStaleSearches = theDeleteStaleSearches; } + /** + * If set to true (default is false), the $expunge operation + * will be enabled on this server. This operation is potentially dangerous since it allows + * a client to physically delete data in a way that can not be recovered (without resorting + * to backups). + *

+ * It is recommended to not enable this setting without appropriate security + * in place on your server to prevent non-administrators from using this + * operation. + *

+ */ + public boolean isExpungeEnabled() { + return myExpungeEnabled; + } + + /** + * If set to true (default is false), the $expunge operation + * will be enabled on this server. This operation is potentially dangerous since it allows + * a client to physically delete data in a way that can not be recovered (without resorting + * to backups). + *

+ * It is recommended to not enable this setting without appropriate security + * in place on your server to prevent non-administrators from using this + * operation. + *

+ */ + public void setExpungeEnabled(boolean theExpungeEnabled) { + myExpungeEnabled = theExpungeEnabled; + } + /** * Should contained IDs be indexed the same way that non-contained IDs are (default is * true) @@ -1025,7 +1060,7 @@ public class DaoConfig { /** * If set to true (default is true), indexes will be - * created for search parameters marked as {@link ca.uhn.fhir.jpa.util.JpaConstants#EXT_SP_UNIQUE}. + * created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}. * This is a HAPI FHIR specific extension which can be used to specify that no more than one * resource can exist which matches a given criteria, using a database constraint to * enforce this. @@ -1036,7 +1071,7 @@ public class DaoConfig { /** * If set to true (default is true), indexes will be - * created for search parameters marked as {@link ca.uhn.fhir.jpa.util.JpaConstants#EXT_SP_UNIQUE}. + * created for search parameters marked as {@link JpaConstants#EXT_SP_UNIQUE}. * This is a HAPI FHIR specific extension which can be used to specify that no more than one * resource can exist which matches a given criteria, using a database constraint to * enforce this. @@ -1073,11 +1108,8 @@ public class DaoConfig { /** * This may be used to optionally register server interceptors directly against the DAOs. */ - public void setInterceptors(IServerInterceptor... theInterceptor) { - setInterceptors(new ArrayList()); - if (theInterceptor != null && theInterceptor.length != 0) { - getInterceptors().addAll(Arrays.asList(theInterceptor)); - } + public void setInterceptors(List theInterceptors) { + myInterceptors = theInterceptors; } /** diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java index fc7c320d389..eca44f7cb8f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java @@ -245,11 +245,13 @@ public abstract class BaseJpaTest { return bundleStr; } - public static void purgeDatabase(IFhirSystemDao theSystemDao, ISearchParamPresenceSvc theSearchParamPresenceSvc, ISearchCoordinatorSvc theSearchCoordinatorSvc, ISearchParamRegistry theSearchParamRegistry) { - + public static void purgeDatabase(DaoConfig theDaoConfig, IFhirSystemDao theSystemDao, ISearchParamPresenceSvc theSearchParamPresenceSvc, ISearchCoordinatorSvc theSearchCoordinatorSvc, ISearchParamRegistry theSearchParamRegistry) { theSearchCoordinatorSvc.cancelAllActiveSearches(); + boolean expungeEnabled = theDaoConfig.isExpungeEnabled(); + theDaoConfig.setExpungeEnabled(true); theSystemDao.expunge(new ExpungeOptions().setExpungeEverything(true)); + theDaoConfig.setExpungeEnabled(expungeEnabled); theSearchParamPresenceSvc.flushCachesForUnitTest(); theSearchParamRegistry.forceRefresh(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java index b009399298c..a4210a76bff 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java @@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu2; import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider; import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; +import ca.uhn.fhir.jpa.util.SingleItemLoadingCache; import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt; import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.composite.MetaDt; @@ -40,6 +41,7 @@ import org.springframework.transaction.support.TransactionTemplate; import javax.persistence.EntityManager; import java.io.IOException; import java.io.InputStream; +import java.util.Map; import static org.junit.Assert.*; import static org.mockito.Mockito.mock; @@ -47,6 +49,9 @@ import static org.mockito.Mockito.mock; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {TestDstu2Config.class}) public abstract class BaseJpaDstu2Test extends BaseJpaTest { + @Autowired + @Qualifier("myResourceCountsCache") + protected SingleItemLoadingCache> myResourceCountsCache; @Autowired protected ISearchParamRegistry mySearchParamRegsitry; @Autowired @@ -189,7 +194,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest { @Before @Transactional() public void beforePurgeDatabase() { - purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry); + purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java index 14bc06a2227..ffcb9a4b9ad 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java @@ -265,7 +265,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest { @Before @Transactional() public void beforePurgeDatabase() { - purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry); + purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java index 99cb6b1264b..0eb282cbd40 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchWithLuceneDisabledTest.java @@ -152,7 +152,7 @@ public class FhirResourceDaoDstu3SearchWithLuceneDisabledTest extends BaseJpaTes @Before @Transactional() public void beforePurgeDatabase() { - purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry); + purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java index 52688e97b6d..9a2b53fad0f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java @@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc; import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc; import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc; import ca.uhn.fhir.jpa.term.IHapiTerminologySvc; +import ca.uhn.fhir.jpa.util.SingleItemLoadingCache; import ca.uhn.fhir.jpa.validation.JpaValidationSupportChainR4; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.parser.StrictErrorHandler; @@ -56,6 +57,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest { private static JpaValidationSupportChainR4 ourJpaValidationSupportChainR4; private static IFhirResourceDaoValueSet ourValueSetDao; + @Autowired + @Qualifier("myResourceCountsCache") + protected SingleItemLoadingCache> myResourceCountsCache; @Autowired protected IResourceLinkDao myResourceLinkDao; @Autowired @@ -273,7 +277,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest { @Transactional() public void beforePurgeDatabase() { final EntityManager entityManager = this.myEntityManager; - purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry); + purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegsitry); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithLuceneDisabledTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithLuceneDisabledTest.java index 30cea5414e0..ce9f92452a5 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithLuceneDisabledTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchWithLuceneDisabledTest.java @@ -93,7 +93,7 @@ public class FhirResourceDaoR4SearchWithLuceneDisabledTest extends BaseJpaTest { @Before @Transactional() public void beforePurgeDatabase() { - purgeDatabase(mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry); + purgeDatabase(myDaoConfig, mySystemDao, mySearchParamPresenceSvc, mySearchCoordinatorSvc, mySearchParamRegistry); } @Before diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java index 90a05bce680..f194983a74f 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderDstu2Test.java @@ -1318,6 +1318,9 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test { pt.addName().addFamily(methodName); ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless(); + myResourceCountsCache.clear(); + myResourceCountsCache.update(); + HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts"); CloseableHttpResponse response = ourHttpClient.execute(get); try { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ExpungeProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java similarity index 96% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ExpungeProviderDstu2Test.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java index e9e08d24d94..8cd118d38a0 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ExpungeProviderDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/ResourceProviderExpungeDstu2Test.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.provider; +import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.util.ExpungeOptions; import ca.uhn.fhir.model.dstu2.resource.Observation; @@ -10,14 +11,14 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.util.TestUtil; import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.*; -public class ExpungeProviderDstu2Test extends BaseResourceProviderDstu2Test { - +public class ResourceProviderExpungeDstu2Test extends BaseResourceProviderDstu2Test { private IIdType myOneVersionPatientId; private IIdType myTwoVersionPatientId; private IIdType myDeletedPatientId; @@ -25,6 +26,11 @@ public class ExpungeProviderDstu2Test extends BaseResourceProviderDstu2Test { private IIdType myTwoVersionObservationId; private IIdType myDeletedObservationId; + @After + public void afterDisableExpunge() { + myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled()); + } + private void assertExpunged(IIdType theId) { try { getDao(theId).read(theId); @@ -97,6 +103,11 @@ public class ExpungeProviderDstu2Test extends BaseResourceProviderDstu2Test { } + @Before + public void beforeEnableExpunge() { + myDaoConfig.setExpungeEnabled(true); + } + private IFhirResourceDao getDao(IIdType theId) { IFhirResourceDao dao; switch (theId.getResourceType()) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java index 94fd9dcc13e..75e30533aa3 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java @@ -1632,6 +1632,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test { pt.addName().setFamily(methodName); ourClient.create().resource(pt).execute().getId().toUnqualifiedVersionless(); + myResourceCountsCache.clear(); myResourceCountsCache.update(); HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts"); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ExpungeProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java similarity index 88% rename from hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ExpungeProviderDstu3Test.java rename to hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java index e3b2a95e3b7..11ac4744bc6 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ExpungeProviderDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderExpungeDstu3Test.java @@ -1,22 +1,27 @@ package ca.uhn.fhir.jpa.provider.dstu3; +import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.util.ExpungeOptions; +import ca.uhn.fhir.jpa.util.JpaConstants; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.util.TestUtil; -import org.hl7.fhir.dstu3.model.Observation; -import org.hl7.fhir.dstu3.model.Patient; +import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.instance.model.api.IIdType; +import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static org.junit.Assert.*; -public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test { +public class ResourceProviderExpungeDstu3Test extends BaseResourceProviderDstu3Test { + private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderExpungeDstu3Test.class); private IIdType myOneVersionPatientId; private IIdType myTwoVersionPatientId; private IIdType myDeletedPatientId; @@ -24,6 +29,11 @@ public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test { private IIdType myTwoVersionObservationId; private IIdType myDeletedObservationId; + @After + public void afterDisableExpunge() { + myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled()); + } + private void assertExpunged(IIdType theId) { try { getDao(theId).read(theId); @@ -96,6 +106,11 @@ public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test { } + @Before + public void beforeEnableExpunge() { + myDaoConfig.setExpungeEnabled(true); + } + private IFhirResourceDao getDao(IIdType theId) { IFhirResourceDao dao; switch (theId.getResourceType()) { @@ -275,6 +290,21 @@ public class ExpungeProviderDstu3Test extends BaseResourceProviderDstu3Test { assertGone(myDeletedObservationId); } + @Test + public void testParameters() { + Parameters p = new Parameters(); + p.addParameter() + .setName(JpaConstants.OPERATION_EXPUNGE_OUT_PARAM_EXPUNGE_COUNT) + .setValue(new IntegerType(1000)); + p.addParameter() + .setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) + .setValue(new BooleanType(true)); + p.addParameter() + .setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) + .setValue(new BooleanType(true)); + ourLog.info(myFhirCtx.newJsonParser().encodeResourceToString(p)); + } + @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java index a459dd22003..84d872e667b 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ExpungeR4Test.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.jpa.provider.r4; +import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.util.ExpungeOptions; import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException; @@ -9,6 +10,7 @@ import ca.uhn.fhir.util.TestUtil; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Patient; +import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; @@ -24,6 +26,16 @@ public class ExpungeR4Test extends BaseResourceProviderR4Test { private IIdType myTwoVersionObservationId; private IIdType myDeletedObservationId; + @After + public void afterDisableExpunge() { + myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled()); + } + + @Before + public void beforeEnableExpunge() { + myDaoConfig.setExpungeEnabled(true); + } + private void assertExpunged(IIdType theId) { try { getDao(theId).read(theId); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderExpungeR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderExpungeR4Test.java index f56bb5082bc..4f6722b09f1 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderExpungeR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderExpungeR4Test.java @@ -1,12 +1,15 @@ package ca.uhn.fhir.jpa.provider.r4; +import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.dao.IFhirResourceDao; import ca.uhn.fhir.jpa.util.JpaConstants; +import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.util.TestUtil; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.*; +import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.Test; @@ -23,6 +26,11 @@ public class ResourceProviderExpungeR4Test extends BaseResourceProviderR4Test { private IIdType myTwoVersionObservationId; private IIdType myDeletedObservationId; + @After + public void afterDisableExpunge() { + myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled()); + } + private void assertExpunged(IIdType theId) { try { getDao(theId).read(theId); @@ -95,6 +103,11 @@ public class ResourceProviderExpungeR4Test extends BaseResourceProviderR4Test { } + @Before + public void beforeEnableExpunge() { + myDaoConfig.setExpungeEnabled(true); + } + private IFhirResourceDao getDao(IIdType theId) { IFhirResourceDao dao; switch (theId.getResourceType()) { @@ -150,6 +163,46 @@ public class ResourceProviderExpungeR4Test extends BaseResourceProviderR4Test { } + @Test + public void testExpungeDisabled() { + myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled()); + + Parameters input = new Parameters(); + input.addParameter() + .setName(JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT) + .setValue(new IntegerType(1000)); + input.addParameter() + .setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES) + .setValue(new BooleanType(true)); + input.addParameter() + .setName(JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS) + .setValue(new BooleanType(true)); + + try { + myClient + .operation() + .onInstance(myTwoVersionPatientId) + .named("expunge") + .withParameters(input) + .execute(); + fail(); + } catch (MethodNotAllowedException e){ + assertEquals("HTTP 405 Method Not Allowed: $expunge is not enabled on this server", e.getMessage()); + } + // Only deleted and prior patients + assertStillThere(myOneVersionPatientId); + assertStillThere(myTwoVersionPatientId.withVersion("1")); + assertStillThere(myTwoVersionPatientId.withVersion("2")); + assertGone(myDeletedPatientId); + + // No observations deleted + assertStillThere(myOneVersionObservationId); + assertStillThere(myTwoVersionObservationId.withVersion("1")); + assertStillThere(myTwoVersionObservationId.withVersion("2")); + assertGone(myDeletedObservationId); + + } + @Test public void testExpungeSystemEverything() { Parameters input = new Parameters(); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java index b12cb064040..e590ee1a247 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java @@ -1690,6 +1690,9 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test { pt.addName().setFamily(methodName); myClient.create().resource(pt).execute().getId().toUnqualifiedVersionless(); + myResourceCountsCache.clear(); + myResourceCountsCache.update(); + HttpGet get = new HttpGet(ourServerBase + "/$get-resource-counts"); CloseableHttpResponse response = ourHttpClient.execute(get); try { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java index 3bb7a429f8c..51e57322d66 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java @@ -1,23 +1,6 @@ package ca.uhn.fhir.jpa.subscription; -import static org.junit.Assert.assertEquals; - -import java.util.List; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.google.common.collect.Lists; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.provider.BaseResourceProviderDstu2Test; @@ -37,6 +20,14 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.util.PortUtil; +import com.google.common.collect.Lists; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.junit.*; + +import java.util.List; /** * Test the rest-hook subscriptions