hapifhir / hapi-fhir

🔥 HAPI FHIR - Java API for HL7 FHIR Clients and Servers
http://hapifhir.io
Apache License 2.0
1.98k stars 1.3k forks source link

AutoContainReferenceTargetsWithNoId (5.7.0) default true results in "HAPI-1826: Resource has invalid reference: #1" #3415

Open tyfoni-systematic opened 2 years ago

tyfoni-systematic commented 2 years ago

Describe the bug When we upgrade from hapi-fhir 5.4.0 to 5.7.0 our creation of careplan fail with "HAPI-1826: Resource has invalid reference: #1". The careplan that are returned has a servicerequest in activity.reference, and we expected a proper reference to the servicerequest resource, but instead we get a reference (#1) to a contained resource with mismatched id.

After setting AutoContainReferenceTargetsWithNoId to false, the request returns a valid careplan (and no contained resource).

To Reproduce Steps to reproduce the behavior:

  1. Create a transaction bundle with careplan and servicerequest
  2. Execute the transactin bundle
  3. Validate the returned careplan
  4. See error: HAPI-1826: Resource has invalid reference: #1

Expected behavior With AutoContainReferenceTargetsWithNoId set to true, the resulting resource should not have referential integrity issues with the contained resource

Environment (please complete the following information):

Additional context The returned careplan (xml) with referential integrity issue: `

`

tyfoni-systematic commented 2 years ago

I can workaround this issue by carefully ordering my transaction bundle (POST) in reverse dependency order. Then resources have been created when the BaseSearchParamExtractor.cleanUpContainedResourceReferences tries to autocontain resources. The decision is then to set a proper reference instead of containing the resource.

My bundle contains the following resources:

  1. CarePlan (root) - activity -> {ServiceRequest (1)}
  2. ServiceRequest (1) - partOf -> CarePlan (root)
  3. CarePlan (sub) - activity -> {ServiceRequest (2), ServiceRequest (3)}
  4. ServiceRequest (2)
  5. ServiceRequest (3)

To workaround I must reorder the bundle: My bundle contains the following resources:

  1. ServiceRequest (1) - partOf -> CarePlan (root)
  2. CarePlan (root) - activity -> {ServiceRequest (1)}
  3. ServiceRequest (2)
  4. ServiceRequest (3)
  5. CarePlan (sub) - activity -> {ServiceRequest (2), ServiceRequest (3)}

Previously (hapi 5.4.0), it was not required to have a specific ordering of a transaction bundle, so I believe that the behaviour in 5.7.0 is a bug.

The problem seems to be in:

    private void cleanUpContainedResourceReferences(IBaseResource theResource, RestSearchParameterTypeEnum theSearchParamType, Collection<RuntimeSearchParam> searchParams) {
        boolean havePathWithResolveExpression =
            myModelConfig.isIndexOnContainedResources()
                || anySearchParameterUsesResolve(searchParams, theSearchParamType);

        if (havePathWithResolveExpression && myContext.getParserOptions().isAutoContainReferenceTargetsWithNoId()) {
            //TODO GGG/JA: At this point, if the Task.basedOn.reference.resource does _not_ have an ID, we will attempt to contain it internally. Wild
            myContext.newTerser().containResources(theResource, FhirTerser.OptionsEnum.MODIFY_RESOURCE, FhirTerser.OptionsEnum.STORE_AND_REUSE_RESULTS);
        }
    }