From 886fa76ef2c14a21c2850a65cbe585c6df06af51 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Fri, 19 Jun 2015 16:08:35 -0400 Subject: [PATCH] Support ifNoneMatch in transaction request --- .../uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java | 29 +++++++++++- .../fhir/jpa/dao/FhirSystemDaoDstu2Test.java | 45 +++++++++++++++++++ src/changes/changes.xml | 3 ++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java index 906d8e5cc10..afe8f2e05e9 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java @@ -32,6 +32,7 @@ import java.util.Set; import javax.persistence.TypedQuery; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.springframework.jmx.access.InvalidInvocationException; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @@ -51,6 +52,7 @@ import ca.uhn.fhir.model.dstu2.valueset.IssueSeverityEnum; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.rest.method.MethodUtil; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; @@ -254,16 +256,37 @@ public class FhirSystemDaoDstu2 extends BaseFhirSystemDao { @SuppressWarnings("rawtypes") IFhirResourceDao resourceDao = parts.getDao(); + String ifNoneMatch = nextEntry.getTransaction().getIfNoneMatch(); + if (isNotBlank(ifNoneMatch)) { + ifNoneMatch = MethodUtil.parseETagValue(ifNoneMatch); + } + if (parts.getResourceId() != null && parts.getParams() == null) { IResource found; + boolean notChanged = false; if (parts.getVersionId() != null) { + if (isNotBlank(ifNoneMatch)) { + throw new InvalidRequestException("Unable to perform vread on '" + url + "' with ifNoneMatch also set. Do not include a version in the URL to perform a conditional read."); + } found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId(), parts.getVersionId())); } else { found = resourceDao.read(new IdDt(parts.getResourceType(), parts.getResourceId())); + if (isNotBlank(ifNoneMatch) && ifNoneMatch.equals(found.getId().getVersionIdPart())) { + notChanged = true; + } } - EntryTransactionResponse resp = response.addEntry().setResource(found).getTransactionResponse(); + Entry entry = response.addEntry(); + if (notChanged == false) { + entry.setResource(found); + } + EntryTransactionResponse resp = entry.getTransactionResponse(); resp.setLocation(found.getId().toUnqualified().getValue()); resp.setEtag(found.getId().getVersionIdPart()); + if (!notChanged) { + resp.setStatus(Integer.toString(Constants.STATUS_HTTP_200_OK)); + } else { + resp.setStatus(Integer.toString(Constants.STATUS_HTTP_304_NOT_MODIFIED)); + } } else if (parts.getParams() != null) { RuntimeResourceDefinition def = getContext().getResourceDefinition(parts.getDao().getResourceType()); SearchParameterMap params = translateMatchUrl(url, def); @@ -282,7 +305,9 @@ public class FhirSystemDaoDstu2 extends BaseFhirSystemDao { searchBundle.addEntry().setResource((IResource) next); } - response.addEntry().setResource(searchBundle); + Entry newEntry = response.addEntry(); + newEntry.setResource(searchBundle); + newEntry.getTransactionResponse().setStatus(Integer.toString(Constants.STATUS_HTTP_200_OK)); } } } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java index 5bd38e37d35..6afacf45aa1 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2Test.java @@ -558,6 +558,51 @@ public class FhirSystemDaoDstu2Test { assertEquals(1, respBundle.getTotal().intValue()); } + @Test + public void testTransactionReadWithIfNoneMatch() { + String methodName = "testTransactionReadWithIfNoneMatch"; + + Patient p = new Patient(); + p.addIdentifier().setSystem("urn:system").setValue(methodName); + p.setId("Patient/" + methodName); + IdDt idv1 = ourPatientDao.update(p).getId(); + ourLog.info("Created patient, got id: {}", idv1); + + p = new Patient(); + p.addIdentifier().setSystem("urn:system").setValue(methodName); + p.addName().addFamily("Family Name"); + p.setId("Patient/" + methodName); + IdDt idv2 = ourPatientDao.update(p).getId(); + ourLog.info("Updated patient, got id: {}", idv2); + + Bundle request = new Bundle(); + request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()); + request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv1.getVersionIdPart() + "\""); + request.addEntry().getTransaction().setMethod(HTTPVerbEnum.GET).setUrl(idv1.toUnqualifiedVersionless().getValue()).setIfNoneMatch("W/\"" + idv2.getVersionIdPart() + "\""); + + Bundle resp = ourSystemDao.transaction(request); + + assertEquals(4, resp.getEntry().size()); + + Entry nextEntry; + + nextEntry = resp.getEntry().get(1); + assertNotNull(nextEntry.getResource()); + assertEquals(Patient.class, nextEntry.getResource().getClass()); + assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified()); + assertEquals("200", nextEntry.getTransactionResponse().getStatus()); + + nextEntry = resp.getEntry().get(2); + assertNotNull(nextEntry.getResource()); + assertEquals(Patient.class, nextEntry.getResource().getClass()); + assertEquals(idv2.toUnqualified(), nextEntry.getResource().getId().toUnqualified()); + assertEquals("200", nextEntry.getTransactionResponse().getStatus()); + + nextEntry = resp.getEntry().get(3); + assertNull(nextEntry.getResource()); + assertEquals("304", nextEntry.getTransactionResponse().getStatus()); + } + @Test public void testTransactionUpdateMatchUrlWithOneMatch() { String methodName = "testTransactionUpdateMatchUrlWithOneMatch"; diff --git a/src/changes/changes.xml b/src/changes/changes.xml index adbd7828612..87a3a152785 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -108,6 +108,9 @@ Questionnaire.title now gets correctly indexed in JPA server (it has no path, so it is a special case) + + JPA server now supports ifNoneMatch in GET within a transaction request. +