diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java
index 8ad4c34658a..a34b1f8f8c7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderDstu3Test.java
@@ -66,6 +66,7 @@ import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
+import ca.uhn.fhir.rest.api.ValidationModeEnum;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.Constants;
@@ -1720,10 +1721,18 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
assertEquals(id.withVersion("2").getValue(), history.getEntry().get(1).getResource().getId());
assertEquals(HTTPVerb.DELETE, history.getEntry().get(1).getRequest().getMethodElement().getValue());
+ assertEquals("http://localhost:" + ourPort + "/fhir/context/Patient/" + id.getIdPart() + "/_history/2", history.getEntry().get(1).getRequest().getUrl());
assertEquals(0, ((Patient) history.getEntry().get(1).getResource()).getName().size());
assertEquals(id.withVersion("1").getValue(), history.getEntry().get(2).getResource().getId());
assertEquals(1, ((Patient) history.getEntry().get(2).getResource()).getName().size());
+
+ try {
+ myBundleDao.validate(history, null, null, null, null, null, mySrd);
+ } catch (PreconditionFailedException e) {
+ ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
+ throw e;
+ }
}
/**
diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java
index 0855fefb090..602436df57a 100644
--- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java
+++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/hapi/rest/server/Dstu3BundleFactory.java
@@ -21,13 +21,7 @@ package org.hl7.fhir.dstu3.hapi.rest.server;
*/
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
+import java.util.*;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.model.Bundle;
@@ -35,25 +29,17 @@ import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Bundle.BundleLinkComponent;
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
import org.hl7.fhir.dstu3.model.Bundle.SearchEntryMode;
-import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.dstu3.model.DomainResource;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.Resource;
+import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
-import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.base.resource.BaseOperationOutcome;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
-import ca.uhn.fhir.rest.server.BundleInclusionRule;
-import ca.uhn.fhir.rest.server.Constants;
-import ca.uhn.fhir.rest.server.EncodingEnum;
-import ca.uhn.fhir.rest.server.IBundleProvider;
-import ca.uhn.fhir.rest.server.IPagingProvider;
-import ca.uhn.fhir.rest.server.IRestfulServer;
-import ca.uhn.fhir.rest.server.IVersionSpecificBundleFactory;
-import ca.uhn.fhir.rest.server.RestfulServerUtils;
+import ca.uhn.fhir.rest.server.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.ResourceReferenceInfo;
@@ -135,6 +121,7 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
String httpVerb = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(next);
if (httpVerb != null) {
entry.getRequest().getMethodElement().setValueAsString(httpVerb);
+ entry.getRequest().getUrlElement().setValue(next.getId());
}
}
@@ -161,7 +148,7 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
for (IBaseResource next : theResult) {
if (next.getIdElement().isEmpty() == false) {
- addedResourceIds.add((IdType) next.getIdElement());
+ addedResourceIds.add(next.getIdElement());
}
}
@@ -221,11 +208,14 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
BundleEntryComponent entry = myBundle.addEntry().setResource((Resource) next);
Resource nextAsResource = (Resource)next;
+ IIdType id = populateBundleEntryFullUrl(next, entry);
String httpVerb = ResourceMetadataKeyEnum.ENTRY_TRANSACTION_METHOD.get(nextAsResource);
if (httpVerb != null) {
entry.getRequest().getMethodElement().setValueAsString(httpVerb);
+ if (id != null) {
+ entry.getRequest().setUrl(id.getValue());
+ }
}
- populateBundleEntryFullUrl(next, entry);
String searchMode = ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(nextAsResource);
if (searchMode != null) {
@@ -244,16 +234,19 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
}
- private void populateBundleEntryFullUrl(IBaseResource next, BundleEntryComponent entry) {
+ private IIdType populateBundleEntryFullUrl(IBaseResource next, BundleEntryComponent entry) {
+ IIdType idElement = null;
if (next.getIdElement().hasBaseUrl()) {
- entry.setFullUrl(next.getIdElement().toVersionless().getValue());
+ idElement = next.getIdElement();
+ entry.setFullUrl(idElement.toVersionless().getValue());
} else {
if (isNotBlank(myBase) && next.getIdElement().hasIdPart()) {
- IIdType id = next.getIdElement().toVersionless();
- id = id.withServerBase(myBase, myContext.getResourceDefinition(next).getName());
- entry.setFullUrl(id.getValue());
+ idElement = next.getIdElement();
+ idElement = idElement.withServerBase(myBase, myContext.getResourceDefinition(next).getName());
+ entry.setFullUrl(idElement.toVersionless().getValue());
}
}
+ return idElement;
}
@Override
@@ -392,7 +385,7 @@ public class Dstu3BundleFactory implements IVersionSpecificBundleFactory {
Resource next = (Resource) nextBaseRes;
BundleEntryComponent nextEntry = myBundle.addEntry();
- nextEntry.setResource((Resource) next);
+ nextEntry.setResource(next);
if (next.getIdElement().isEmpty()) {
nextEntry.getRequest().setMethod(HTTPVerb.POST);
} else {
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d8e56d94f25..ebd29ae6a7c 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -81,6 +81,11 @@
DELETE fails because of constraint issues, instead of
HTTP 400 Invalid Request]]>
+
+ Server history operation did not populate the Bundle.entry.request.url
+ field, which is required in order for the bundle to pass validation.
+ Thanks to Richard Kavanaugh for spotting this!
+