From a3d1114b808c86fe1ad286e3b962b8d657a2d247 Mon Sep 17 00:00:00 2001 From: Nate Moraca Date: Wed, 20 Sep 2023 10:11:20 -0400 Subject: [PATCH 1/2] remove HAPI client and references; HAPI validation libraries will remain --- .../madiefhirservice/hapi/HapiFhirServer.java | 119 ---------------- .../resources/MeasureBundleController.java | 33 ----- .../services/MeasureBundleService.java | 8 -- src/main/resources/application.yml | 4 - .../hapi/HapiFhirServerTest.java | 132 ------------------ 5 files changed, 296 deletions(-) delete mode 100644 src/main/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServer.java delete mode 100644 src/test/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServerTest.java diff --git a/src/main/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServer.java b/src/main/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServer.java deleted file mode 100644 index 6338a10f..00000000 --- a/src/main/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServer.java +++ /dev/null @@ -1,119 +0,0 @@ -package gov.cms.madie.madiefhirservice.hapi; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.client.api.IGenericClient; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.hl7.fhir.r4.model.Bundle; -import org.hl7.fhir.r4.model.Library; -import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; -import org.hl7.fhir.r4.model.Resource; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import jakarta.annotation.PostConstruct; -import java.util.Optional; - -@Service -@Slf4j -public class HapiFhirServer { - - private static final String CACHE_HEADER_NAME = "Cache-Control"; - private static final String CACHE_HEADER_VALUE = "no-cache"; - - @Getter private final FhirContext fhirContext; - - @Value("${hapi.fhir.url}") - private String hapiFhirUrl; - - @Getter IGenericClient hapiClient; - - public HapiFhirServer(FhirContext fhirContext) { - this.fhirContext = fhirContext; - } - - @PostConstruct - public void setUp() { - hapiClient = fhirContext.newRestfulGenericClient(hapiFhirUrl); - hapiClient.registerInterceptor(createLoggingInterceptor()); - - log.info("Created hapi client for server: {} ", hapiFhirUrl); - } - - private LoggingInterceptor createLoggingInterceptor() { - var loggingInterceptor = new LoggingInterceptor(); - - loggingInterceptor.setLogger(log); - loggingInterceptor.setLogRequestBody(false); - loggingInterceptor.setLogRequestHeaders(false); - loggingInterceptor.setLogRequestSummary(log.isDebugEnabled()); - - loggingInterceptor.setLogResponseBody(false); - loggingInterceptor.setLogResponseHeaders(false); - loggingInterceptor.setLogResponseSummary(log.isDebugEnabled()); - - return loggingInterceptor; - } - - public Bundle fetchLibraryBundleByNameAndVersion(String name, String version) { - return hapiClient - .search() - .forResource(Library.class) - .where(Library.VERSION.exactly().code(version)) - .and(Library.NAME.matchesExactly().value(name)) - .returnBundle(Bundle.class) - .withAdditionalHeader(CACHE_HEADER_NAME, CACHE_HEADER_VALUE) - .execute(); - } - - public Optional fetchHapiLibrary(String name, String version) { - return findLibraryResourceInBundle( - fetchLibraryBundleByNameAndVersion(name, version), Library.class); - } - - public Optional findLibraryResourceInBundle( - Bundle bundle, Class clazz) { - if (bundle.getEntry().size() > 1) { - log.error( - "Hapi-Fhir Resource for {} returned more than one resource count: {}", - clazz.getSimpleName(), - bundle.getEntry().size()); - return Optional.empty(); - } else { - return findResourceFromBundle(bundle, clazz); - } - } - - private Optional findResourceFromBundle(Bundle bundle, Class clazz) { - Resource resource = bundle.getEntry().get(0).getResource(); - - if (clazz.isInstance(resource)) { - log.info("Hapi-Fhir Resource for {} found in DB.", clazz.getSimpleName()); - return Optional.of((T) resource); - } else { - log.error( - "Hapi-Fhir Resource is of wrong type expected: {} found in bundle: {}", - clazz.getSimpleName(), - resource.getClass().getSimpleName()); - return Optional.empty(); - } - } - - public MethodOutcome createResource(Resource resource) { - log.debug( - "Creating resource {} with id {} in HAPI", - resource.getResourceType() != null ? resource.getResourceType().name() : "null", - resource.getId()); - MethodOutcome outcome = hapiClient.create().resource(resource).execute(); - log.debug("Resource created successfully in HAPI. Resource id {}", resource.getId()); - return outcome; - } - - public MethodOutcome createResourceAsString(String resource) { - log.debug("Creating resource in HAPI"); - MethodOutcome outcome = hapiClient.create().resource(resource).execute(); - log.debug("Resource created successfully in HAPI. Resource id {}", outcome.getId().toString()); - return outcome; - } -} diff --git a/src/main/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleController.java b/src/main/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleController.java index 2538b8aa..601fa437 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleController.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleController.java @@ -65,39 +65,6 @@ public ResponseEntity getMeasureBundle( .body(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle)); } - @PostMapping(value = "/save", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity saveMeasure( - HttpServletRequest request, - @RequestHeader("Authorization") String accessToken, - @RequestBody @Validated(Measure.ValidationSequence.class) Measure measure) { - log.debug("Entering saveMeasure()"); - - Bundle bundle = - measureBundleService.createMeasureBundle( - measure, - request.getUserPrincipal(), - BundleUtil.MEASURE_BUNDLE_TYPE_EXPORT, - accessToken); - bundle.setType(Bundle.BundleType.DOCUMENT); - String serialized = - fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle); - MethodOutcome outcome = measureBundleService.saveMeasureBundle(serialized); - - if (outcome != null && outcome.getCreated()) { - log.debug( - "Successfully saved MADiE measure in HAPI FHIR. MADiE measure id = " - + measure.getId() - + " HAPI FHIR id = " - + outcome.getId().toString()); - return ResponseEntity.status(HttpStatus.CREATED).body(outcome.getId().toString()); - } else { - String errorMsg = - "Error saving versioned measure in HAPI FHIR! MADiE measure id = " + measure.getId(); - log.error(errorMsg); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorMsg); - } - } - @PutMapping( value = "/export", produces = { diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java index e6b617f7..34419336 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/MeasureBundleService.java @@ -1,7 +1,6 @@ package gov.cms.madie.madiefhirservice.services; import gov.cms.madie.madiefhirservice.constants.UriConstants; -import gov.cms.madie.madiefhirservice.hapi.HapiFhirServer; import gov.cms.madie.madiefhirservice.utils.BundleUtil; import gov.cms.madie.madiefhirservice.utils.FhirResourceHelpers; import gov.cms.madie.madiefhirservice.utils.ResourceUtils; @@ -23,8 +22,6 @@ import org.hl7.fhir.r4.model.Resource; import org.springframework.stereotype.Service; -import ca.uhn.fhir.rest.api.MethodOutcome; - import java.util.HashMap; import java.util.List; import java.util.Map; @@ -37,7 +34,6 @@ public class MeasureBundleService { private final MeasureTranslatorService measureTranslatorService; private final LibraryTranslatorService libraryTranslatorService; private final LibraryService libraryService; - private final HapiFhirServer hapiFhirServer; private final ElmTranslatorClient elmTranslatorClient; private final HumanReadableService humanReadableService; @@ -149,10 +145,6 @@ public CqlLibrary createCqlLibraryForMadieMeasure(Measure madieMeasure) { .build(); } - public MethodOutcome saveMeasureBundle(String measureBundle) { - return hapiFhirServer.createResourceAsString(measureBundle); - } - private void setNarrativeText(DomainResource resource, String humanReadable) { Narrative narrative = new Narrative(); narrative.setStatus(Narrative.NarrativeStatus.EXTENSIONS); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 38895971..87997bfe 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -3,10 +3,6 @@ server: servlet: context-path: /api -hapi: - fhir: - url: ${HAPI_FHIR_URL:http://localhost:8080/fhir} - fhir-base-url: ${FHIR_BASE_URL:http://ecqi.healthit.gov/ecqms} madie: diff --git a/src/test/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServerTest.java b/src/test/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServerTest.java deleted file mode 100644 index 70ad1ab8..00000000 --- a/src/test/java/gov/cms/madie/madiefhirservice/hapi/HapiFhirServerTest.java +++ /dev/null @@ -1,132 +0,0 @@ -package gov.cms.madie.madiefhirservice.hapi; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.rest.api.MethodOutcome; -import ca.uhn.fhir.rest.client.api.IGenericClient; -import gov.cms.madie.madiefhirservice.utils.LibraryHelper; -import gov.cms.madie.madiefhirservice.utils.ResourceFileUtil; - -import org.hl7.fhir.instance.model.api.IIdType; -import org.hl7.fhir.r4.model.Bundle; -import org.hl7.fhir.r4.model.Library; -import org.hl7.fhir.r4.model.Measure; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class HapiFhirServerTest implements LibraryHelper, ResourceFileUtil { - - @InjectMocks private HapiFhirServer hapiFhirServer; - - @Mock private FhirContext fhirContext; - @Mock MethodOutcome methodOutcome; - @Mock IIdType iidType; - - IGenericClient hapiClient; - - Bundle bundle = new Bundle(); - private Library globalCommonsFunctionsLibrary; - - @BeforeEach - void setUp() { - ReflectionTestUtils.setField(hapiFhirServer, "hapiFhirUrl", "https://hapiFhirTestUrl.com"); - hapiClient = mock(IGenericClient.class, new ReturnsDeepStubs()); - ReflectionTestUtils.setField(hapiFhirServer, "hapiClient", hapiClient); - } - - @BeforeEach - void buildLibraryBundle() { - - String fhirHelpersCql = getStringFromTestResource("/includes/FHIRHelpers.cql"); - Library fhirHelpersLibrary = createLibrary(fhirHelpersCql); - - String globalCommonsFunctionsCql = - getStringFromTestResource("/includes/GlobalCommonFunctions.cql"); - globalCommonsFunctionsLibrary = createLibrary(globalCommonsFunctionsCql); - - Bundle.BundleEntryComponent bundleEntryComponent = bundle.addEntry(); - bundleEntryComponent.setResource(fhirHelpersLibrary); - } - - @Test - void getCtx() { - assertEquals(fhirContext, hapiFhirServer.getFhirContext()); - } - - @Test - void getHapiClient() { - assertEquals(hapiClient, hapiFhirServer.getHapiClient()); - } - - @Test - void testSuccessfullyFindingLibraryResourceInBundle() { - Optional optionalLibrary = - hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class); - assertTrue(optionalLibrary.isPresent()); - assertEquals("FHIRHelpers", optionalLibrary.get().getName()); - } - - @Test - void testMoreThanOneResourceFound() { - Bundle.BundleEntryComponent bundleEntryComponent = bundle.addEntry(); - bundleEntryComponent.setResource(globalCommonsFunctionsLibrary); - - assertEquals(2, bundle.getEntry().size()); - - Optional optionalLibrary = - hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class); - assertTrue(optionalLibrary.isEmpty()); - } - - @Test - void testResourceFoundIsNotAnInstanceOfLibrary() { - Bundle bundle = new Bundle(); - Measure measureResource = new Measure(); - Bundle.BundleEntryComponent bundleEntryComponent = bundle.addEntry(); - bundleEntryComponent.setResource(measureResource); - - // providing measure instance instead of library - Optional optionalLibrary = - hapiFhirServer.findLibraryResourceInBundle(bundle, Library.class); - assertTrue(optionalLibrary.isEmpty()); - } - - @Test - void createResource() { - MethodOutcome outcome = new MethodOutcome(); - - Object when = hapiClient.create().resource(any(Library.class)).execute(); - - when((Object) when).thenReturn(outcome); - - MethodOutcome methodOutcome = hapiFhirServer.createResource(new Library()); - assertSame(outcome, methodOutcome); - } - - @Test - void createResourceAsString() { - - when(methodOutcome.getId()).thenReturn(iidType); - when(iidType.toString()).thenReturn("testId"); - - Object when = hapiClient.create().resource(any(String.class)).execute(); - - when((Object) when).thenReturn(methodOutcome); - - MethodOutcome methodOutcome = hapiFhirServer.createResourceAsString(new Bundle().toString()); - assertSame(methodOutcome, methodOutcome); - } -} From 6a8eda3a9ec871be400f149d956be97ef97f5a42 Mon Sep 17 00:00:00 2001 From: Nate Moraca Date: Wed, 20 Sep 2023 10:22:33 -0400 Subject: [PATCH 2/2] remove more refs to HAPI client logic --- .../services/HumanReadableService.java | 1 - .../MeasureBundleControllerMvcTest.java | 80 ------------------- .../services/LibraryServiceTest.java | 1 - .../services/MeasureBundleServiceTest.java | 15 ---- 4 files changed, 97 deletions(-) diff --git a/src/main/java/gov/cms/madie/madiefhirservice/services/HumanReadableService.java b/src/main/java/gov/cms/madie/madiefhirservice/services/HumanReadableService.java index 1e34c185..35f6e29f 100644 --- a/src/main/java/gov/cms/madie/madiefhirservice/services/HumanReadableService.java +++ b/src/main/java/gov/cms/madie/madiefhirservice/services/HumanReadableService.java @@ -35,7 +35,6 @@ @Service @RequiredArgsConstructor public class HumanReadableService extends ResourceUtils { - private final LiquidEngine liquidEngine; diff --git a/src/test/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleControllerMvcTest.java b/src/test/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleControllerMvcTest.java index 7861d986..df030ee1 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleControllerMvcTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/resources/MeasureBundleControllerMvcTest.java @@ -107,86 +107,6 @@ public void testGetMeasureBundleXml() throws Exception { .createMeasureBundle(any(Measure.class), any(Principal.class), anyString(), anyString()); } - @Test - public void testSaveMeasureSuccess() throws Exception { - String madieMeasureJson = - getStringFromTestResource("/measures/SimpleFhirMeasureLib/madie_measure.json"); - Bundle testBundle = MeasureTestHelper.createTestMeasureBundle(); - - when(measureBundleService.createMeasureBundle( - any(Measure.class), any(Principal.class), anyString(), anyString())) - .thenReturn(testBundle); - when(fhirContext.newJsonParser()).thenReturn(FhirContext.forR4().newJsonParser()); - - when(methodOutcome.getCreated()).thenReturn(true); - when(methodOutcome.getId()).thenReturn(iidType); - when(iidType.toString()).thenReturn("testId"); - - when(measureBundleService.saveMeasureBundle(anyString())).thenReturn(methodOutcome); - - mockMvc - .perform( - MockMvcRequestBuilders.post("/fhir/measures/save") - .with(user(TEST_USER_ID)) - .with(csrf()) - .header(HttpHeaders.AUTHORIZATION, "test-okta") - .content(madieMeasureJson) - .contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(status().isCreated()); - verify(measureBundleService, times(1)).saveMeasureBundle(anyString()); - } - - @Test - public void testSaveMeasureFailure() throws Exception { - String madieMeasureJson = - getStringFromTestResource("/measures/SimpleFhirMeasureLib/madie_measure.json"); - Bundle testBundle = MeasureTestHelper.createTestMeasureBundle(); - - when(measureBundleService.createMeasureBundle( - any(Measure.class), any(Principal.class), anyString(), anyString())) - .thenReturn(testBundle); - when(fhirContext.newJsonParser()).thenReturn(FhirContext.forR4().newJsonParser()); - - when(measureBundleService.saveMeasureBundle(anyString())).thenReturn(null); - - mockMvc - .perform( - MockMvcRequestBuilders.post("/fhir/measures/save") - .with(user(TEST_USER_ID)) - .with(csrf()) - .header(HttpHeaders.AUTHORIZATION, "test-okta") - .content(madieMeasureJson) - .contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(status().is5xxServerError()); - verify(measureBundleService, times(1)).saveMeasureBundle(anyString()); - } - - @Test - public void testSaveMeasureFailureNotCreated() throws Exception { - String madieMeasureJson = - getStringFromTestResource("/measures/SimpleFhirMeasureLib/madie_measure.json"); - Bundle testBundle = MeasureTestHelper.createTestMeasureBundle(); - - when(measureBundleService.createMeasureBundle( - any(Measure.class), any(Principal.class), anyString(), anyString())) - .thenReturn(testBundle); - when(fhirContext.newJsonParser()).thenReturn(FhirContext.forR4().newJsonParser()); - - when(methodOutcome.getCreated()).thenReturn(false); - when(measureBundleService.saveMeasureBundle(anyString())).thenReturn(methodOutcome); - - mockMvc - .perform( - MockMvcRequestBuilders.post("/fhir/measures/save") - .with(user(TEST_USER_ID)) - .with(csrf()) - .header(HttpHeaders.AUTHORIZATION, "test-okta") - .content(madieMeasureJson) - .contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(status().is5xxServerError()); - verify(measureBundleService, times(1)).saveMeasureBundle(anyString()); - } - @Test public void testExportMeasure() throws Exception { String madieMeasureJson = diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java index 899c523e..ebe16075 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/LibraryServiceTest.java @@ -2,7 +2,6 @@ import gov.cms.madie.madiefhirservice.cql.LibraryCqlVisitorFactory; import gov.cms.madie.madiefhirservice.exceptions.*; -import gov.cms.madie.madiefhirservice.hapi.HapiFhirServer; import gov.cms.madie.madiefhirservice.utils.BundleUtil; import gov.cms.madie.madiefhirservice.utils.LibraryHelper; import gov.cms.madie.madiefhirservice.utils.ResourceFileUtil; diff --git a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java index 8dd6519b..597f5e83 100644 --- a/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java +++ b/src/test/java/gov/cms/madie/madiefhirservice/services/MeasureBundleServiceTest.java @@ -5,7 +5,6 @@ import ca.uhn.fhir.rest.api.MethodOutcome; import gov.cms.madie.madiefhirservice.constants.UriConstants; import gov.cms.madie.madiefhirservice.exceptions.CqlLibraryNotFoundException; -import gov.cms.madie.madiefhirservice.hapi.HapiFhirServer; import gov.cms.madie.madiefhirservice.utils.BundleUtil; import gov.cms.madie.madiefhirservice.utils.MeasureTestHelper; import gov.cms.madie.madiefhirservice.utils.ResourceFileUtil; @@ -49,7 +48,6 @@ public class MeasureBundleServiceTest implements ResourceFileUtil { @Mock private LibraryService libraryService; @Mock private HumanReadableService humanReadableService; @Mock private ElmTranslatorClient elmTranslatorClient; - @Mock private HapiFhirServer hapiFhirServer; @Mock MethodOutcome methodOutcome; @Mock IIdType iidType; @@ -155,19 +153,6 @@ public void testCreateMeasureBundleWhenIncludedLibraryNotFoundInHapi() { is(equalTo("Cannot find a CQL Library with name: FHIRHelpers, version: 4.0.001"))); } - @Test - public void testSaveMeasure() { - when(methodOutcome.getCreated()).thenReturn(true); - when(methodOutcome.getId()).thenReturn(iidType); - when(iidType.toString()).thenReturn("testId"); - when(hapiFhirServer.createResourceAsString(anyString())).thenReturn(methodOutcome); - - MethodOutcome outcome = measureBundleService.saveMeasureBundle("test"); - - assertTrue(outcome.getCreated()); - assertEquals("testId", outcome.getId().toString()); - } - @Test public void testCreateMeasureBundleForExport() { when(measureTranslatorService.createFhirMeasureForMadieMeasure(madieMeasure))