Hi everyone,
I am new to FHIR resources and encountering difficulties in getting started. Any guidance would be greatly appreciated, as I may be approaching this incorrectly by manually writing Java classes after failing to find a method to generate them from the resource definitions.
In Germany, "Gematik" has defined FHIR resources and profiles that I need to parse (both ways). While parsing global resources works without issues, I am encountering problems wherever Gematik has introduced extensions or modifications.
To extend resources, I followed the example/tutorial provided here:
https://hapifhir.io/hapi-fhir/docs/model/custom_structures.html
Initially, this seemed straightforward, but I have encountered two major issues that I cannot resolve:
Exception in thread "main" ca.uhn.fhir.context.ConfigurationException: HAPI-1705: Detected duplicate field name 'destination' in type 'de.carecloud.app.fhir.MessageHeaderAppTransport'
at ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition.scanCompositeElementForChildren(BaseRuntimeElementCompositeDefinition.java:367)
at ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition.scanCompositeElementForChildren(BaseRuntimeElementCompositeDefinition.java:206)
at ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition.sealAndInitialize(BaseRuntimeElementCompositeDefinition.java:557)
at ca.uhn.fhir.context.RuntimeResourceDefinition.sealAndInitialize(RuntimeResourceDefinition.java:199)
at ca.uhn.fhir.context.ModelScanner.init(ModelScanner.java:163)
at ca.uhn.fhir.context.ModelScanner.<init>(ModelScanner.java:98)
at ca.uhn.fhir.context.FhirContext.scanResourceTypes(FhirContext.java:1095)
at ca.uhn.fhir.context.FhirContext.validateInitialized(FhirContext.java:1213)
at ca.uhn.fhir.context.FhirContext.getResourceDefinition(FhirContext.java:498)
at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:646)
at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:722)
at de.carecloud.app.fhir.FhirPlayground.parsePrescriptionRequestToPrescriberCopy(FhirPlayground.java:574)
at de.carecloud.app.fhir.FhirPlayground.main(FhirPlayground.java:596)
Exception in thread "main" ca.uhn.fhir.parser.DataFormatException: HAPI-1851: DataFormatException at [[row,col {unknown-source}]: [51,13]]: HAPI-1814: Incorrect resource type found, expected "ErpServiceRequestRequestHeader" but found "MessageHeader"
at ca.uhn.fhir.parser.XmlParser.doXmlLoop(XmlParser.java:262)
at ca.uhn.fhir.parser.XmlParser.parseResource(XmlParser.java:999)
at ca.uhn.fhir.parser.XmlParser.doParseResource(XmlParser.java:171)
at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:653)
at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:722)
at de.carecloud.app.fhir.FhirPlayground.parsePrescriptionRequestToPrescriberCopy(FhirPlayground.java:575)
at de.carecloud.app.fhir.FhirPlayground.main(FhirPlayground.java:597)
Caused by: ca.uhn.fhir.parser.DataFormatException: HAPI-1814: Incorrect resource type found, expected "ErpServiceRequestRequestHeader" but found "MessageHeader"
at ca.uhn.fhir.parser.ParserState$BasePreResourceState.enteringNewElement(ParserState.java:1074)
at ca.uhn.fhir.parser.ParserState.enteringNewElement(ParserState.java:137)
at ca.uhn.fhir.parser.JsonParser.doParseResource(JsonParser.java:261)
at ca.uhn.fhir.parser.JsonParser.doParseResource(JsonParser.java:243)
at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:653)
at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:722)
at ca.uhn.fhir.parser.ParserState$BasePreResourceState.postProcess(ParserState.java:1162)
at ca.uhn.fhir.parser.ParserState$BasePreResourceState.wereBack(ParserState.java:1255)
at ca.uhn.fhir.parser.ParserState$PreResourceStateHl7Org.wereBack(ParserState.java:1333)
at ca.uhn.fhir.parser.ParserState.pop(ParserState.java:169)
at ca.uhn.fhir.parser.ParserState$ElementCompositeState.endingElement(ParserState.java:598)
at ca.uhn.fhir.parser.ParserState.endingElement(ParserState.java:133)
at ca.uhn.fhir.parser.XmlParser.doXmlLoop(XmlParser.java:242)
... 6 more
Minimal Code Example
My implementation is as follows (all imports are based on the R4 model, as Gematik builds upon it):
@ResourceDef(name = "MessageHeaderAppTransport", profile = "https://gematik.de/fhir/atf/StructureDefinition/message-header-app-transport")
public class MessageHeaderAppTransport extends MessageHeader {
@Child(name = "destination", min = 1, max = Child.MAX_UNLIMITED, type = { MessageDestinationComponent.class })
@Description(shortDefinition = "Angaben zum Empfänger der Nachricht", formalDefinition = "Angaben zum Empfänger der Nachricht")
@MustSupport(value = true)
private List<MessageDestinationComponent> destination;
}
@Block()
public static class MessageDestinationComponent extends MessageHeader.MessageDestinationComponent {
// TODO: Make Changes done by Gematik
}
@ResourceDef(name = "ErpServiceRequestRequestHeader", profile = "https://gematik.de/fhir/erp-servicerequest/StructureDefinition/erp-service-request-request-header")
public class ErpServiceRequestRequestHeader extends MessageHeaderAppTransport {
}
@ResourceDef(name = "Bundle", profile = "https://gematik.de/fhir/erp-servicerequest/StructureDefinition/erp-service-request-message-container")
public class ErpServiceRequestMessageContainer extends Bundle {
}
I then call the parser like this:
Note: The parsed xml is an example provided by Gematik here: https://simplifier.net/erezept-servicerequest/UC3-1-Prescription-Request-To-Prescriber-COPY/~xml
FhirContext ctx = FhirContext.forR4();
ctx.registerCustomType(ErpServiceRequestRequestHeader.class);
ctx.registerCustomType(ErpServiceRequestMessageContainer.class);
ctx.registerCustomType(MessageHeaderAppTransport.class);
ctx.registerCustomType(MessageHeaderAppTransport.MessageDestinationComponent.class);
ctx.setDefaultTypeForProfile("https://gematik.de/fhir/erp-servicerequest/StructureDefinition/erp-service-request-request-header", ErpServiceRequestRequestHeader.class);
ctx.setDefaultTypeForProfile("https://gematik.de/fhir/atf/StructureDefinition/message-header-app-transport", MessageHeaderAppTransport.class);
ctx.setDefaultTypeForProfile("https://gematik.de/fhir/erp-servicerequest/StructureDefinition/erp-service-request-message-container", ErpServiceRequestMessageContainer.class);
IParser parser = ctx.newXmlParser().setPrettyPrint(true);
var parsed = parser.parseResource(ErpServiceRequestMessageContainer.class, UC31PrescritiionRequestToPrescriberCopyEXAMPLE.xmlExample);