From 0a160a35baf4cf099109cb2ada4c867b36c77036 Mon Sep 17 00:00:00 2001 From: karneet1212 <112980019+karneet1212@users.noreply.github.com> Date: Wed, 26 Oct 2022 13:29:28 -0400 Subject: [PATCH] 4175-$validate-operation-on-a-resource-update-results-in-an-error-stating-resource-has-no-id (#4181) * Added unit test + solution * Changelog * Cleanup * changelog filename --- ...n-an-error-stating-resource-has-no-id.yaml | 7 +++++ .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 11 ++++++- .../dao/r4/FhirResourceDaoR4ValidateTest.java | 29 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4175-validate-operation-on-a-resource-update-results-in-an-error-stating-resource-has-no-id.yaml diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4175-validate-operation-on-a-resource-update-results-in-an-error-stating-resource-has-no-id.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4175-validate-operation-on-a-resource-update-results-in-an-error-stating-resource-has-no-id.yaml new file mode 100644 index 00000000000..8734c865ad9 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_2_0/4175-validate-operation-on-a-resource-update-results-in-an-error-stating-resource-has-no-id.yaml @@ -0,0 +1,7 @@ +--- +type: fix +issue: 4175 +jira: SMILE-4872 +title: "Previously, performing $validate operation on resource update and sending the resource as a + parameter in the request body would result in an error stating that the resource was missing id. + This has been fixed by allowing the resource to be processed correctly when sent as a parameter." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 635d64dc2a1..6c33e2909ea 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -122,6 +122,8 @@ import org.hl7.fhir.instance.model.api.IBaseParameters; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.Parameters.ParametersParameterComponent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Required; import org.springframework.transaction.PlatformTransactionManager; @@ -135,6 +137,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.PostConstruct; import javax.persistence.NoResultException; +import javax.persistence.Parameter; import javax.persistence.TypedQuery; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -2024,7 +2027,13 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public void validateResource(IValidationContext theCtx) { - boolean hasId = theCtx.getResource().getIdElement().hasIdPart(); + IBaseResource resource = theCtx.getResource(); + if (resource instanceof Parameters) { + List params = ((Parameters) resource).getParameter(); + params = params.stream().filter(param -> param.getName().contains("resource")).collect(Collectors.toList()); + resource = params.get(0).getResource(); + } + boolean hasId = resource.getIdElement().hasIdPart(); if (myMode == ValidationModeEnum.CREATE) { if (hasId) { throw new UnprocessableEntityException(Msg.code(997) + "Resource has an ID - ID must not be populated for a FHIR create"); diff --git a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java index 68cd5ad1fdd..66e75b16249 100644 --- a/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java +++ b/hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4ValidateTest.java @@ -57,6 +57,7 @@ import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Observation.ObservationStatus; import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.Quantity; @@ -1633,6 +1634,34 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test { } + @Test + public void testValidateRawResourceForUpdateWithId() { + String methodName = "testValidateForUpdate"; + Patient pat = new Patient(); + pat.setId("Patient/123"); + pat.addName().setFamily(methodName); + Parameters params = new Parameters(); + params.addParameter().setName("resource").setResource(pat); + String rawResource = myFhirContext.newJsonParser().encodeResourceToString(params); + myPatientDao.validate(pat, null, rawResource, EncodingEnum.JSON, ValidationModeEnum.UPDATE, null, mySrd); + } + @Test + public void testValidateRawResourceForUpdateWithNoId() { + String methodName = "testValidateForUpdate"; + Patient pat = new Patient(); + pat.addName().setFamily(methodName); + Parameters params = new Parameters(); + params.addParameter().setName("resource").setResource(pat); + String rawResource = myFhirContext.newJsonParser().encodeResourceToString(params); + try { + myPatientDao.validate(pat, null, rawResource, EncodingEnum.JSON, ValidationModeEnum.UPDATE, null, mySrd); + fail(); + } catch (UnprocessableEntityException e) { + assertThat(e.getMessage(), containsString("ID must be populated")); + } + + } + @Test public void testValidateForUpdateWithContained() { String methodName = "testValidateForUpdate";