change mdm interceptor loader to fail when message subscription types… (#5128)

* change mdm interceptor loader to fail when message subscription types aren't enabled.

* cleanup

* cleanup

* fix tests

* cleanup

* spotless

* fix test

* fix test

* changelog

---------

Co-authored-by: Ken Stevens <ken@smilecdr.com>
This commit is contained in:
Ken Stevens 2023-07-27 10:39:32 -04:00 committed by GitHub
parent dcf3240191
commit b376778b99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 43 deletions

View File

@ -0,0 +1,7 @@
---
type: change
issue: 5128
title: "Previously, when running with mdm, the server automatically changed storage settings to enable
message subscriptions. This has been changed to require the user to explicitly enable message subscriptions
when running with mdm. If mdm is enabled and message subscriptions are not enabled, the server will now throw
an exception on startup."

View File

@ -1,10 +1,13 @@
package ca.uhn.fhir.jpa.mdm.config;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.mdm.helper.MdmHelperR4;
import ca.uhn.fhir.jpa.subscription.channel.config.SubscriptionChannelConfig;
import ca.uhn.fhir.jpa.subscription.submit.config.SubscriptionSubmitterConfig;
import org.hl7.fhir.dstu2.model.Subscription;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
@Import({SubscriptionSubmitterConfig.class, SubscriptionChannelConfig.class})
public class TestMdmConfigR4 extends BaseTestMdmConfig {
@ -12,4 +15,14 @@ public class TestMdmConfigR4 extends BaseTestMdmConfig {
MdmHelperR4 mdmHelperR4() {
return new MdmHelperR4();
}
@Primary
@Bean
public JpaStorageSettings storageSettings() {
JpaStorageSettings retVal = new JpaStorageSettings();
retVal.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.MESSAGE);
return retVal;
}
}

View File

@ -1,15 +1,13 @@
package ca.uhn.fhir.jpa.util.jsonpatch;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.jpa.patch.JsonPatchUtils;
import ca.uhn.fhir.jpa.test.BaseJpaTest;
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import org.hl7.fhir.r4.model.Observation;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.PlatformTransactionManager;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@ -17,9 +15,7 @@ import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
public class JsonPatchUtilsTest extends BaseJpaTest {
private static final FhirContext ourCtx = FhirContext.forR4Cached();
public class JsonPatchUtilsTest extends BaseJpaR4Test {
private static final Logger ourLog = LoggerFactory.getLogger(JsonPatchUtilsTest.class);
@SuppressWarnings("JsonStandardCompliance")
@ -37,7 +33,7 @@ public class JsonPatchUtilsTest extends BaseJpaTest {
" } ]";
try {
JsonPatchUtils.apply(ourCtx, new Observation(), patchText);
JsonPatchUtils.apply(myFhirContext, new Observation(), patchText);
fail();
} catch (InvalidRequestException e) {
ourLog.info(e.toString());
@ -62,7 +58,7 @@ public class JsonPatchUtilsTest extends BaseJpaTest {
" } ]";
try {
JsonPatchUtils.apply(ourCtx, new Observation(), patchText);
JsonPatchUtils.apply(myFhirContext, new Observation(), patchText);
fail();
} catch (InvalidRequestException e) {
ourLog.info(e.toString());
@ -88,9 +84,9 @@ public class JsonPatchUtilsTest extends BaseJpaTest {
"]";
Observation toUpdate = new Observation();
toUpdate = JsonPatchUtils.apply(ourCtx, toUpdate, patchText);
toUpdate = JsonPatchUtils.apply(myFhirContext, toUpdate, patchText);
String outcome = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(toUpdate);
String outcome = myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(toUpdate);
ourLog.info(outcome);
assertThat(outcome, containsString("\"reference\": \"Media/465eb73a-bce3-423a-b86e-5d0d267638f4\""));
@ -111,21 +107,11 @@ public class JsonPatchUtilsTest extends BaseJpaTest {
Observation toUpdate = new Observation();
try {
JsonPatchUtils.apply(ourCtx, toUpdate, patchText);
JsonPatchUtils.apply(myFhirContext, toUpdate, patchText);
fail();
} catch (InvalidRequestException e) {
assertEquals(Msg.code(1271) + "Failed to apply JSON patch to Observation: " + Msg.code(1825) + "Unknown element 'derivedFromXXX' found during parse", e.getMessage());
}
}
@Override
protected FhirContext getFhirContext() {
return ourCtx;
}
@Override
protected PlatformTransactionManager getTxManager() {
return null;
}
}

View File

@ -36,9 +36,41 @@ import ca.uhn.fhir.jpa.config.JpaConfig;
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.JpaPersistedResourceValidationSupport;
import ca.uhn.fhir.jpa.dao.data.*;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamCoordsDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamNumberDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamStringDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamTokenDao;
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamUriDao;
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.dao.data.IResourceTagDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemDao;
import ca.uhn.fhir.jpa.dao.data.ITermCodeSystemVersionDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptDesignationDao;
import ca.uhn.fhir.jpa.dao.data.ITermConceptPropertyDao;
import ca.uhn.fhir.jpa.dao.data.ITermValueSetConceptDao;
import ca.uhn.fhir.jpa.dao.data.ITermValueSetDao;
import ca.uhn.fhir.jpa.entity.TermConcept;
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
import ca.uhn.fhir.jpa.entity.TermConceptProperty;
import ca.uhn.fhir.jpa.entity.TermValueSet;
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
import ca.uhn.fhir.jpa.model.entity.ForcedId;
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamUri;
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.model.util.JpaConstants;
import ca.uhn.fhir.jpa.partition.IPartitionLookupSvc;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
@ -62,7 +94,11 @@ import ca.uhn.fhir.test.utilities.LoggingExtension;
import ca.uhn.fhir.test.utilities.ProxyUtil;
import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
import ca.uhn.fhir.test.utilities.server.SpringContextGrabbingTestExecutionListener;
import ca.uhn.fhir.util.*;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.ClasspathUtil;
import ca.uhn.fhir.util.FhirVersionIndependentConcept;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.TestUtil;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
@ -98,7 +134,13 @@ import javax.persistence.EntityManager;
import java.io.IOException;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@ -108,7 +150,11 @@ import java.util.stream.Stream;
import static ca.uhn.fhir.util.TestUtil.doRandomizeLocaleAndTimezone;
import static java.util.stream.Collectors.joining;
import static org.awaitility.Awaitility.await;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.when;
@ -146,7 +192,7 @@ public abstract class BaseJpaTest extends BaseTest {
@Autowired
protected FhirContext myFhirContext;
@Autowired
protected JpaStorageSettings myStorageSettings = new JpaStorageSettings();
protected JpaStorageSettings myStorageSettings;
@Autowired
protected DatabaseBackedPagingProvider myDatabaseBackedPagingProvider;
@Autowired

View File

@ -55,17 +55,19 @@ public class MdmProviderLoader {
@Autowired
private JpaStorageSettings myStorageSettings;
private BaseMdmProvider myMdmProvider;
private MdmProviderDstu3Plus myMdmProvider;
private MdmLinkHistoryProviderDstu3Plus myMdmHistoryProvider;
public void loadProvider() {
switch (myFhirContext.getVersion().getVersion()) {
case DSTU3:
case R4:
myResourceProviderFactory.addSupplier(() -> new MdmProviderDstu3Plus(
myFhirContext, myMdmControllerSvc, myMdmControllerHelper, myMdmSubmitSvc, myMdmSettings));
myMdmProvider = new MdmProviderDstu3Plus(
myFhirContext, myMdmControllerSvc, myMdmControllerHelper, myMdmSubmitSvc, myMdmSettings);
myResourceProviderFactory.addSupplier(() -> myMdmProvider);
if (myStorageSettings.isNonResourceDbHistoryEnabled()) {
myResourceProviderFactory.addSupplier(
() -> new MdmLinkHistoryProviderDstu3Plus(myFhirContext, myMdmControllerSvc));
myMdmHistoryProvider = new MdmLinkHistoryProviderDstu3Plus(myFhirContext, myMdmControllerSvc);
myResourceProviderFactory.addSupplier(() -> myMdmHistoryProvider);
}
break;
default:
@ -76,6 +78,11 @@ public class MdmProviderLoader {
@PreDestroy
public void unloadProvider() {
if (myMdmProvider != null) {
myResourceProviderFactory.removeSupplier(() -> myMdmProvider);
}
if (myMdmHistoryProvider != null) {
myResourceProviderFactory.removeSupplier(() -> myMdmHistoryProvider);
}
}
}

View File

@ -19,9 +19,10 @@
*/
package ca.uhn.fhir.jpa.mdm.interceptor;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.interceptor.api.IInterceptorService;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.subscription.submit.interceptor.SubscriptionSubmitInterceptorLoader;
import ca.uhn.fhir.mdm.api.IMdmSettings;
import ca.uhn.fhir.mdm.interceptor.IMdmStorageInterceptor;
import ca.uhn.fhir.mdm.interceptor.MdmSearchExpandingInterceptor;
@ -50,21 +51,18 @@ public class MdmSubmitterInterceptorLoader {
@Autowired
private IInterceptorService myInterceptorService;
@Autowired
private SubscriptionSubmitInterceptorLoader mySubscriptionSubmitInterceptorLoader;
@PostConstruct
public void loadInterceptors() {
if (!myMdmSettings.isEnabled()) {
return;
}
myStorageSettings.addSupportedSubscriptionType(Subscription.SubscriptionChannelType.MESSAGE);
if (!myStorageSettings.getSupportedSubscriptionTypes().contains(Subscription.SubscriptionChannelType.MESSAGE)) {
throw new ConfigurationException(
Msg.code(2421) + "MDM requires Message Subscriptions to be enabled in the Storage Settings");
}
myInterceptorService.registerInterceptor(myIMdmStorageInterceptor);
myInterceptorService.registerInterceptor(myMdmSearchExpandingInterceptorInterceptor);
ourLog.info("MDM interceptor registered");
// We need to call SubscriptionSubmitInterceptorLoader.start() again in case there were no subscription types
// the first time it was called.
mySubscriptionSubmitInterceptorLoader.start();
ourLog.info("MDM interceptors registered");
}
}