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

How do I best return a TerminologyCapabilities resource? #1681

Open pgwilliams opened 4 years ago

pgwilliams commented 4 years ago

Hi @jamesagnew, thank you for this project, it's awesome.

Describe the issue I have a FHIR Server which implements various ResourceProviders which are working fine. I appreciate that the HAPI framework generates my CapabilityStatement for me, but I now want to also return a TerminologyCapabilities resource when the mode=terminology parameter is detected on the metadata request. I've tried a few things, but I'm stuck and would appreciate it - if you'd foreseen someone wanting to do this - is there a suggested "best" way to return one of these objects?

Environment (please complete the following information):

Additional context Here's the code I've written. The @Metadata tag causes all requests for metadata to come through the function it annotates, so I believe it has to return either a ServerCapabilities or a TerminologyCapabilities resource depending on the mode parameter. The common parent of these two resources is a MetadataResource which I've coded below, but at runtime I get told Failure scanning class FHIRTerminologyCapabilitiesProvider: Conformance resource provider method 'getConformance' should return a Conformance resource class, returns: class org.hl7.fhir.r4.model.MetadataResource

` public class FHIRTerminologyCapabilitiesProvider extends ServerCapabilityStatementProvider {

@Metadata
public MetadataResource getConformance(HttpServletRequest request, RequestDetails requestDetails) {
    if (request.getParameter("mode") != null && request.getParameter("mode").equals("terminology")) {
        return getTerminologyCapabilities();
    } else {
        return super.getServerConformance(request, requestDetails);
    }
}

private TerminologyCapabilities getTerminologyCapabilities() {
    TerminologyCapabilities tc = new TerminologyCapabilities();
    return tc;
}

} ` Thanks! Peter

pgwilliams commented 4 years ago

Ah, I thought I had this working because my unit test passed but it turns out that the response is cached and whatever I request first, either passing in mode=terminology or not, I get the same thing back any subsequent time until the cache expires.

I see the setCache method on the ServerCapabilityStatementProvider is deprecated (does nothing) and I can't see how to set the timeout to zero. Even if I could, I'd rather not because the cache is a Good Thing....or would be if I could work out how & where to provide that switch for the "mode" parameter?

kaicode commented 3 months ago

This is still an issue for us. Could anyone provide pointers for us to fix our open source terminology server?

kaicode commented 3 months ago

It's possible to work around the caching by:

However the next blocker to returning TerminologyCapabilities is that HAPI seems to need a "format" property on the MetadataResource being returned from our getConformance method.

Getting this error when returning an object who's class extends org.hl7.fhir.r4.model.TerminologyCapabilities:

{
  "resourceType": "OperationOutcome",
  "issue": [ {
    "severity": "error",
    "code": "processing",
    "diagnostics": "HAPI-1700: Unknown child name 'format' in element TerminologyCapabilities - Valid names are: [closure, codeSearch, codeSystem, contact, contained, copyright, date, description, expansion, experimental, extension, extension[x], id, implementation, implicitRules, jurisdiction, kind, language, lockedDate, meta, modifierExtension, modifierExtension[x], name, publisher, purpose, software, status, text, title, translation, url, useContext, validateCode, version]"
  } ]
}

Stack trace:

2024-08-06T22:28:58.954+01:00 ERROR 63010 --- [io-8080-exec-10] c.u.f.r.s.i.ExceptionHandlingInterceptor : Failure during REST processing: ca.uhn.fhir.parser.DataFormatException: HAPI-1700: Unknown child name 'format' in element TerminologyCapabilities - Valid names are: [closure, codeSearch, codeSystem, contact, contained, copyright, date, description, expansion, experimental, extension, extension[x], id, implementation, implicitRules, jurisdiction, kind, language, lockedDate, meta, modifierExtension, modifierExtension[x], name, publisher, purpose, software, status, text, title, translation, url, useContext, validateCode, version]

ca.uhn.fhir.parser.DataFormatException: HAPI-1700: Unknown child name 'format' in element TerminologyCapabilities - Valid names are: [closure, codeSearch, codeSystem, contact, contained, copyright, date, description, expansion, experimental, extension, extension[x], id, implementation, implicitRules, jurisdiction, kind, language, lockedDate, meta, modifierExtension, modifierExtension[x], name, publisher, purpose, software, status, text, title, translation, url, useContext, validateCode, version]
    at ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition.getChildByNameOrThrowDataFormatException(BaseRuntimeElementCompositeDefinition.java:160)
    at ca.uhn.fhir.util.FhirTerser.getValues(FhirTerser.java:632)
    at ca.uhn.fhir.util.FhirTerser.getValues(FhirTerser.java:423)
    at ca.uhn.fhir.util.FhirTerser.getValues(FhirTerser.java:753)
    at ca.uhn.fhir.rest.server.interceptor.ResponseHighlighterInterceptor.capabilityStatementGenerated(ResponseHighlighterInterceptor.java:483)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at ca.uhn.fhir.interceptor.executor.BaseInterceptorService$HookInvoker.invoke(BaseInterceptorService.java:550)
    at ca.uhn.fhir.interceptor.executor.BaseInterceptorService.doCallHooks(BaseInterceptorService.java:287)
    at ca.uhn.fhir.interceptor.executor.BaseInterceptorService.callHooksAndReturnObject(BaseInterceptorService.java:258)
    at ca.uhn.fhir.interceptor.executor.BaseInterceptorService.callHooksAndReturnObject(BaseInterceptorService.java:63)
    at ca.uhn.fhir.rest.server.method.ConformanceMethodBinding.createCapabilityStatement(ConformanceMethodBinding.java:196)
    at ca.uhn.fhir.rest.server.method.ConformanceMethodBinding.invokeServer(ConformanceMethodBinding.java:179)
    at ca.uhn.fhir.rest.server.method.ConformanceMethodBinding.invokeServer(ConformanceMethodBinding.java:54)
    at ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding.doInvokeServer(BaseResourceReturningMethodBinding.java:146)
    at ca.uhn.fhir.rest.server.method.BaseResourceReturningMethodBinding.invokeServer(BaseResourceReturningMethodBinding.java:275)
    at ca.uhn.fhir.rest.server.RestfulServer.handleRequest(RestfulServer.java:1198)
    at ca.uhn.fhir.rest.server.RestfulServer.doGet(RestfulServer.java:424)
    at ca.uhn.fhir.rest.server.RestfulServer.service(RestfulServer.java:1931)
    at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:174)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:149)
kaicode commented 3 months ago

Code here: https://github.com/IHTSDO/snowstorm/blob/10.3.1/src/main/java/org/snomed/snowstorm/fhir/services/FHIRTerminologyCapabilitiesProvider.java#L36

kaicode commented 1 week ago

I have now worked out how to do this. We can prevent the error above by extending the ResponseHighlighterInterceptor and only calling capabilityStatementGenerated if the IBaseConformance theCapabilityStatement is of type CapabilityStatement..

I also used @Metadata(cacheMillis = 0) in the ServerCapabilityStatementProvider to prevent caching.

Full set of changes here: https://github.com/IHTSDO/snowstorm-x/commit/31c28bc87322817bf28efed42a7030f18316056e

kaicode commented 1 week ago

This issue can be closed as resolved.