How-to's
10 Min Read

Custom Resources in Firely Server

Christiaan Knaap
Christiaan Knaap

Subscribe to our newsletter

Subscribe

TL;DR;

Firely Server supports Custom Resources. Define your own resource types, store and validate them in Firely Server just like any other resource. Be wary: don’t try to exchange them with others.

What are Custom Resources?

Custom Resources in this blog and to Firely Server are resources of a ResourceType not defined in the FHIR Specification. However, they are normal resources. This means that they are defined by a StructureDefinition and are a specialization of DomainResource. They have all the usual common elements like an id, narrative, etc.

When (not) to use Custom Resources?

“Een ander begrijpt niks van jouw zelf gedefinieerde blokken.”

Did you understand the line above? Yes? You must be Dutch or you used Google Translate. Either way, if you want to be interoperable you need to use a common language. And not a custom one. In the same way, Custom Resources are not for interoperability. Keep that in mind.

The intended use is simple. When you use Firely Server as the platform for an application, there is sometimes that 10% of data that won’t fit any of the FHIR resources. It would be very inefficient to use a second database for that 10%. Therefore, we decided to allow you to structure that data just like any official ResourceType, and store it in Firely Server just like any other resource. The below blog post will show you exactly how to do that.

The official FHIR way to structure data not defined as a ResourceType is to use the ResourceType Basic and add extensions for any data that needs to fit in. However, a Custom Resource is a lot easier to map, code, and also a lot more readable. A Basic resource may still be interoperable while a Custom Resource certainly is not.

Example use case: Education

Let’s assume that you have an app where you want to keep a record of people’s education. In FHIR, no ResourceType Education exists (for Practitioners, there is the element qualification – but that is beside the point of this example). Here, we will create the custom ResourceType ‘Education’ and save some Education resources to Firely Server.

In this example, all the FHIR requests are listed in a Postman collection that you can use on your own Firely Server instance.

Write the definition of Education

There is currently (afaik) no tooling available to create a StructureDefinition for a custom ResourceType other than a text editor. A couple of hacks you can do are:

  • adjust the StructureDefinition of an existing ResourceType, preferably Basic;
  • use Forge to write a Logical Model and adjust the result in a text editor to make it a
  • ResourceType.

You will find more details on this in the section below. For now, let’s just check the result. Simplifier.net is the place to administer your definitions, and yes it can support the definition of a custom resource as well. I created the ‘Education’ project for this: https://simplifier.net/education. If you open the resource ‘Education’, you can check the requirements that a definition for Custom Resources must meet:

  • kind = resource
  • derivation = specialization
  • base = DomainResource
  • you can only use FHIR defined datatypes

You may note that the canonical URL of the StructureDefinition starts with http://hl7.org/fhir, just like the official ResourceTypes. This looks odd for something you define yourself, but in STU3 the invariant sdf-7 on StructureDefinition enforces this. As this limitation is removed in R4, we strongly encourage you to use a canonical. This canonical should be in a domain you manage.

Simplifier also renders all the elements nicely. Take a look at the elements in this resource.

Get Firely Server

Since you are on the Simplifier.net website already, you may as well download Firely Server directly from it. Insider tip: despite the order of the page, first download and extract the binaries. Then, download the evaluation license directly into the directory with the Firely Server binaries. More information on how to get started with Firely Server is in the documentation. We also have a blog post that takes you through the process of downloading and installing Firely Server step-by-step.

Make Education known to Firely Server

Firely Server has an administration endpoint (and database) that defines what ResourceTypes, profiles, and searchparameters it will handle. You can control that in several ways. In this case, we will connect Firely Server to our project to make it load the StructureDefinition straight from Simplifier. Create a file named ‘appsettings.instance.json’ in the binaries directory. In it, add the Simplifier project as a source for the Administration import:

{
"AdministrationImportOptions": {
"SimplifierProjects": [
{
"Uri": "https://stu3.simplifier.net/education",
// "UserName": "your Simplifier user name",
// "Password": "secret",
"BatchSize": 20
}
]
}
}

Since I made the project public, you don’t need a username/password for this connection. If you try this with your own private project, you do need to fill those in.

Now start Firely Server from the commandline.

<your-firely-server-folder>dotnet firely.server.dll

In the log, you should see that it is loading conformance resources from the Simplifier project. If you encounter any errors: the log file with more detailed logging can by default be found at %temp%/vonk-<date>.log.

Alternatively, you can start Firely Server vanilla and upload the StructureDefinition to the Administration endpoint interactively. The request for that is in the Postman collection. This way you actually add the endpoint for Education while Firely Server is running!

Test!

First, let’s make sure that the StructureDefinition was loaded. Pull up Postman and query:

GET http://localhost:4080/administration/StructureDefinition/Education 

This should return the StructureDefinition as it is on Simplifier.

The Postman collection also contains a request to generate a snapshot for this StructureDefinition. Although it describes a custom structure, the snapshot generator can process the definition itself.

Since we defined a new ResourceType, there should be a corresponding endpoint on Firely Server as well. Let’s try:

GET http://localhost:4080/Education

As expected, the endpoint is valid and you get an empty Bundle. Firely Server dynamically added the endpoint based on the definition.

In the Postman collection, there are three examples of Education resources that show you the following: (a) what these look like and (b) what your favorite software providers have studied :-). Try to run the PUT statements that upsert the three Education resources. You can then retrieve them all together, or individually:

GET http://localhost:4080/Education 
GET http://localhost:4080/Education/christiaan-maths

On a final note: Validation. In fact, you can validate your custom resource as well. That StructureDefinition is there for a reason, no?

GET  http://localhost:4080/Education/christiaan-maths/$validate

This also means that prevalidation works for custom resources. Prevalidation is a feature in Firely Server that allows you to control how strict Firely Server validates resources that are sent to it. You can avoid developer or input mistakes by validating the resource as it is being stored.

Wrap up

In Firely Server, you can store Custom Resources just like any other resource. Without any coding, simply POST the definition to Firely Server. As it is driven by StructureDefinitions, you get a decent description that can be shared and managed through Simplifier.net. And Firely Server can validate the instances for you.

Two further improvements will turn custom resources into truly first-class citizens of the Firely Server world. Firstly, you are allowed to add SearchParameters defined on your custom resource. And with SearchParameters comes chained search, _(rev)include, etc. Secondly, you cannot yet validate custom resources within a Bundle. This will be fixed in the next version of Firely Server.

Notes

Turn the Basic SD into a Custom Resource definition

In the Firely Server documentation, you will find the detailed description for this approach: creating a StructureDefinition for a Custom Resource.

Turn a logical model into a Custom Resource definition

  • Start Forge and build a logical model called ‘Education’. Save it to disk.
  • Open the generated file in a text editor and adjust:
    • change ‘kind’ to ‘resource’
    • edit ‘type’ to ‘Education’
    • change ‘baseDefinition’ to ‘http://hl7.org/fhir/StructureDefinition/DomainResource
    • rename ‘snapshot’ to ‘differential’
    • remove the first element ‘Education’

Want to stay on top of Interoperability and Health IT? 

Subscribe to our newsletter for the latest news on FHIR. 

Post a comment

Your email address will not be published. Required fields are marked *