From d166d014d60c1e7398a9d0187cd827ea1da9b8ad Mon Sep 17 00:00:00 2001 From: smirnovaae Date: Thu, 28 Sep 2023 12:48:19 -0700 Subject: [PATCH 1/5] wip --- .../gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java b/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java index 0240b14d..c994dbd8 100644 --- a/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java +++ b/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java @@ -55,6 +55,7 @@ private static void cleanOutUnNeededData(ExplanationOfBenefit benefit) { Inherited - Identifier, resourceType, type */ // Extensions should exist in benefit: AB2D-5728 Validate Humana AB2D data dictionary for missing elements reported in STU3 + benefit.setExtension(null); benefit.setPatientTarget(null); benefit.setCreated(null); benefit.setEnterer(null); From 77850f579bc0910ef3d0c5d2882d34a5b8e97e8a Mon Sep 17 00:00:00 2001 From: smirnovaae Date: Tue, 14 Jan 2025 08:41:04 -0800 Subject: [PATCH 2/5] Revert Post request to BFD --- .../cms/ab2d/bfd/client/BFDClientImpl.java | 7 +-- .../cms/ab2d/bfd/client/BFDSearchImpl.java | 31 +++-------- .../bfd/client/BlueButtonClientR4Test.java | 4 +- .../bfd/client/BlueButtonClientSTU3Test.java | 22 ++++---- .../gov/cms/ab2d/bfd/client/MockUtils.java | 53 ++++++------------- build.gradle | 8 +-- 6 files changed, 44 insertions(+), 81 deletions(-) diff --git a/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDClientImpl.java b/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDClientImpl.java index d1d9fd5a..44748f5d 100644 --- a/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDClientImpl.java +++ b/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDClientImpl.java @@ -1,6 +1,5 @@ package gov.cms.ab2d.bfd.client; -import ca.uhn.fhir.rest.api.SearchStyleEnum; import ca.uhn.fhir.rest.gclient.TokenClientParam; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; @@ -162,8 +161,7 @@ public IBaseBundle requestPartDEnrolleesFromServer(FhirVersion version, String c .withAdditionalHeader(BFDClient.BFD_HDR_BULK_CLIENTID, contractNumber) .withAdditionalHeader(BFDClient.BFD_HDR_BULK_JOBID, getJobId()) .withAdditionalHeader(INCLUDE_IDENTIFIERS_HEADER, MBI_HEADER_VALUE) - .count(contractToBenePageSize) - .usingStyle(SearchStyleEnum.POST); + .count(contractToBenePageSize); log.info("Executing request to get Part D Enrollees " + request); return request.returnBundle(version.getBundleClass()) .encodedJson() @@ -191,8 +189,7 @@ public IBaseBundle requestPartDEnrolleesFromServer(FhirVersion version, String c .withAdditionalHeader(BFDClient.BFD_HDR_BULK_CLIENTID, contractNumber) .withAdditionalHeader(BFDClient.BFD_HDR_BULK_JOBID, getJobId()) .withAdditionalHeader(INCLUDE_IDENTIFIERS_HEADER, MBI_HEADER_VALUE) - .count(contractToBenePageSize) - .usingStyle(SearchStyleEnum.POST); + .count(contractToBenePageSize); log.info("Executing request to get Part D Enrollees " + request); return request.returnBundle(version.getBundleClass()) .encodedJson() diff --git a/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDSearchImpl.java b/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDSearchImpl.java index 0c83bb3e..585f94df 100644 --- a/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDSearchImpl.java +++ b/ab2d-bfd/src/main/java/gov/cms/ab2d/bfd/client/BFDSearchImpl.java @@ -4,14 +4,10 @@ import com.newrelic.api.agent.Trace; import gov.cms.ab2d.fhir.FhirVersion; import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; import org.apache.http.HttpStatus; -import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.message.BasicNameValuePair; +import org.apache.http.client.methods.HttpGet; import org.hl7.fhir.instance.model.api.IBaseBundle; import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; @@ -54,32 +50,21 @@ public BFDSearchImpl(HttpClient httpClient, Environment environment, BfdClientVe @Override public IBaseBundle searchEOB(long patientId, OffsetDateTime since, OffsetDateTime until, int pageSize, String bulkJobId, FhirVersion version, String contractNum) throws IOException { String urlLocation = bfdClientVersions.getUrl(version); + StringBuilder url = new StringBuilder(urlLocation + "ExplanationOfBenefit?patient=" + patientId + "&excludeSAMHSA=true"); - HttpPost request = new HttpPost(urlLocation + "ExplanationOfBenefit/_search"); - // No active profiles means use JSON - if (environment.getActiveProfiles().length == 0) { - request.addHeader("Accept", "application/fhir+json;q=1.0, application/json+fhir;q=0.9"); - } - request.addHeader(HttpHeaders.ACCEPT, "gzip"); - request.addHeader(HttpHeaders.ACCEPT_CHARSET, "utf-8"); - request.addHeader(BFDClient.BFD_HDR_BULK_CLIENTID, contractNum); - request.addHeader(BFDClient.BFD_HDR_BULK_JOBID, bulkJobId); - - List params = new ArrayList<>(); - params.add(new BasicNameValuePair("patient", "" + patientId)); - params.add(new BasicNameValuePair("excludeSAMHSA", "true")); if (since != null) { - params.add(new BasicNameValuePair("_lastUpdated", "ge" + since)); + url.append("&_lastUpdated=ge").append(since); } if (until != null) { - params.add(new BasicNameValuePair("_lastUpdated", "le" + until)); + url.append("&_lastUpdated=le").append(until); } if (pageSize > 0) { - params.add(new BasicNameValuePair("_count", "" + pageSize)); + url.append("&_count=").append(pageSize); } - request.setEntity(new UrlEncodedFormEntity(params)); + + HttpGet request = new HttpGet(url.toString()); log.info("Executing BFD Search Request " + request); byte[] responseBytes = getEOBSFromBFD(patientId, request); @@ -91,7 +76,7 @@ public IBaseBundle searchEOB(long patientId, OffsetDateTime since, OffsetDateTim Method exists to track connection to BFD for New Relic */ @Trace - private byte[] getEOBSFromBFD(long patientId, HttpPost request) throws IOException { + private byte[] getEOBSFromBFD(long patientId, HttpGet request) throws IOException { byte[] responseBytes; try (CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(request)) { int status = response.getStatusLine().getStatusCode(); diff --git a/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientR4Test.java b/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientR4Test.java index 814a6c4c..352cbd5e 100644 --- a/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientR4Test.java +++ b/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientR4Test.java @@ -65,7 +65,7 @@ public static void setupBFDClient() throws IOException { // Ensure timeouts are working. MockUtils.createMockServerExpectation( - "/v2/fhir/ExplanationOfBenefit/_search", + "/v2/fhir/ExplanationOfBenefit", HttpStatus.SC_OK, getRawJson(SAMPLE_EOB_BUNDLE), List.of(Parameter.param("patient", TEST_PATIENT_ID.toString()), @@ -74,7 +74,7 @@ public static void setupBFDClient() throws IOException { ); MockUtils.createMockServerExpectation( - "/v2/fhir/Patient/_search", + "/v2/fhir/Patient", HttpStatus.SC_OK, getRawJson(SAMPLE_PATIENT_BUNDLE), List.of(Parameter.param("_has:Coverage.extension", diff --git a/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientSTU3Test.java b/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientSTU3Test.java index c906300f..5ff9cd0e 100644 --- a/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientSTU3Test.java +++ b/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/BlueButtonClientSTU3Test.java @@ -82,7 +82,7 @@ public static void setupBFDClient() throws IOException { // Ensure timeouts are working. MockUtils.createMockServerExpectation( - "/v1/fhir/ExplanationOfBenefit/_search", + "/v1/fhir/ExplanationOfBenefit", HttpStatus.SC_OK, StringUtils.EMPTY, Collections.singletonList(Parameter.param("patient", TEST_SLOW_PATIENT_ID.toString())), @@ -92,7 +92,7 @@ public static void setupBFDClient() throws IOException { for (String patientId : TEST_PATIENT_IDS) { MockUtils.createMockServerExpectation( - "/v1/fhir/Patient/_search" + patientId, + "/v1/fhir/Patient" + patientId, HttpStatus.SC_OK, getRawJson(SAMPLE_PATIENT_PATH_PREFIX + patientId + ".json"), List.of(), @@ -100,7 +100,7 @@ public static void setupBFDClient() throws IOException { ); MockUtils.createMockServerExpectation( - "/v1/fhir/ExplanationOfBenefit/_search", + "/v1/fhir/ExplanationOfBenefit", HttpStatus.SC_OK, getRawJson(SAMPLE_EOB_PATH_PREFIX + patientId + ".json"), List.of(Parameter.param("patient", patientId), @@ -110,7 +110,7 @@ public static void setupBFDClient() throws IOException { } MockUtils.createMockServerExpectation( - "/v1/fhir/Patient/_search", + "/v1/fhir/Patient", HttpStatus.SC_OK, getRawJson(SAMPLE_PATIENT_PATH_PREFIX + "/bundle/patientbundle.json"), List.of(), @@ -119,14 +119,14 @@ public static void setupBFDClient() throws IOException { // Patient that exists, but has no records MockUtils.createMockServerExpectation( - "/v1/fhir/Patient/_search" + TEST_NO_RECORD_PATIENT_ID, + "/v1/fhir/Patient" + TEST_NO_RECORD_PATIENT_ID, HttpStatus.SC_OK, getRawJson(SAMPLE_PATIENT_PATH_PREFIX + TEST_NO_RECORD_PATIENT_ID + ".json"), List.of(), MOCK_PORT_V1 ); MockUtils.createMockServerExpectation( - "/v1/fhir/ExplanationOfBenefit/_search", + "/v1/fhir/ExplanationOfBenefit", HttpStatus.SC_OK, getRawJson(SAMPLE_EOB_PATH_PREFIX + TEST_NO_RECORD_PATIENT_ID + ".json"), List.of(Parameter.param("patient", TEST_NO_RECORD_PATIENT_ID.toString()), @@ -135,14 +135,14 @@ public static void setupBFDClient() throws IOException { ); MockUtils.createMockServerExpectation( - "/v1/fhir/Patient/_search" + TEST_NO_RECORD_PATIENT_ID_MBI, + "/v1/fhir/Patient" + TEST_NO_RECORD_PATIENT_ID_MBI, HttpStatus.SC_OK, getRawJson(SAMPLE_PATIENT_PATH_PREFIX + TEST_NO_RECORD_PATIENT_ID_MBI + ".json"), List.of(), MOCK_PORT_V1 ); MockUtils.createMockServerExpectation( - "/v1/fhir/ExplanationOfBenefit/_search", + "/v1/fhir/ExplanationOfBenefit", HttpStatus.SC_OK, getRawJson(SAMPLE_EOB_PATH_PREFIX + TEST_NO_RECORD_PATIENT_ID_MBI + ".json"), List.of(Parameter.param("patient", TEST_NO_RECORD_PATIENT_ID_MBI.toString()), @@ -153,7 +153,7 @@ public static void setupBFDClient() throws IOException { // Create mocks for pages of the results for (String startIndex : List.of("10", "20", "30")) { MockUtils.createMockServerExpectation( - "/v1/fhir/ExplanationOfBenefit/_search", + "/v1/fhir/ExplanationOfBenefit", HttpStatus.SC_OK, getRawJson(SAMPLE_EOB_PATH_PREFIX + TEST_PATIENT_ID + "_" + startIndex + ".json"), List.of(Parameter.param("patient", TEST_PATIENT_ID.toString()), @@ -166,7 +166,7 @@ public static void setupBFDClient() throws IOException { for (String month : CONTRACT_MONTHS) { MockUtils.createMockServerExpectation( - "/v1/fhir/Patient/_search", + "/v1/fhir/Patient", HttpStatus.SC_OK, getRawJson(SAMPLE_PATIENT_PATH_PREFIX + "/bundle/patientbundle.json"), List.of(Parameter.param("_has:Coverage.extension", @@ -247,7 +247,7 @@ void shouldNotHaveNextBundle() { "Should have no next link since all the resources are in the bundle"); } -// @Test + @Test void shouldHaveNextBundle() { org.hl7.fhir.dstu3.model.Bundle response = (org.hl7.fhir.dstu3.model.Bundle) bbc.requestEOBFromServer(STU3, TEST_PATIENT_ID, CONTRACT); diff --git a/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/MockUtils.java b/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/MockUtils.java index 36828528..eadd78b6 100644 --- a/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/MockUtils.java +++ b/ab2d-bfd/src/test/java/gov/cms/ab2d/bfd/client/MockUtils.java @@ -29,7 +29,7 @@ static String getRawJson(String path) throws IOException { } /** - * Helper method that configures the mock server to respond to a given POST request + * Helper method that configures the mock server to respond to a given GET request * * @param path The path segment of the URL that would be received by BlueButton * @param respCode The desired HTTP response code @@ -47,41 +47,22 @@ static MockServerClient createMockServerExpectation(String path, int respCode, S static MockServerClient createMockServerExpectation(String path, int respCode, String payload, List qStringParams, int delayMs, int port) { MockServerClient mock = new MockServerClient("localhost", port); - if (path.contains("/fhir/metadata")) { - mock.when( - HttpRequest.request() - .withMethod("GET") - .withPath(path) - .withBody(params(qStringParams)), - Times.unlimited() - ).respond( - org.mockserver.model.HttpResponse.response() - .withStatusCode(respCode) - .withHeader( - new Header("Content-Type", - "application/json;charset=UTF-8") - ) - .withBody(payload) - .withDelay(TimeUnit.MILLISECONDS, delayMs) - ); - } else { - mock.when( - HttpRequest.request() - .withMethod("POST") - .withPath(path) - .withBody(params(qStringParams)), - Times.unlimited() - ).respond( - org.mockserver.model.HttpResponse.response() - .withStatusCode(respCode) - .withHeader( - new Header("Content-Type", - "application/json;charset=UTF-8") - ) - .withBody(payload) - .withDelay(TimeUnit.MILLISECONDS, delayMs) - ); - } + mock.when( + HttpRequest.request() + .withMethod("GET") + .withPath(path) + .withQueryStringParameters(qStringParams), + Times.unlimited() + ).respond( + org.mockserver.model.HttpResponse.response() + .withStatusCode(respCode) + .withHeader( + new Header("Content-Type", + "application/json;charset=UTF-8") + ) + .withBody(payload) + .withDelay(TimeUnit.MILLISECONDS, delayMs) + ); return mock; } diff --git a/build.gradle b/build.gradle index 5ce87960..33f09980 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ ext { // AB2D libraries fhirVersion='2.1.0' - bfdVersion='3.2.0' + bfdVersion='2.5.0' aggregatorVersion='2.0.1' filtersVersion='2.1.0' eventClientVersion='3.2.1' @@ -157,8 +157,8 @@ subprojects { jar { processResources.exclude('checkstyle.xml') - classifier "main".equalsIgnoreCase(gitBranch()) || "main".equalsIgnoreCase(System.getenv('BRANCH_NAME')) ? "" : "SNAPSHOT" - out.println("**** building branch - " + gitBranch() + ", classifier - " + classifier + " - CI branch - " + System.getenv('BRANCH_NAME')) + // classifier "main".equalsIgnoreCase(gitBranch()) || "main".equalsIgnoreCase(System.getenv('BRANCH_NAME')) ? "" : "SNAPSHOT" + // out.println("**** building branch - " + gitBranch() + ", classifier - " + classifier + " - CI branch - " + System.getenv('BRANCH_NAME')) } test { @@ -174,7 +174,7 @@ subprojects { jacocoTestReport { reports { - xml.enabled true + // xml.enabled true } } From 0c53022612ed2e66f92a5a2b79a9897f92e671d7 Mon Sep 17 00:00:00 2001 From: smirnovaae Date: Tue, 14 Jan 2025 08:41:43 -0800 Subject: [PATCH 3/5] Revert Post request to BFD --- .../gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java b/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java index c994dbd8..0240b14d 100644 --- a/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java +++ b/ab2d-filters/src/main/java/gov/cms/ab2d/filter/ExplanationOfBenefitTrimmerSTU3.java @@ -55,7 +55,6 @@ private static void cleanOutUnNeededData(ExplanationOfBenefit benefit) { Inherited - Identifier, resourceType, type */ // Extensions should exist in benefit: AB2D-5728 Validate Humana AB2D data dictionary for missing elements reported in STU3 - benefit.setExtension(null); benefit.setPatientTarget(null); benefit.setCreated(null); benefit.setEnterer(null); From 0f8c76153b81758f4fec9f281915ccfeca61a281 Mon Sep 17 00:00:00 2001 From: smirnovaae Date: Tue, 28 Jan 2025 16:29:09 -0800 Subject: [PATCH 4/5] update dependency --- ab2d-sns-client/build.gradle | 2 +- build.gradle | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ab2d-sns-client/build.gradle b/ab2d-sns-client/build.gradle index b20834fc..4d9afed1 100644 --- a/ab2d-sns-client/build.gradle +++ b/ab2d-sns-client/build.gradle @@ -5,7 +5,7 @@ dependencies { compileOnly "org.projectlombok:lombok:${lombokVersion}" implementation 'com.fasterxml.jackson.core:jackson-core:2.17.2' implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2' - implementation 'software.amazon.awssdk:sns:2.27.9' + implementation "io.awspring.cloud:spring-cloud-aws-starter-sns:${springCloudAwsVersion}" implementation(project(":ab2d-events-client")) testCompileOnly "org.projectlombok:lombok:${lombokVersion}" diff --git a/build.gradle b/build.gradle index a3789907..678aabce 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ ext { eventClientVersion='3.2.3' propertiesClientVersion='2.0.0' contractClientVersion='2.0.0' - snsClientVersion='1.0.0' + snsClientVersion='1.0.1' sourcesRepo = 'ab2d-maven-repo' deployerRepo = 'ab2d-main' @@ -157,8 +157,8 @@ subprojects { jar { processResources.exclude('checkstyle.xml') - // classifier "main".equalsIgnoreCase(gitBranch()) || "main".equalsIgnoreCase(System.getenv('BRANCH_NAME')) ? "" : "SNAPSHOT" - // out.println("**** building branch - " + gitBranch() + ", classifier - " + classifier + " - CI branch - " + System.getenv('BRANCH_NAME')) + classifier "main".equalsIgnoreCase(gitBranch()) || "main".equalsIgnoreCase(System.getenv('BRANCH_NAME')) ? "" : "SNAPSHOT" + out.println("**** building branch - " + gitBranch() + ", classifier - " + classifier + " - CI branch - " + System.getenv('BRANCH_NAME')) } test { @@ -174,7 +174,7 @@ subprojects { jacocoTestReport { reports { - // xml.enabled true + xml.enabled true } } From e6283b0d2b5d1889135327f09ec93da39ba0cad5 Mon Sep 17 00:00:00 2001 From: smirnovaae Date: Mon, 3 Feb 2025 14:31:49 -0800 Subject: [PATCH 5/5] upgrade jackson version --- ab2d-sns-client/build.gradle | 4 ++-- build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ab2d-sns-client/build.gradle b/ab2d-sns-client/build.gradle index 4d9afed1..8df6aa7e 100644 --- a/ab2d-sns-client/build.gradle +++ b/ab2d-sns-client/build.gradle @@ -3,8 +3,8 @@ dependencies { implementation "org.springframework.boot:spring-boot-starter:${springBootVersion}" annotationProcessor "org.projectlombok:lombok:${lombokVersion}" compileOnly "org.projectlombok:lombok:${lombokVersion}" - implementation 'com.fasterxml.jackson.core:jackson-core:2.17.2' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2' + implementation "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}" + implementation "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}" implementation "io.awspring.cloud:spring-cloud-aws-starter-sns:${springCloudAwsVersion}" implementation(project(":ab2d-events-client")) diff --git a/build.gradle b/build.gradle index 954e9772..5004d774 100644 --- a/build.gradle +++ b/build.gradle @@ -45,7 +45,7 @@ ext { testContainerVersion='1.20.1' mockServerVersion='5.15.0' liquibaseVersion="4.23.0" - jacksonVersion = "2.15.2" + jacksonVersion = "2.18.2" slackAPIVersion='1.30.0' jupiterVersion='5.9.3' hl7Version = '5.6.971'