Skip to content

Commit 5628899

Browse files
[DPC-5384] Me/dpc 5384 dw upgrade (#3004)
## 🎫 Ticket https://jira.cms.gov/browse/DPC-5384 ## 🛠 Changes Bumped DropWizard from 4.x to 5.0.1 and updated code where necessary. ## ℹ️ Context - DropWizard 4.x had reached end of life. - Jetty 11 was accumulating Snyk alerts that are only fixed in 12.x, and Jetty 12 is only supported in DropWizard 5. ## 🧪 Validation CI passes and services can start and run.
1 parent e09e7ca commit 5628899

10 files changed

Lines changed: 124 additions & 142 deletions

File tree

dpc-api/pom.xml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,6 @@
109109
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
110110
<scope>compile</scope>
111111
</dependency>
112-
<dependency>
113-
<groupId>${hapi.fhir.groupID}</groupId>
114-
<artifactId>hapi-fhir-caching-caffeine</artifactId>
115-
<scope>compile</scope>
116-
</dependency>
117112
<dependency>
118113
<groupId>io.jsonwebtoken</groupId>
119114
<artifactId>jjwt-api</artifactId>
@@ -132,9 +127,8 @@
132127
<scope>runtime</scope>
133128
</dependency>
134129
<dependency>
135-
<groupId>com.github.ben-manes.caffeine</groupId>
136-
<artifactId>caffeine</artifactId>
137-
<version>2.9.3</version>
130+
<groupId>${hapi.fhir.groupID}</groupId>
131+
<artifactId>hapi-fhir-caching-caffeine</artifactId>
138132
</dependency>
139133
<dependency>
140134
<groupId>com.google.guava</groupId>

dpc-api/src/test/java/gov/cms/dpc/api/APITestHelpers.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import gov.cms.dpc.fhir.dropwizard.handlers.exceptions.PersistenceExceptionHandler;
2424
import gov.cms.dpc.fhir.validations.DPCProfileSupport;
2525
import gov.cms.dpc.fhir.validations.ProfileValidator;
26-
import gov.cms.dpc.fhir.validations.dropwizard.FHIRValidatorProvider;
26+
import gov.cms.dpc.fhir.validations.dropwizard.FHIRValidationModule;
2727
import gov.cms.dpc.fhir.validations.dropwizard.InjectingConstraintValidatorFactory;
2828
import gov.cms.dpc.testing.APIAuthHelpers;
2929
import gov.cms.dpc.testing.factories.FHIRPatientBuilder;
@@ -63,7 +63,6 @@ public class APITestHelpers {
6363
private static final String ATTRIBUTION_TRUNCATE_TASK = "http://localhost:9902/tasks/truncate";
6464
private static final String CONSENT_TRUNCATE_TASK = "http://localhost:9901/tasks/truncate";
6565
public static String ORGANIZATION_NPI = "1111111112";
66-
6766
private static final String configPath = "src/test/resources/test.application.yml";
6867

6968
private APITestHelpers() {
@@ -166,7 +165,7 @@ public static ResourceExtension buildResourceExtension(FhirContext
166165
new DefaultProfileValidationSupport(ctx),
167166
new InMemoryTerminologyServerValidationSupport(ctx));
168167
final InjectingConstraintValidatorFactory constraintFactory = new InjectingConstraintValidatorFactory(
169-
Set.of(new ProfileValidator(new FHIRValidatorProvider(ctx, config, support).get())));
168+
Set.of(new ProfileValidator(new FHIRValidationModule(config).provideFhirValidator(ctx, support))));
170169

171170
builder.setValidator(provideValidator(constraintFactory));
172171
}

dpc-api/src/test/java/gov/cms/dpc/api/resources/v1/DataResourceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ static Stream<Arguments> downloadArgs() {
6060
@ParameterizedTest
6161
@MethodSource("downloadArgs")
6262
void canDownloadFiles(boolean compressFile, Map<String, String> requestHeaders) throws IOException {
63-
String testData = "test data".repeat(500);
63+
String testData = "test data".repeat(50);
6464
String fileName = createTestExport(testData, compressFile);
6565

6666
try (ClassicHttpResponse response = downloadExport(fileName, requestHeaders)) {

dpc-attribution/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
<groupId>ru.vyarus</groupId>
5757
<artifactId>dropwizard-guicey</artifactId>
5858
</dependency>
59+
<dependency>
60+
<groupId>${hapi.fhir.groupID}</groupId>
61+
<artifactId>hapi-fhir-caching-caffeine</artifactId>
62+
</dependency>
5963
<dependency>
6064
<groupId>com.google.inject</groupId>
6165
<artifactId>guice</artifactId>

dpc-common/src/main/java/gov/cms/dpc/fhir/validations/dropwizard/FHIRValidationModule.java

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,40 @@
33
import ca.uhn.fhir.context.FhirContext;
44
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
55
import ca.uhn.fhir.validation.FhirValidator;
6+
import ca.uhn.fhir.validation.ValidationOptions;
67
import com.google.inject.AbstractModule;
78
import com.google.inject.Provides;
89
import com.google.inject.Scopes;
910
import com.google.inject.TypeLiteral;
1011
import com.google.inject.multibindings.Multibinder;
12+
import gov.cms.dpc.fhir.DPCIdentifierSystem;
1113
import gov.cms.dpc.fhir.configuration.DPCFHIRConfiguration.FHIRValidationConfiguration;
1214
import gov.cms.dpc.fhir.validations.DPCProfileSupport;
1315
import gov.cms.dpc.fhir.validations.ProfileValidator;
16+
import gov.cms.dpc.fhir.validations.profiles.PatientProfile;
17+
import io.dropwizard.jersey.validation.Validators;
18+
import jakarta.inject.Singleton;
1419
import jakarta.validation.ConstraintValidator;
1520
import jakarta.validation.ConstraintValidatorFactory;
1621
import jakarta.validation.Validator;
1722
import jakarta.validation.ValidatorFactory;
1823
import org.glassfish.jersey.server.internal.inject.ConfiguredValidator;
1924
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
2025
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
26+
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
27+
import org.hl7.fhir.dstu3.model.Enumerations;
28+
import org.hl7.fhir.dstu3.model.Patient;
29+
import org.slf4j.Logger;
30+
import org.slf4j.LoggerFactory;
31+
32+
import java.sql.Date;
2133

2234

2335
/**
2436
* Guice module for setting up the required Validation components, if requested by the application
2537
*/
2638
public class FHIRValidationModule extends AbstractModule {
39+
private static final Logger logger = LoggerFactory.getLogger(FHIRValidationModule.class);
2740

2841
private final FHIRValidationConfiguration config;
2942

@@ -41,11 +54,9 @@ protected void configure() {
4154
constraintBinder.addBinding().to(ProfileValidator.class);
4255

4356
bind(ConstraintValidatorFactory.class).to(InjectingConstraintValidatorFactory.class);
44-
bind(ValidatorFactory.class).toProvider(ValidatorFactoryProvider.class);
4557
bind(ConfiguredValidator.class).to(InjectingConfiguredValidator.class);
4658

4759
bind(DPCProfileSupport.class).in(Scopes.SINGLETON);
48-
bind(FhirValidator.class).toProvider(FHIRValidatorProvider.class);
4960
}
5061

5162
@Provides
@@ -58,6 +69,14 @@ Validator provideValidator(ValidatorFactory factory) {
5869
return factory.getValidator();
5970
}
6071

72+
@Provides
73+
@Singleton
74+
ValidatorFactory provideValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
75+
return Validators.newConfiguration()
76+
.constraintValidatorFactory(constraintValidatorFactory)
77+
.buildValidatorFactory();
78+
}
79+
6180
@Provides
6281
ValidationSupportChain provideSupportChain(DPCProfileSupport dpcModule) {
6382
FhirContext ctx = FhirContext.forDstu3();
@@ -66,4 +85,39 @@ ValidationSupportChain provideSupportChain(DPCProfileSupport dpcModule) {
6685
new DefaultProfileValidationSupport(ctx),
6786
new InMemoryTerminologyServerValidationSupport(ctx));
6887
}
88+
89+
@Provides
90+
@Singleton
91+
public FhirValidator provideFhirValidator(FhirContext ctx,
92+
ValidationSupportChain supportChain) {
93+
final FhirValidator fhirValidator = ctx.newValidator();
94+
final FhirInstanceValidator instanceValidator = new FhirInstanceValidator(supportChain);
95+
96+
fhirValidator.registerValidatorModule(instanceValidator);
97+
primeValidator(fhirValidator);
98+
99+
return fhirValidator;
100+
}
101+
102+
/**
103+
* Helper method that primes the Validator cache by creating a dummy patient and validating it.
104+
* This is really dumb, but it avoids issues where the tests timeout when running in CI.
105+
* Is necessary in order to address DPC-608
106+
* <p>
107+
* We may need to add more resources here in the future, if things continue to be slow.
108+
*
109+
* @param validator - {@link FhirValidator} validator to prime
110+
*/
111+
private void primeValidator(FhirValidator validator) {
112+
logger.trace("Validating dummy patient");
113+
final Patient patient = new Patient();
114+
patient.addName().addGiven("Dummy").setFamily("Patient");
115+
patient.addIdentifier().setSystem(DPCIdentifierSystem.MBI.getSystem()).setValue("test-mbi");
116+
patient.setGender(Enumerations.AdministrativeGender.MALE);
117+
patient.setBirthDate(Date.valueOf("1990-01-01"));
118+
119+
final ValidationOptions op = new ValidationOptions();
120+
op.addProfile(PatientProfile.PROFILE_URI);
121+
validator.validateWithResult(patient, op);
122+
}
69123
}

dpc-common/src/main/java/gov/cms/dpc/fhir/validations/dropwizard/FHIRValidatorProvider.java

Lines changed: 0 additions & 85 deletions
This file was deleted.

dpc-common/src/test/java/gov/cms/dpc/fhir/dropwizard/filters/FHIRRequestFilterTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package gov.cms.dpc.fhir.dropwizard.filters;
22

33
import gov.cms.dpc.fhir.FHIRMediaTypes;
4+
import jakarta.servlet.http.HttpServletResponse;
45
import jakarta.ws.rs.WebApplicationException;
56
import jakarta.ws.rs.container.ContainerRequestContext;
67
import jakarta.ws.rs.core.HttpHeaders;
78
import jakarta.ws.rs.core.MediaType;
89
import jakarta.ws.rs.core.MultivaluedMap;
910
import jakarta.ws.rs.core.UriInfo;
10-
import org.eclipse.jetty.server.Response;
1111
import org.junit.jupiter.api.Test;
1212
import org.mockito.Mockito;
1313

@@ -43,7 +43,7 @@ void testMissingAcceptsHeaderForExport() throws URISyntaxException {
4343
Mockito.when(request.getHeaders()).thenReturn(headerMap);
4444

4545
final WebApplicationException exception = assertThrows(WebApplicationException.class, () -> filter.filter(request));
46-
assertEquals(Response.SC_BAD_REQUEST, exception.getResponse().getStatus(), "Should have 400 error");
46+
assertEquals(HttpServletResponse.SC_BAD_REQUEST, exception.getResponse().getStatus(), "Should have 400 error");
4747
}
4848

4949
@Test
@@ -55,7 +55,7 @@ void testIncorrectAcceptsHeaderForExport() throws URISyntaxException {
5555
Mockito.when(request.getHeaders()).thenReturn(headerMap);
5656

5757
final WebApplicationException exception = assertThrows(WebApplicationException.class, () -> filter.filter(request));
58-
assertEquals(Response.SC_UNSUPPORTED_MEDIA_TYPE, exception.getResponse().getStatus(), "Should have 415 error");
58+
assertEquals(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, exception.getResponse().getStatus(), "Should have 415 error");
5959
}
6060

6161
@Test
@@ -67,7 +67,7 @@ void testWildcardAcceptsHeaderForExport() throws URISyntaxException {
6767
Mockito.when(request.getHeaders()).thenReturn(headerMap);
6868

6969
final WebApplicationException exception = assertThrows(WebApplicationException.class, () -> filter.filter(request));
70-
assertEquals(Response.SC_UNSUPPORTED_MEDIA_TYPE, exception.getResponse().getStatus(), "Should have 415 error");
70+
assertEquals(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, exception.getResponse().getStatus(), "Should have 415 error");
7171
}
7272

7373
@Test
@@ -92,7 +92,7 @@ void testNullAcceptsHeader() throws URISyntaxException {
9292
Mockito.when(request.getHeaders()).thenReturn(headerMap);
9393

9494
final WebApplicationException exception = assertThrows(WebApplicationException.class, () -> filter.filter(request));
95-
assertEquals(Response.SC_BAD_REQUEST, exception.getResponse().getStatus(), "Should have 400 error");
95+
assertEquals(HttpServletResponse.SC_BAD_REQUEST, exception.getResponse().getStatus(), "Should have 400 error");
9696
}
9797

9898
@Test
@@ -104,7 +104,7 @@ void testIncorrectContentHeader() throws URISyntaxException {
104104
Mockito.when(request.getHeaders()).thenReturn(headerMap);
105105

106106
final WebApplicationException exception = assertThrows(WebApplicationException.class, () -> filter.filter(request));
107-
assertEquals(Response.SC_UNSUPPORTED_MEDIA_TYPE, exception.getResponse().getStatus(), "Should have 415 error");
107+
assertEquals(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE, exception.getResponse().getStatus(), "Should have 415 error");
108108
}
109109

110110
@Test

dpc-common/src/test/java/gov/cms/dpc/fhir/validations/FHIRValidatorProviderTest.java

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package gov.cms.dpc.fhir.validations.dropwizard;
2+
3+
import ca.uhn.fhir.context.FhirContext;
4+
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
5+
import ca.uhn.fhir.validation.FhirValidator;
6+
import gov.cms.dpc.fhir.configuration.DPCFHIRConfiguration;
7+
import jakarta.validation.ConstraintValidatorFactory;
8+
import jakarta.validation.ValidatorFactory;
9+
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
10+
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
11+
import org.junit.jupiter.api.Test;
12+
13+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
14+
import static org.mockito.Mockito.mock;
15+
16+
class FHIRValidationModuleUnitTest {
17+
private final DPCFHIRConfiguration.FHIRValidationConfiguration config = mock(DPCFHIRConfiguration.FHIRValidationConfiguration.class);
18+
private final ConstraintValidatorFactory cvf = mock(ConstraintValidatorFactory.class);
19+
private final FHIRValidationModule validationModule = new FHIRValidationModule(config);
20+
21+
@Test
22+
void createsValidatorFactory() {
23+
ValidatorFactory factory = validationModule.provideValidatorFactory(cvf);
24+
assertInstanceOf(ValidatorFactory.class, factory);
25+
}
26+
27+
@Test
28+
void createsValidator() {
29+
FhirContext ctx = FhirContext.forDstu3();
30+
ValidationSupportChain chain = new ValidationSupportChain(
31+
new DefaultProfileValidationSupport(ctx),
32+
new InMemoryTerminologyServerValidationSupport(ctx));
33+
34+
FhirValidator validator = validationModule.provideFhirValidator(ctx, chain);
35+
assertInstanceOf(FhirValidator.class, validator);
36+
}
37+
}

0 commit comments

Comments
 (0)