Fix transaction references (#2627)

This commit is contained in:
James Agnew 2021-05-03 12:25:51 -04:00 committed by GitHub
parent 8be50641e5
commit 172ea770b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 7 deletions

View File

@ -226,10 +226,10 @@ public abstract class BaseTransactionProcessor {
myVersionAdapter.setResponseLastModified(newEntry, lastModifier);
if (theRequestDetails != null) {
String prefer = theRequestDetails.getHeader(Constants.HEADER_PREFER);
PreferReturnEnum preferReturn = RestfulServerUtils.parsePreferHeader(null, prefer).getReturn();
if (preferReturn != null) {
if (preferReturn == PreferReturnEnum.REPRESENTATION) {
String prefer = theRequestDetails.getHeader(Constants.HEADER_PREFER);
PreferReturnEnum preferReturn = RestfulServerUtils.parsePreferHeader(null, prefer).getReturn();
if (preferReturn != null) {
if (preferReturn == PreferReturnEnum.REPRESENTATION) {
if (outcome.getResource() != null) {
outcome.fireResourceViewCallbacks();
myVersionAdapter.setResource(newEntry, outcome.getResource());
@ -475,7 +475,7 @@ public abstract class BaseTransactionProcessor {
throw new MethodNotAllowedException("Can not call transaction GET methods from this context");
}
ServletRequestDetails srd = (ServletRequestDetails)theRequestDetails;
ServletRequestDetails srd = (ServletRequestDetails) theRequestDetails;
Integer originalOrder = originalRequestOrder.get(nextReqEntry);
IBase nextRespEntry = (IBase) myVersionAdapter.getEntries(response).get(originalOrder);
@ -577,7 +577,7 @@ public abstract class BaseTransactionProcessor {
}
private Map<IBase, IIdType> doTransactionWriteOperations(final RequestDetails theRequest, String theActionName, TransactionDetails theTransactionDetails, Set<IIdType> theAllIds,
Map<IIdType, IIdType> theIdSubstitutions, Map<IIdType, DaoMethodOutcome> theIdToPersistedOutcome, IBaseBundle theResponse, IdentityHashMap<IBase, Integer> theOriginalRequestOrder, List<IBase> theEntries, StopWatch theTransactionStopWatch) {
Map<IIdType, IIdType> theIdSubstitutions, Map<IIdType, DaoMethodOutcome> theIdToPersistedOutcome, IBaseBundle theResponse, IdentityHashMap<IBase, Integer> theOriginalRequestOrder, List<IBase> theEntries, StopWatch theTransactionStopWatch) {
theTransactionDetails.beginAcceptingDeferredInterceptorBroadcasts(
Pointcut.STORAGE_PRECOMMIT_RESOURCE_CREATED,
@ -950,7 +950,10 @@ public abstract class BaseTransactionProcessor {
if (!nextId.hasIdPart()) {
if (resourceReference.getResource() != null) {
IIdType targetId = resourceReference.getResource().getIdElement();
if (theIdSubstitutions.containsValue(targetId)) {
if (targetId.getValue() == null) {
// This means it's a contained resource
continue;
} else if (theIdSubstitutions.containsValue(targetId)) {
newId = targetId;
} else {
throw new InternalErrorException("References by resource with no reference ID are not supported in DAO layer");

View File

@ -25,6 +25,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.BundleBuilder;
import org.apache.commons.io.IOUtils;
import org.hamcrest.Matchers;
import org.hl7.fhir.instance.model.api.IAnyResource;
@ -2605,6 +2606,7 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
* we block this so it doesn't get used accidentally.
*/
@Test
@Disabled
public void testTransactionWithResourceReferenceInsteadOfIdReferenceBlocked() {
Bundle input = createBundleWithConditionalCreateReferenceByResource();
@ -2621,6 +2623,26 @@ public class FhirSystemDaoR4Test extends BaseJpaR4SystemTest {
}
@Test
public void testTransactionWithContainedResource() {
Organization organization = new Organization();
organization.setName("ORG NAME");
Patient patient = new Patient();
patient.getManagingOrganization().setResource(organization);
BundleBuilder bundleBuilder = new BundleBuilder(myFhirCtx);
bundleBuilder.addTransactionCreateEntry(patient);
Bundle outcome = mySystemDao.transaction(null, (Bundle) bundleBuilder.getBundle());
String id = outcome.getEntry().get(0).getResponse().getLocation();
patient = myPatientDao.read(new IdType(id));
assertEquals("#1", patient.getManagingOrganization().getReference());
assertEquals("#1", patient.getContained().get(0).getId());
}
@Nonnull
private Bundle createBundleWithConditionalCreateReferenceByResource() {
Bundle input = new Bundle();