FHIR Prototyping with Node-RED – part 2

In part one of this series, we looked at using node-RED to manage notifications using the FHIR Subscription resource for a Use Case where relatives (or other care givers) could be notified when a person is admitted to hospital. We looked at the overall flow – now let’s look a bit deeper into some of the details.

First up – when we received a POSTed resource, we validated that it was correct using a sub-flow. How does that work? A subflow is simply a flow that implements a specific bit of functionality and can be called by another flow. It can return one or more messages – or not have a return at all. It’s a way of ‘encapsulating’ complexity and making the main flows simpler. We could have also created a custom node for this – which has the advantage that it’s easier to re-use in many different flows, and we can use any nodejs capability.

Here’s the sub flow:

3. validator.png

As you can see, it has exactly the same components as the main flow (though the lines are dashed). There are 2 special nodes that correspond to the ‘interfaces’ exposed by the subflow:

  • A single input node
  • 2 output nodes – a ‘valid’ and an ‘invalid’ output.

If you look back at the main route, you can see how these fit in.

The flow is pretty simple: first, we check that we got a valid JSON object – failing the validation if not. The function node that performs the check will add an ‘isValid’ flag to the message, and the next node is a switch that routes based on that flag. It will also create a url that will call the $validate operation on the FHIR server – which is picked up by the next node – an HTTP request node. This node makes the actual call (a POST) to the FHIR server and validates the resource.

After the HTTP request has completed, we examine the OperationOutcome resource that was returned for any errors in a function node – setting a flag and passing to the switch node as we did when checking the json. The switch then connects to the ‘valid’ or ‘invalid’ output as appropriate. (Remember that the statusCode from the $validate operation does not indicate whether the validation succeeded or failed – that information is in the OperationOutcome).

At the moment we only use this subflow when receiving a new resource via a POST – but we could easily use it in a PUT update operation as well.


Now let’s take a look at the Subscription resource. The key parts of this resource for our purposes are:

  • criteria – what will trigger the notification. This is a FHIR search query, so in our case a value of Encounter?patient={patientId} seems reasonable – assuming that we have the patientId of course. (If you look at the Encounter resource you won’t see a ‘patient’ property – it’s ‘subject’. But – remember that these are search criteria – and Encounter does indeed have a search parameter called ‘patient’).
  • type – what sort of notification channel we will support. Currently we support ‘rest-hook’ and ‘email’. Note that this property has a ‘required’ binding to the ValueSet – we can’t add any others, unless we use an extension to do so.
  • endpoint – where the notification is to be sent

It’s important to note that we aren’t implementing  ‘generic’ subscription functionality here. We’re being highly specific about the subscriptions – and the format of those subscriptions – that we will accept. There’s nothing to stop us relaxing that restriction – though we’d need to change the implementation design if we did so. Indeed, this is the main purpose for using node-RED for this kind of investigation – it makes it much easier to make changes like this as we are exploring and clarifying the requirements.

Although we store the subscriptions as FHIR resources, internally we use a simpler format to make checking for subscriptions easier. There’s another sub-flow for this – it reads all the Subscription resources from the FHIR server and converts them into the internal format. It gets called automatically at startup – and also when a new Subscription resource is POSTed.

Screen Shot 2019-01-07 at 3.18.45 PM.png

Note that we aren’t looking for updates to the Subscription at the moment (such as stopping it, or changing the notification channel). It would be quite simple to do – we would support a PUT endpoint for updates, and if the resource is a Subscription just call the ‘load subscriptions’ subflow.

HL7 Version 2

So far we’ve been assuming that the PAS system in the hospital is generating Encounter resources – but it’s far more common that it generates HL7 Version 2 messages. Can we consume those as well? As it turns out we can, and here’s the flow:


We assume that the PAS system can easily POST a standard HL7 v2 message to the hub (We can always use a different input node if not). This will be a text file (though the segment endings are just a line feed) so we look to see if it’s an admission message (ADT^A01) and if it is, look for Subscriptions as we did before. We can re-use the same notification channel as we did for Encounter resources, but there is a catch – in our Subscription we had the criteria as Encounter?patient={patientId}, and we don’t have a FHIR patient id in a V2 message.

But we do have an identifier – PID-3 – so a criteria of Encounter?patient.identifier={identifier} will work for us (this is an example of a chained query by the way…) Note that we could use the same pattern for Encounter resources – but we would have to retrieve the patient resource from the FHIR server first – so it’s rather more complex to do so.

As always we could do more with this flow – for example, we could convert the ADT message into an Encounter resource and save in the FHIR server. Or – given that ADT messages also have other clinical data like Conditions and Allergies, we could create and save resources of those types as well.

User Interface

The last thing to think about is how to support a web based User Interface. For example, to create a new subscription, modify an existing one or to view notifications that have been sent (assuming we kept a history of course). Or – we talked about a Portal in the first post, any reason why it can’t be exposed from node-RED?

Turns out it’s pretty straightforward.

Given the node-RED is developed on nodejs, all you need to do is to create the artifacts that make up the application and then serve them as static files via an http input node.

Here’s the flow:

5. UI.png

It starts (of course) with an http node listening at an appropriate end point (/ui in this case), uses a function node to create the filename for the file that has the html for that page, then a file read node before returning the file in the http response.

The flow does show a new node – the ‘catch’ node – which is triggered if a file does not exist (i.e. it’s an unknown url) in which case we set an appropriate error message and return a 404.

So there you go. Reasonably complex workflow implemented in a way that is (I think) easy to follow, easy to alter and easy(ish) to debug (breakpoints would be nice). I think if you were going to implement security – like SMART – for the user interface or API you’d delegate that to an external service and just check for access tokens on the http calls (you can insert express middleware functions to do this).

Just what you need when testing out an Implementation Guide that is more than just data structures.




About David Hay
I'm an independent contractor working with a number of Organizations in the health IT space. I'm an HL7 Fellow, Chair Emeritus of HL7 New Zealand and a co-chair of the FHIR Management Group. I have a keen interest in health IT, especially health interoperability with HL7 and the FHIR standard. I'm the author of a FHIR training and design tool - clinFHIR - which is sponsored by InterSystems Ltd.

9 Responses to FHIR Prototyping with Node-RED – part 2

  1. Pingback: FHIR Prototyping with Node-Red – part 1 | Hay on FHIR

  2. JF says:

    I wonder if you can help me with a query regarding FHIR I’ve been scratching my head over. How does one validate a FHIR bundle of type ‘document’ is valid? Are there any (free?) third party or official tools that would allow one to confirm validity?

    • David Hay says:

      Depends on what you mean by ‘valid’. As you say – it’s just a Bundle with a Composition resource, so you can use $validate against the Bundle endpoint and that should conform basic validity. Are you thinking of conformance to a profile? (http://hl7.org/fhir/documents.html#profiles ) – I’m guessing that validating the Composition would take you a long way towards that – though wouldn’t conform the actual presence of resources in the bundle…

      • JF says:

        NHS Digital have an example FHIR file for a mental health edischarge form, however their bundle type (“document”) doesn’t appear to validate in any commonly found validation tools, but an example FHIR file I was provided with (of type “transaction”) confusingly does, so I’m under the impression the bundle type impacts validation. Whilst I suppose, yes, I mean the profile, the validation issue, I’ve been told, rests on the bundle type, much to my confusion.

        Example document:
        (Scroll to the very bottom using the keyboard’s ‘End’ button for the ‘view raw’ link, which can be right-clicked save-as into an .xml file).

        I suspect the validators suggested by NHS Digital do not include the profiles (which are stated as being ‘standard’ but I suspect are truly ‘custom’). I was under the impression validators can pull profile resources from the specified URL in the file, but it appears not to be the case and I’m confused how one goes about validating such a file. A lot of suggestions involve Java code for HAPI FHIR, but nothing for modifying pre-existing third party applications or stand-alone binaries.

        I will profess to ignorance, documentation on the topic has been… wildly confusing, to say at best.

  3. David Hay says:

    I generally use the $validate operation exposed by the reference servers for this kind of thing (though the java validator supplied by the project will probably work as well).

    Try POSTing the example to Grahames server at http://test.fhir.org/r3/Bundle/$validate (Note that you need to set both Content-type and Accept headers to application/fhir+xml to get an OperationOutcome back)

    You’ll get a number of errors – mostly relating to missing resources in the bundle (references to missing resources that is) – but no issue with it being a FHIR document.

    This should also work on the hapi test server as well – though I got a gateway error when I tried – but my clinfhir server at http://snapp.clinfhir.com:8081/baseDstu3/Bundle/$validate which is an instance of hapi worked)

    May be worth pointing this out to the NHS so they can correct it.

    Hope this helps!


    • JF says:

      Thank you for helping out so far, I’ve raised it up as an issue for them to address, and it’s good to hear from someone else that confirms my suspicions. It’s nice to have guidance on a complex topic.

      I do have a final query – are there any local (EG command line based) FHIR validators that you can recommend that can be pointed to a folder of (custom) FHIR profiles which it can then use to validate a FHIR file or files?

      I imagine there must be a neat .jar somewhere that can be told to get profiles from X directory and validate Y files generating Z output.

      • David Hay says:

        well – the validator that comes with the spec will do it on a file by file basis – not too hard to extend it with a simple java app I would have thought. Or – a command line script that reads the contents of the folder and calls $validate on each one. Nodejs would be good for that…

      • JF says:

        Thank you for your efforts in assisting me. I wanted to return the favour.

        I’ve produced two GitHub projects which are both work-in-progress, but I feel they might be helpful to the wider FHIR community.

        One goes to some length to solving the Clarotech validation issue (turns out you need to save a ton of profiles, valuesets and codesystem files) which is more aimed at NHS Trusts, which can be found here:

        The other is based on a modified version of your instructions for setting up a HAPI FHIR server, which I’ve converted into a .sh (bash script) which can be run on most Linux boxes, which prompts the user for input in getting a basic HAPI FHIR server setup and running, which can be found here:

        Both are relatively incomplete, but I believe go a great way to assisting people trying to setup FHIR development environments. Both are released under BSD clause 2.

        Thank you for your time.

      • David Hay says:

        Thanks for your efforts! I’ll place a link to the install script in the blog post – and you may want to pass on the Clarotech project to INTEROPen…

Leave a Reply

%d bloggers like this: