hapifhir / hapi-fhir

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

$document operation doesn't include nested (inner) sections referenced resources in response #2660

Open ywangmaxmd opened 3 years ago

ywangmaxmd commented 3 years ago

Describe the bug When READ a composition with $document operation, the server supposes to generate a Document bundle that includes Composition and all referenced resources. However, the HAPI API doesn't include nested (inner) sections referenced resources in the Document bundle.

To Reproduce Steps to reproduce the behavior: http://hapi.fhir.org/baseR4/Composition/2111276/$document

{ "resourceType": "Bundle", "type": "document", "entry": [ { "resource": { "resourceType": "Composition", "id": "2111276", "meta": { "versionId": "1", "lastUpdated": "2021-05-17T20:24:04.911+00:00", "source": "#j9uSvJOUUTBx4JAG" }, "status": "final", "title": "Test Composition", "section": [ { "title": "Section A", "text": { "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Section A Text

" }, "entry": [ { "reference": "Observation/2111277", "display": "Observation A" } ], "section": [ { "title": "Inner Section", "text": { "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Inner Section Text
" }, "entry": [ { "reference": "Observation/2111278", "display": "Observation B" } ] } ] } ] } }, { "resource": { "resourceType": "Observation", "id": "2111277", "meta": { "versionId": "1", "lastUpdated": "2021-05-17T20:24:04.911+00:00", "source": "#j9uSvJOUUTBx4JAG" }, "text": { "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Obsevation A" } } } ] }

Observation B (Observation/2111278) isn't included in the response.

Environment (please complete the following information):

jamesagnew commented 3 years ago

Hi @ywangmaxmd - Thanks for the report with a linked test case. I'd agree with your assessment that HAPI FHIR isn't doing the right thing here.

Eernie commented 2 years ago

I've found out that if you add the line to the hfj_res_link table, then the document operation works as expected. Meaning that the save action does not work as I would expect. I've tried to understand what is going on. But it seems that the ca.uhn.fhir.context.ModelScanner#scanResource doesn't consider the section recursion as searchable/includable. I don't know how to fix this. But I believe this can be an easy fix, except for the unlimited recursion struggle.

The following is the content of the variable searchParams from method ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor#extractSearchParams

searchParams = {Collections$UnmodifiableCollection@25522}  size = 19
 0 = {RuntimeSearchParam@25526} "RuntimeSearchParam[base=[Composition],name=_id,path=,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-_id]"
 1 = {RuntimeSearchParam@25527} "RuntimeSearchParam[base=[Composition],name=attester,path=Composition.attester.party,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-attester]"
 2 = {RuntimeSearchParam@25528} "RuntimeSearchParam[base=[Composition],name=author,path=Composition.author,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-author]"
 3 = {RuntimeSearchParam@25529} "RuntimeSearchParam[base=[Composition],name=class,path=Composition.class,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-class]"
 4 = {RuntimeSearchParam@25530} "RuntimeSearchParam[base=[Composition],name=confidentiality,path=Composition.confidentiality,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-confidentiality]"
 5 = {RuntimeSearchParam@25531} "RuntimeSearchParam[base=[Composition],name=context,path=Composition.event.code,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-context]"
 6 = {RuntimeSearchParam@25532} "RuntimeSearchParam[base=[Composition],name=date,path=Composition.date,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-date]"
 7 = {RuntimeSearchParam@25533} "RuntimeSearchParam[base=[Composition],name=encounter,path=Composition.encounter,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-encounter]"
 8 = {RuntimeSearchParam@25534} "RuntimeSearchParam[base=[Composition],name=entry,path=Composition.section.entry,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-entry]"
 9 = {RuntimeSearchParam@25535} "RuntimeSearchParam[base=[Composition],name=identifier,path=Composition.identifier,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-identifier]"
 10 = {RuntimeSearchParam@25536} "RuntimeSearchParam[base=[Composition],name=patient,path=Composition.subject,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-patient]"
 11 = {RuntimeSearchParam@25537} "RuntimeSearchParam[base=[Composition],name=period,path=Composition.event.period,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-period]"
 12 = {RuntimeSearchParam@25538} "RuntimeSearchParam[base=[Composition],name=related-id,path=Composition.relatesTo.target.as(Identifier),id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-related-id]"
 13 = {RuntimeSearchParam@25539} "RuntimeSearchParam[base=[Composition],name=related-ref,path=Composition.relatesTo.target.as(Reference),id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-related-ref]"
 14 = {RuntimeSearchParam@25540} "RuntimeSearchParam[base=[Composition],name=section,path=Composition.section.code,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-section]"
 15 = {RuntimeSearchParam@25541} "RuntimeSearchParam[base=[Composition],name=status,path=Composition.status,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-status]"
 16 = {RuntimeSearchParam@25542} "RuntimeSearchParam[base=[Composition],name=subject,path=Composition.subject,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-subject]"
 17 = {RuntimeSearchParam@25466} "RuntimeSearchParam[base=[Composition],name=title,path=Composition.title,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-title]"
 18 = {RuntimeSearchParam@25543} "RuntimeSearchParam[base=[Composition],name=type,path=Composition.type,id=<null>,uri=http://hl7.org/fhir/SearchParameter/Composition-type]"

It has the Composition.section.entry path. But not the Composition.section.section.entry. But then again, how deep should it look? 🤔

Anyone know's how to fix this?

Eernie commented 2 years ago

In our server I was able to come up with a solution. It's not the best way to do this I guess, but it seems to be working correctly:

@ResourceDef(name = "Composition", profile = "http://hl7.org/fhir/Profile/Composition")
class RecursiveComposition : Composition() {
    @SearchParamDefinition(
        name = "recursive_entry",
        path = "Composition.section.section.entry",
        description = "A reference to data that supports this section",
        type = "reference"
    )
    @JvmField
    val SP_RECURSIVE_ENTRY = "entry"
}

And also overriding the entry resource.Composition=<FQN of class> in file org/hl7/fhir/dstu3/model/fhirversion.properties

@jamesagnew Any idea how to fix this in a propper way?