Extending the hapi-fhir-structures?

1,355 views
Skip to first unread message

adam.c...@villagerockinvestments.com

unread,
Jan 13, 2016, 11:20:23 AM1/13/16
to HAPI FHIR
We are looking to implement a FHIR server but also need to provide additional resources, IS there a way that we can generate our own structures the same way that the project does for the FHIR Specification? 

James Agnew

unread,
Jan 13, 2016, 11:58:30 AM1/13/16
to adam.c...@villagerockinvestments.com, HAPI FHIR
Hi Adam,

HAPI was deliberately designed to make this possible, so the good news is that yes it should absolutely be possible.

The easiest way to do this is to just create your own resource definition by hand. We don't yet have documentation on how to do this, but if you open the source for, say, the Patient resource (Patient.java) you will see that the resources are defined basically as a pojo with a few HAPI specific annotations added. You can create your own classes using these same annotations and HAPI will treat them as resources like any other.

In theory you could also create your definition by using the same spreadsheets that HL7 uses to define its resources. We use a maven plugin to automatically turn these into resource classes, but doing it this way would require some tweaking to the maven plugin I think in order to get it to accept arbitrary inputs.

Cheers,
James


On Wed, Jan 13, 2016 at 11:20 AM, <adam.c...@villagerockinvestments.com> wrote:
We are looking to implement a FHIR server but also need to provide additional resources, IS there a way that we can generate our own structures the same way that the project does for the FHIR Specification? 

--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+...@googlegroups.com.
To post to this group, send email to hapi...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/hapi-fhir/722a2731-3bb5-467f-8385-c89beaa5ad65%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Adam Carbone

unread,
Jan 13, 2016, 12:05:32 PM1/13/16
to HAPI FHIR, adam.c...@villagerockinvestments.com
Ok yes I had been looking at the maven tinder plugin and saw that these were generated resources and figured that was the only way to create a resource. So just by following the same basic model of an existing resource the restful server will "automagically" make them available? 

What about the JPA Providers I see that the plugin generates those as well, if I were to go the route of "tweaking" the plugin would that be an advantage that I would get the JPAProvider classes generated as well?

James Agnew

unread,
Jan 13, 2016, 12:09:44 PM1/13/16
to Adam Carbone, HAPI FHIR
Yup, the JPA generators (which generate the resource provider for JPA, as well as the spring config which includes all of the resourceproviders) could also be produced by tweaking the Maven plugin.

I think that to be honest, if I was trying to do what you're doing I would probably just manually create the resource class as well as the resource provider class. That seems like way less work than trying to create conformant spreadsheets and then trying to get the plugin to recognize them. The latter would be more useful to others though, since they could then take advantage of the updated plugin. It would also allow you to have non-programmers defining your custom resources, which could be a plus for you.

Cheers,
James


Adam Carbone

unread,
Jan 13, 2016, 12:16:09 PM1/13/16
to HAPI FHIR, adam.c...@villagerockinvestments.com
So I started with what you had suggested I copied Patient and am starting to create my own resource 'Note'

First thing I encounter are the following Annotations 

@ResourceDef(name="Patient", profile="http://hl7.org/fhir/profiles/Patient", id="patient")

@SearchParamDefinition(name="identifier", path="Patient.identifier", description="A patient identifier", type="token"  )

@Child(name="identifier", type=IdentifierDt.class, order=0, min=0, max=Child.MAX_UNLIMITED, summary=true, modifier=false)

@Description( shortDefinition="id", formalDefinition="An identifier for this patient" )

@Block()

I'm probably going to need to have some understanding to attempt to have any success at this. Is there a direction that you can point me even an API doc on the annotations to try to understand what these are used for?

Adam

Adam Carbone

unread,
Jan 13, 2016, 12:18:05 PM1/13/16
to HAPI FHIR, adam.c...@villagerockinvestments.com
I'm doing an evaluation and the ability to extend the resources will be a determining factor in whether we can use the library because we would rather not have to maintain two systems. 

James Agnew

unread,
Jan 13, 2016, 1:40:37 PM1/13/16
to Adam Carbone, HAPI FHIR
Hi Adam,

The JavaDocs for the annotations are all available on our usual spot here: http://jamesagnew.github.io/hapi-fhir/apidocs/index.html

For what it's worth:


@ResourceDef(name="Patient", profile="http://hl7.org/fhir/profiles/Patient", id="patient")
This is neccesary, but only name="" needs to be provided.

@SearchParamDefinition(name="identifier", path="Patient.identifier", description="A patient identifier", type="token"  )
This is used by JPA to determine which fields to index.

@Child(name="identifier", type=IdentifierDt.class, order=0, min=0, max=Child.MAX_UNLIMITED, summary=true, modifier=false)
Every field must have this populated.

@Description( shortDefinition="id", formalDefinition="An identifier for this patient" )
This is purely optional.

@Block()
Every child element that contains sub-elements is marked with this annotation.

Cheers,
James



Adam Carbone

unread,
Jan 13, 2016, 2:24:04 PM1/13/16
to HAPI FHIR, adam.c...@villagerockinvestments.com
Thank you for this... it seems like in the XXXResourceProvider these are standard boiler plate elements across all? 

@Description(shortDefinition="The resource identity")
@OptionalParam(name="_id")
StringAndListParam theId, 

@Description(shortDefinition="The resource language")
@OptionalParam(name="_language")
StringAndListParam theResourceLanguage, 

@Description(shortDefinition="Search the contents of the resource's data using a fulltext search")
@OptionalParam(name=ca.uhn.fhir.rest.server.Constants.PARAM_CONTENT)
StringAndListParam theFtContent, 

@Description(shortDefinition="Search the contents of the resource's narrative using a fulltext search")
@OptionalParam(name=ca.uhn.fhir.rest.server.Constants.PARAM_TEXT)
StringAndListParam theFtText, 

@Description(shortDefinition="Search for resources which have the given tag")
@OptionalParam(name=ca.uhn.fhir.rest.server.Constants.PARAM_TAG)
TokenAndListParam theSearchForTag, 

@Description(shortDefinition="Search for resources which have the given security labels")
@OptionalParam(name=ca.uhn.fhir.rest.server.Constants.PARAM_SECURITY)
TokenAndListParam theSearchForSecurity, 
  
@Description(shortDefinition="Search for resources which have the given profile")
@OptionalParam(name=ca.uhn.fhir.rest.server.Constants.PARAM_PROFILE)
UriAndListParam theSearchForProfile, 

Are there any more?

Adam Carbone

unread,
Jan 13, 2016, 2:27:24 PM1/13/16
to HAPI FHIR, adam.c...@villagerockinvestments.com
Seems like these are as well

@IncludeParam(reverse=true)
Set<Include> theRevIncludes,
@Description(shortDefinition="Only return resources which were last updated as specified by the given range")
@OptionalParam(name="_lastUpdated")
DateRangeParam theLastUpdated, 

@IncludeParam(allow= {
"Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "Observation:device" , "Observation:encounter" , "Observation:patient" , "Observation:performer" , "Observation:related-target" , "Observation:specimen" , "Observation:subject" , "*"
}) 
Set<Include> theIncludes,
@Sort 
SortSpec theSort,
@ca.uhn.fhir.rest.annotation.Count
Integer theCount

James Agnew

unread,
Jan 13, 2016, 2:30:37 PM1/13/16
to Adam Carbone, HAPI FHIR
Here's the template that they get generated from. It could be used as a hing for what gets repeated in each resource provider:

https://github.com/jamesagnew/hapi-fhir/blob/master/hapi-tinder-plugin/src/main/resources/vm/jpa_resource_provider.vm

Cheers,
James

Adam Carbone

unread,
Jan 13, 2016, 3:16:40 PM1/13/16
to HAPI FHIR, adam.c...@villagerockinvestments.com
So I'v had some moderate success with this doing as you suggested... 

The new resource can be seen on the FhirTesterOverlay application so it must be making it into the conformance document. But when I click on it I get the following exception:

ca.uhn.fhir.parser.DataFormatException: Unknown resource name "Note" (this name is not known in FHIR version "DSTU2")
	ca.uhn.fhir.context.FhirContext.getResourceDefinition(FhirContext.java:274)
	ca.uhn.fhir.to.Controller.actionResource(Controller.java:308)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	java.lang.reflect.Method.invoke(Unknown Source)
	org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
	org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
	org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
	org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:860)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	org.ebaysf.web.cors.CORSFilter.handleNonCORS(CORSFilter.java:437)
	org.ebaysf.web.cors.CORSFilter.doFilter(CORSFilter.java:172)

Not sure if it is the FhirTester app or the RestServer throwing the exception.

Regards,
Adam

James Agnew

unread,
Jan 13, 2016, 10:50:25 PM1/13/16
to Adam Carbone, HAPI FHIR
Ah, yeah, the testing overlay probably won't support your new resource type out of the box. That's good news you're getting this error I suppose, since it means that the server is properly exporting it.

It's probably worth trying to test the server independently of the testing web UI for now. If the server is working well, the next step will be the testing UI. It'll definitely be possible to get it working, but it'll need some tweaks to the tester itself first.

Cheers,
James

mohankrishna Machireddy

unread,
Feb 14, 2024, 5:33:07 PM2/14/24
to HAPI FHIR
I have a custom structure USCorePatientResource that extends Patient Resource, I have added few extensions to the Patient resource.
When I am testing from Postman, I am facing the same issue like yours.

ca.uhn.fhir.parser.DataFormatException: HAPI-1684: Unknown resource name "USCorePatient" (this name is not known in FHIR version "R4")

Could you tell me whether you found a way ?
Reply all
Reply to author
Forward
0 new messages