New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot parse custom ProcedureRequest with custom TimingDt #423

Closed
sjanic opened this Issue Aug 12, 2016 · 2 comments

Comments

Projects
None yet
2 participants
@sjanic
Contributor

sjanic commented Aug 12, 2016

I'm having an issue, where my custom ProcedureRequest cannot be parsed to JSON. I get the following exception:

Exception in thread "main" ca.uhn.fhir.parser.DataFormatException: scheduled has type com.sij.fhirbug.CustomTimingDt but this is not a valid type for this element - Expected one of: [class com.sij.fhirbug.CustomTimingDt]
    at ca.uhn.fhir.parser.BaseParser.throwExceptionForUnknownChildType(BaseParser.java:895)
    at ca.uhn.fhir.parser.BaseParser.getChildNameAndDef(BaseParser.java:436)
    at ca.uhn.fhir.parser.JsonParser.encodeCompositeElementChildrenToStreamWriter(JsonParser.java:615)
    at ca.uhn.fhir.parser.JsonParser.encodeCompositeElementToStreamWriter(JsonParser.java:764)
    at ca.uhn.fhir.parser.JsonParser.encodeResourceToJsonStreamWriter(JsonParser.java:900)
    at ca.uhn.fhir.parser.JsonParser.encodeResourceToJsonStreamWriter(JsonParser.java:803)
    at ca.uhn.fhir.parser.JsonParser.doEncodeResourceToWriter(JsonParser.java:214)
    at ca.uhn.fhir.parser.BaseParser.encodeResourceToWriter(BaseParser.java:365)
    at ca.uhn.fhir.parser.BaseParser.encodeResourceToString(BaseParser.java:349)
    at com.sij.fhirbug.CustomProcedureRequestMain.main(CustomProcedureRequestMain.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

I have made a reproducible example where I can provoke the exception. Given the following profiles:

CustomProcedureRequest.txt

CustomTimingDt.txt

And the following main program:
CustomProcedureRequestMain.txt

@sjanic

This comment has been minimized.

Show comment
Hide comment
@sjanic

sjanic Aug 12, 2016

Contributor

As to what the bug might be, I have an idea:
I debugged the ModelScanner.java, which from what I could tell is responsible for loading the FhirContext with the build-in and custom Resources and Datatypes. In the ModelScanner it splits the Resources and Datatypes to different RuntimeDefinitions it references later for parsing resources to XML, JSON etc.

When the RuntimeDefinitions are defined, a sealAndInitialize method is called to fill out the definition with the necessary Resource or Datatype information so it can be used later by the parsers.
The HAPI client encounters my CustomProcedureRequest, and defines its RuntimeDefinitions. When it gets to the scheduled field, the ModelScanner isn't aware of the scheduled's datatype CustomTimingDt, because we haven't encountered it yet, and cannot define it at that time. But since the RuntimeDefinition for scheduled is sealed afterwards, it can never update its definition, and the parser will fail with the above mentioned exception.

It seems that in RuntimeChildDeclaredExtensionDefinition.java we are aware of this:

@Override
void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
    myUrlToChildExtension = new HashMap<String, RuntimeChildDeclaredExtensionDefinition>();

    BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);

    /*
     * This will happen for any type that isn't defined in the base set of 
     * built-in types, e.g. custom structures or custom extensions
     */
    if (elementDef == null) {
        elementDef = theContext.getElementDefinition(myChildType);
    }

...

But not in RuntimeChildChoiceDefinition, which scheduled in CustomProcedureRequest gets defined as. @jamesagnew Could it be that some of the RuntimeDefinitions simply are missing this guard?

Contributor

sjanic commented Aug 12, 2016

As to what the bug might be, I have an idea:
I debugged the ModelScanner.java, which from what I could tell is responsible for loading the FhirContext with the build-in and custom Resources and Datatypes. In the ModelScanner it splits the Resources and Datatypes to different RuntimeDefinitions it references later for parsing resources to XML, JSON etc.

When the RuntimeDefinitions are defined, a sealAndInitialize method is called to fill out the definition with the necessary Resource or Datatype information so it can be used later by the parsers.
The HAPI client encounters my CustomProcedureRequest, and defines its RuntimeDefinitions. When it gets to the scheduled field, the ModelScanner isn't aware of the scheduled's datatype CustomTimingDt, because we haven't encountered it yet, and cannot define it at that time. But since the RuntimeDefinition for scheduled is sealed afterwards, it can never update its definition, and the parser will fail with the above mentioned exception.

It seems that in RuntimeChildDeclaredExtensionDefinition.java we are aware of this:

@Override
void sealAndInitialize(FhirContext theContext, Map<Class<? extends IBase>, BaseRuntimeElementDefinition<?>> theClassToElementDefinitions) {
    myUrlToChildExtension = new HashMap<String, RuntimeChildDeclaredExtensionDefinition>();

    BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(myChildType);

    /*
     * This will happen for any type that isn't defined in the base set of 
     * built-in types, e.g. custom structures or custom extensions
     */
    if (elementDef == null) {
        elementDef = theContext.getElementDefinition(myChildType);
    }

...

But not in RuntimeChildChoiceDefinition, which scheduled in CustomProcedureRequest gets defined as. @jamesagnew Could it be that some of the RuntimeDefinitions simply are missing this guard?

@jamesagnew

This comment has been minimized.

Show comment
Hide comment
@jamesagnew

jamesagnew Aug 14, 2016

Owner

Thanks for reporting! I was able to reproduce this, so I'm committing a fix shortly.

Owner

jamesagnew commented Aug 14, 2016

Thanks for reporting! I was able to reproduce this, so I'm committing a fix shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment