Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions dpc-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,6 @@
<artifactId>hapi-fhir-validation-resources-dstu3</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${hapi.fhir.groupID}</groupId>
<artifactId>hapi-fhir-caching-caffeine</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
Expand All @@ -132,9 +127,8 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.3</version>
<groupId>${hapi.fhir.groupID}</groupId>
<artifactId>hapi-fhir-caching-caffeine</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
Expand Down
5 changes: 2 additions & 3 deletions dpc-api/src/test/java/gov/cms/dpc/api/APITestHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import gov.cms.dpc.fhir.dropwizard.handlers.exceptions.PersistenceExceptionHandler;
import gov.cms.dpc.fhir.validations.DPCProfileSupport;
import gov.cms.dpc.fhir.validations.ProfileValidator;
import gov.cms.dpc.fhir.validations.dropwizard.FHIRValidatorProvider;
import gov.cms.dpc.fhir.validations.dropwizard.FHIRValidationModule;
import gov.cms.dpc.fhir.validations.dropwizard.InjectingConstraintValidatorFactory;
import gov.cms.dpc.testing.APIAuthHelpers;
import gov.cms.dpc.testing.factories.FHIRPatientBuilder;
Expand Down Expand Up @@ -63,7 +63,6 @@ public class APITestHelpers {
private static final String ATTRIBUTION_TRUNCATE_TASK = "http://localhost:9902/tasks/truncate";
private static final String CONSENT_TRUNCATE_TASK = "http://localhost:9901/tasks/truncate";
public static String ORGANIZATION_NPI = "1111111112";

private static final String configPath = "src/test/resources/test.application.yml";

private APITestHelpers() {
Expand Down Expand Up @@ -166,7 +165,7 @@ public static ResourceExtension buildResourceExtension(FhirContext
new DefaultProfileValidationSupport(ctx),
new InMemoryTerminologyServerValidationSupport(ctx));
final InjectingConstraintValidatorFactory constraintFactory = new InjectingConstraintValidatorFactory(
Set.of(new ProfileValidator(new FHIRValidatorProvider(ctx, config, support).get())));
Set.of(new ProfileValidator(new FHIRValidationModule(config).provideFhirValidator(ctx, support))));

builder.setValidator(provideValidator(constraintFactory));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ static Stream<Arguments> downloadArgs() {
@ParameterizedTest
@MethodSource("downloadArgs")
void canDownloadFiles(boolean compressFile, Map<String, String> requestHeaders) throws IOException {
String testData = "test data".repeat(500);
String testData = "test data".repeat(50);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reduced this because the test is still occasionally failing due to resource limitations.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @MEspositoE14s, instead of using .repeat(50) here, why not just pass an example thats closer to what the data would look like?

String fileName = createTestExport(testData, compressFile);

try (ClassicHttpResponse response = downloadExport(fileName, requestHeaders)) {
Expand Down
4 changes: 4 additions & 0 deletions dpc-attribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@
<groupId>ru.vyarus</groupId>
<artifactId>dropwizard-guicey</artifactId>
</dependency>
<dependency>
<groupId>${hapi.fhir.groupID}</groupId>
<artifactId>hapi-fhir-caching-caffeine</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,40 @@
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationOptions;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.multibindings.Multibinder;
import gov.cms.dpc.fhir.DPCIdentifierSystem;
import gov.cms.dpc.fhir.configuration.DPCFHIRConfiguration.FHIRValidationConfiguration;
import gov.cms.dpc.fhir.validations.DPCProfileSupport;
import gov.cms.dpc.fhir.validations.ProfileValidator;
import gov.cms.dpc.fhir.validations.profiles.PatientProfile;
import io.dropwizard.jersey.validation.Validators;
import jakarta.inject.Singleton;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorFactory;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import org.glassfish.jersey.server.internal.inject.ConfiguredValidator;
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
import org.hl7.fhir.dstu3.model.Enumerations;
import org.hl7.fhir.dstu3.model.Patient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Date;


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

private final FHIRValidationConfiguration config;

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

bind(ConstraintValidatorFactory.class).to(InjectingConstraintValidatorFactory.class);
bind(ValidatorFactory.class).toProvider(ValidatorFactoryProvider.class);
bind(ConfiguredValidator.class).to(InjectingConfiguredValidator.class);

bind(DPCProfileSupport.class).in(Scopes.SINGLETON);
bind(FhirValidator.class).toProvider(FHIRValidatorProvider.class);
Comment on lines -44 to -48
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we no longer need ValidatorFactory.class and FhirValidator.class?

}

@Provides
Expand All @@ -58,6 +69,14 @@ Validator provideValidator(ValidatorFactory factory) {
return factory.getValidator();
}

@Provides
@Singleton
ValidatorFactory provideValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
return Validators.newConfiguration()
.constraintValidatorFactory(constraintValidatorFactory)
.buildValidatorFactory();
}

@Provides
ValidationSupportChain provideSupportChain(DPCProfileSupport dpcModule) {
FhirContext ctx = FhirContext.forDstu3();
Expand All @@ -66,4 +85,39 @@ ValidationSupportChain provideSupportChain(DPCProfileSupport dpcModule) {
new DefaultProfileValidationSupport(ctx),
new InMemoryTerminologyServerValidationSupport(ctx));
}

@Provides
@Singleton
public FhirValidator provideFhirValidator(FhirContext ctx,
ValidationSupportChain supportChain) {
final FhirValidator fhirValidator = ctx.newValidator();
final FhirInstanceValidator instanceValidator = new FhirInstanceValidator(supportChain);

fhirValidator.registerValidatorModule(instanceValidator);
primeValidator(fhirValidator);

return fhirValidator;
}

/**
* Helper method that primes the Validator cache by creating a dummy patient and validating it.
* This is really dumb, but it avoids issues where the tests timeout when running in CI.
* Is necessary in order to address DPC-608
* <p>
* We may need to add more resources here in the future, if things continue to be slow.
*
* @param validator - {@link FhirValidator} validator to prime
*/
private void primeValidator(FhirValidator validator) {
logger.trace("Validating dummy patient");
final Patient patient = new Patient();
patient.addName().addGiven("Dummy").setFamily("Patient");
patient.addIdentifier().setSystem(DPCIdentifierSystem.MBI.getSystem()).setValue("test-mbi");
patient.setGender(Enumerations.AdministrativeGender.MALE);
patient.setBirthDate(Date.valueOf("1990-01-01"));

final ValidationOptions op = new ValidationOptions();
op.addProfile(PatientProfile.PROFILE_URI);
validator.validateWithResult(patient, op);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package gov.cms.dpc.fhir.dropwizard.filters;

import gov.cms.dpc.fhir.FHIRMediaTypes;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.UriInfo;
import org.eclipse.jetty.server.Response;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

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

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

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

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

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

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

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

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

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

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

@Test
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package gov.cms.dpc.fhir.validations.dropwizard;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.validation.FhirValidator;
import gov.cms.dpc.fhir.configuration.DPCFHIRConfiguration;
import jakarta.validation.ConstraintValidatorFactory;
import jakarta.validation.ValidatorFactory;
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.mockito.Mockito.mock;

class FHIRValidationModuleUnitTest {
private final DPCFHIRConfiguration.FHIRValidationConfiguration config = mock(DPCFHIRConfiguration.FHIRValidationConfiguration.class);
private final ConstraintValidatorFactory cvf = mock(ConstraintValidatorFactory.class);
private final FHIRValidationModule validationModule = new FHIRValidationModule(config);

@Test
void createsValidatorFactory() {
ValidatorFactory factory = validationModule.provideValidatorFactory(cvf);
assertInstanceOf(ValidatorFactory.class, factory);
}

@Test
void createsValidator() {
FhirContext ctx = FhirContext.forDstu3();
ValidationSupportChain chain = new ValidationSupportChain(
new DefaultProfileValidationSupport(ctx),
new InMemoryTerminologyServerValidationSupport(ctx));

FhirValidator validator = validationModule.provideFhirValidator(ctx, chain);
assertInstanceOf(FhirValidator.class, validator);
}
}
Loading
Loading