Author Archives: Christiaan Knaap

FHIR up your legacy data

TLDR;

At the FHIR DevDays we released Vonk FHIR Facade. A set of NuGet packages to FHIR-enable existing (legacy) systems. Read on or dive in.

What can I do with it?

12-08-21-bici-01

Ever tried a different kind of bike? A recumbent, a canal bike or even a flying bicycle? From the cyclist’s perspective they’re all the same. That’s because they all have the same interface (pedals, steering wheel, something to sit on). But some of them need a little adjustment to their ‘surface’. That is where riding water or air is different from riding a road, and no single universal bike could cover all of them. Likewise, Vonk FHIR Facade empowers you to provide the same – FHIR – interface and just bridge the gap to different backend systems.

So whether you have that homegrown Access® system with valuable research data or that tailored Diabetes registration or this cool app platform that defines it’s own web services – Vonk FHIR Facade is meant to put a uniform API in front of each of them. And yes, that uniform API is obviously FHIR.

What is it?

The turn-key Vonk FHIR Server is built from several libraries. The FHIR RESTful API logic is built into Vonk.Core. It is agnostic to the actual storage. Instead it only communicates with an abstraction of the storage. We have already built three implementations of that abstraction ourselves. That way we are able to support very different types of storage, currently SQL Server, MongoDB and Memory.

Vonk FHIR Facade offers you the Vonk.Core library for all the FHIR functionality, and allows you to provide an implementation of the storage abstraction that fits your existing repository. That can be a database (relational or otherwise), other web services or even flat files, but that might hurt performance 🙂

Do I have to program?

Yes. Building a Facade with Vonk means building an ASP.NET (Core) web application that uses the provided NuGet packages.

The .NET programming languages give you a lot of freedom to express whatever you need to access the backend system. This power is hard to express in a declarative approach. On top of that, it allows for optimal performance.

That being said, we strive to develop methods to define a Facade for users that are less familiar with (.NET) programming. In order to get that right, we will first collect best practices from the early adopters and look for emerging patterns.

Side wheels for relational databases

Side wheels for relational databases

We expect access to relational databases to be the most common schema. And we already implemented it three times ourselves. So we provided a base implementation for doing exactly that, based on .NET Entity Framework Core: Vonk.Facade.Relational.

How does it work?

Here we have to be a bit technical – it’s about programming right? Implementing the storage abstraction involves two main components:

  1. Mapping data from the entities in your backend / database to FHIR Resources
    (And vice-versa if you accept creates or updates.)
  2. Translating pieces of the FHIR search mechanism to queries / web calls in your backend system.

Mapping data

This is pretty straightforward. Given that you have one or more related entities in your source system, you create a new instance of the target resourcetype and fill in the blanks:

public IResource MapPatient(ViSiPatient source)
{
  var patient = new Patient();
  patient.Id = source.Id.ToString();
  patient.Identifier.Add(new Identifier("http://mycompany.org/patientnumber", source.PatientNumber));
  patient.Name.Add(new HumanName().WithGiven(source.FirstName).AndFamily(source.FamilyName));
  patient.BirthDate = new FhirDateTime(source.DateOfBirth).ToString();
  patient.Telecom.Add(new ContactPoint(ContactPoint.ContactPointSystem.Email, ContactPoint.ContactPointUse.Home, source.EmailAddress));
  return patient.AsIResource();
}

You can also put data in extensions if a custom profile requires you to do so.

Before you program the mapping, you will have to design it first. Unless data is required on one side that is absent on the other, this will not take too much time.

Building queries

Searching in FHIR can become pretty complex. Straightforwardly searching for a string may already involve inspecting multiple columns in your database (e.g. the names of a patient), and then there are several other types of searchparameters like token, quantity or reference and modifiers on top of that.

What Vonk will do for you is analyzing the search url (or body, POST is also allowed for search) and break it up to pieces. It will validate all the parts of it:

  • Is the searchparameter defined on the requested resourcetype (also within a chain)?
  • Is the modifier valid for this type of parameter?
  • Is the argument in a valid format?
  • Can the quantity be canonicalized?

After that, it will present you a parametername and a value that contains the details according to the type of searchparameter. This gives you all the information to essentially build a clause of the where statement.

public override PatientQuery AddValueFilter(string parameterName, ReferenceFromValue value)
{
  if (parameterName == "subject" && value.Source == "Observation")
  {
    var obsQuery = value.CreateQuery(new BPQueryFactory(OnContext));
    var obsIds = obsQuery.Execute(OnContext).Select(bp => bp.PatientId);

    return PredicateQuery(p => obsIds.Contains(p.Id));
  }
  return base.AddValueFilter(parameterName, value);
}

The example above contains a non-trivial type of search: it is the result of a reverse chain on a reference search parameter: e.g. Patient?_has:Observation:subject.code=abc. Vonk disassembles that search url and makes sure you only need to worry about one thing at a time. If you would also implement the Observation.code parameter, this whole search would work.

The BPQueryFactory is in this example the factory that creates where clauses on the imaginary BloodPressure table, yielding Observation resources. This is the class where you would implement the Observation.code parameter in (based on a TokenValue).

A bonus is that if you implement the parameter as done above, include functionality comes for free: Patient?_revinclude=Observation:subject.

This implementation utilizes an EFCore DbContext and LINQ to express the filter. But the repository interfaces also allow you to express in terms of other query mechanisms, e.g. an http call.

Providing a FHIR response

This is where Vonk takes over again. You just return a list of resources based on the data returned from the composed query and the mapping. Vonk will take care of bundling, paging links and serialization to the requested format.

If you have not implemented one of the used searchparameters, Vonk will report that in an OperationOutcome. It will also automatically handle other headers for you such as the Prefer header on create and update.

STU3

This release of Vonk FHIR Facade supports FHIR STU3. Expect support for R4 shortly after that has been released.

Get on your bike!

We prepared an elaborate example for reading and searching Patient and Observation resources on a fictitious legacy system. You can find it on the Vonk documentation site. This is accompanied by code (of which the examples above are an excerpt) on Github.

The Facade code is meant to be ready for use in production scenario’s. Nevertheless this is the first release, so expect to see some changes to the interfaces in the near future. To smoothen your implementation and any changes afterwards we would like to keep in touch about your development.

Of course we’re very eager to provide support and get feedback from your experiences. Contact us on vonk@furore.com.

Pricing

Currently the pricing of all editions of Vonk – Server, Facade, Components – is the same. Please read the product page for details on the Launching Customer Program.

Vonk 0.3: subscriptions and more

TL;DR;

Recently we released an upgrade of the enterprise FHIR Server named Vonk. This release 0.3 contains features like custom search parameters, subscriptions and an Administration API. For a complete overview of new features, see the release notes. You can try for yourself at http://vonk.furore.com or download a trial version on http://simplifier.net.

Remember my bike?

It is strong, durable and simple. But if you are going to take a long ride, you need stuff. Hot coffee, raincoat and of course binoculars to check all the birds. Thaortlieb-back-roller-black-n-white-pannier-pair-white-black-EV229664-9085-9.jpgt means hanging a back roller to it. And that is what we did with Vonk as well: add a back roller full of new features.

Protection from the elements

What a raincoat is to a cyclist, validation can be to Vonk. Just bare validation was already possible (and still is, on /<resourcetype>/$validate), but now you can also protect your data by validating of all resources that are created or updated. And if they fail validation, they are rejected.

That is nice, but you probably have made your own custom profiles (in the form of StructureDefinitions). Of course hosted on http://simplifier.net 🙂 Previously you had to send these to /StructureDefinition/yourSD to make Vonk use it for validation. You can now feed them to Vonk through the new Administration API, still by doing a FHIR update interaction.

Finally, you can specify a list of profiles in the settings so that Vonk will only allow resources conforming to any of those profiles.

Subscriptions

2017-09-19 11.38.51Although a subscription to fresh coffee while riding is not really feasible, you now can subscribe to resource changes in Vonk. How this works is described in the FHIR specification, but the gist of it is that you post a Subscription resource to the Vonk Administration API. The resource specifies criteria for which resources you would like to receive notifications, and a channel through which you want to get those notifications.

Current limitations are that you can only specify a channel of type rest-hook, and changes on referenced resources do not ‘bubble up’. And although subscriptions are evaluated asynchronously, we did not yet build it for large numbers of subscriptions. See the documentation for details.

Find more

If you search for birds, you need binoculars (or better: a telescope). If you look for img-20170919-wa0013.jpgresources, you need as many features as possible. So we introduced custom search parameters. You can specify several sources (the .Net API, a zip file, a directory) with custom search parameters at startup. After that, new or updated resources will be indexed for these new parameters, and you can use them in your search interactions. Existing resources can be re-indexed through the Administration API, in order to find them on the new parameters as well.

Besides that, we implemented support for _list, _has, _elements, _type and _revinclude. And we improved on :missing, :exact and datetime handling. Finally, we moved to using the FHIRpath Expression in the SearchParameter resource to extract the indexed data, meaning we can now handle all the search parameters in the spec (and probably all your custom ones as well). A full list of improvements is provided in the release notes.

Go faster

I made my bike slightly faster by making it lighter: I removed the fixed dynamo and headlamp as I use a much better LED lamp if I have to. We also made Vonk faster, but by adding things: indexes! Both the SQL and MongoDb database implementations could use a few extra indexes, since reading and searching is used a lot more then update and create.

Have your partner make lunch

Do you know the happy feeling when you find a nice lunch in your bag, readymade by your partner? You can now pre-load Vonk with a set of resources as well, and make the users as happy. This is particularly useful if Vonk is used as a reference server for testing between communication partners. You use it by posting a zipfile with resources through the Administration API (/administration/preload). This interface is not meant for bulk loading really large sets of resources.

Start your ride easier

We have had a lot of positive feedback on the ease of deployment of Vonk. But we felt it could still be easier. So we removed the step of creating your SQL database yourself. If you allow Vonk to do so, it will automatically create databases for both the regular operations and the Administration API. For MongoDb this already happened, and for the Memory implementation this is obviously not an issue.

Beware if you have a database for the previous version of Vonk (0.2.*). It cannot be automatically updated. We will contact customers with professional support to upgrade their databases. You can check your version of Vonk in the CapabilityStatement.

License

You need a license to run Vonk. On Simplifier.net you can download an evaluation license. This will grant you usage of Vonk during 30 days, and it requires you to restart Vonk every 12 hours. If you need more evaluation time, you can simple download a renewed evaluation license. If you need to test without the 12 hour limit, please contact us.

Pricing

If you’re interested in using Vonk for production purposes, visit our pricing pages. We are still working towards a usage based pricing model and in the meantime you can enroll in our Launching Customer Program. Early customers are rewarded with the choice to stay in this pricing model once we have implemented the usage based pricing model.

Vonk FHIR Server in public Beta

Take a ride

Furore has built a new FHIR Server named Vonk. In keywords: enterprise grade, support available, SQL Server and MongoDB, FHIR Facade, cross-platform, Dockerized, .Net Core, STU3. As of now it is in public Beta. Try it at http://vonk.furore.com or download a trial at Simplifier.

Inspiration

FietsCK-01

This is my bike. After being a simple city bike for the first 25 years, I decided to keep the good parts and improve the rest. Now it suits all my many bike needs. It is clean. No gears, no cables, no chain cover, just the items that I really need. It is strong but not heavy. Steel frame, steel carrier, able to carry my wife on a romantic trip and it doesn’t break on the many potholes and loose tiles in the city. It is versatile. It can ride both dirt- and tarmac roads. Run lightly on my way to work, carry all the groceries for a week on Friday. It has the right size. Large enough for my 1.95m length, but it still easily fits in a bicycle rack. It never gets in my way in the shed. Maybe the best part is the carbon belt drive that I had mounted recently. Unbreakable and yet free of maintenance. And now that the bike is 27 years old and still my daily commuting bike I can faithfully say that it’s proven technology. And my inspiration for developing Vonk.

The old bike

Back in 2012 when FHIR had just started, Furore started implementing the server part of the specification in .Net, and we called it Spark. A reference implementation to test the spec and provide the world with a real FHIR server to develop and test against. It has gained a lot of attraction, well beyond these purposes. Many requests for e.g. production use, SQL Server, STU3 and company support reached us.

The new bike

So we decided to respond with a new incarnation of Spark that would be able to serve as a very versatile yet production ready FHIR server. And it deserved it’s own name: Vonk. Vonk packs together our extensive experience with FHIR, the HL7 FHIR .Net library and Spark in a fully new solution based on Microsoft .Net Core.

fietsck-03.jpg

New, robust technology

Several of you may have seen my talk on building a FHIR Server (> 19:30) at FHIR DevDays last November. By now we have realized many of the ideas that I presented in that talk. As of today we present the official Beta release of Vonk.

Ready to ride

My bike is always ready to ride. For a quick schoolrun or an extended birdwatching ride – it will just run. Vonk FHIR Server is the same. Install and run. It is a stand alone FHIR server with MongoDB storage. Or SQL Server and then truly support transactions. Or run a few quick tests on the in-memory store. The storage API that we created to accommodate these very different storage engines enables us to add other other back ends easily, either with or without support of Entity Framework.

Change the wheels

A few weeks ago my birdwatching buddy lured me into a dirt road. Dirt became mud and then deep mud. Even my bike has limits. It meant I had to continue walking. But with Vonk you just change the wheels! With Vonk FHIR Facade you can leverage the power of the storage API to plug it on top of your existing database. Thus Vonk acts as a FHIR REST facade on top of your (legacy) system. And although Vonk is enterprise grade, it is not heavy. So you can unleash your systems small and large all in the same way. All you need to do is create an implementation of the storage abstraction for your use case. We already did so ourselves: the Simplifier.net platform runs on Vonk. The same abstraction even allows you to address other (web) services for retrieving or storing the actual data, thereby using Vonk as a hub, possibly backed by other Vonk instances that are facades to your internal systems. When creating a facade you program the new wheels in .Net, with all the power that comes with that. On the roadmap is creating facades by configuration.

Assemble your own

No gears, no handbrakes, clean as can be. But a bit too clean if you need to climb a hill. In the Netherlands we don’t do hills, but Vonk can be used around the globe. Vonk FHIR Components gives you all the good parts of Vonk, for you to assemble your own perfect FHIR Server. Or integrate it into a larger web server. Or turn it into a hometrainer. Just add and leave out parts as you like. Vonk FHIR Components will become available as NuGet packages.

Run all the tasks you need

From groceries to commuting: even my bike is not as versatile as Vonk. In this beta release it will do STU3 and DSTU2, JSON and XML, and most of the regular FHIR interactions plus a few bonus ones:

  • capability statement (metadata)
  • create, read, update, delete
  • search on all specified parameters, also chained, choices, multiple resource types, include related resources
  • full resource version management, enabling history on resource, resource type and system level
  • process batches of interactions, in a transaction if you wish (requires transactional storage)
  • validate a resource against the spec or a custom profile
  • extensible to custom operation (‘$your-operation’)

The road ahead

More features are on their way. Priority is volatile and can be influenced by customer requests.

  • support for several more options, e.g. _summary, _elements and conditional operations
  • subscriptions
  • documents ($document)
  • proper support for ‘Binary’ resources

Lock it

fietsck-06.jpg

Security in Amsterdam is not about riding with a helmet, but putting at least two solid locks on your bike. We know a thing or two about not letting your bike get stolen. Or your data. So Vonk runs on https, can be fronted by a reverse proxy (e.g. Apache or NGINX) and exposes just the FHIR RESTful API endpoints. But a fully locked bike brings you nowhere. You need access, but limited access if needed. Therefore Vonk can participate in an OAuth2 single sign-on environment. Access to resources can be based on the claims in the OAuth2 access token. You can use the preconfigured scopes and launch contexts as defined by SMART-on-FHIR, or configure your own.

Ride anywhere

Although my bike won’t ride on water (in Amsterdam we have canalbikes for that) or deep mud, just about any other surface will do. And Vonk is no different: it runs on Windows, Linux, OSX, as an executable or in a Docker container, on premise or in the cloud, as an Azure App Service – you choose.

Ride fast

When my colleague Marco showed me Vonk running on Docker I was so thrilled I even overtook e-bikes at 30 km/h on my way home. With Vonk we also made performance a number one priority. Using the newest Microsoft ASP.Net technology and proven storage solutions we managed to implement a very performant FHIR Server. Being lightweight and fully asynchronous you can scale out or up as you see fit.

Be in control

In the Netherlands there is wind. Usually in your face. You need to lie low. So my first upgrade was the handlebar that allows me to lie comfortably on it and still keep control over the bike. Extensive semantic logging to just about any target and a connection to Microsoft Application Insights allows you to control Vonk just as well. Integrated validation can be used as a gatekeeper to accept only compliant resources. On the roadmap is also an extensible management API to:

FietsCK-05

  • add profiles, or restrict to specific profiles
  • add or restrict the search parameters
  • enable or disable operations

Where is the blueprint?

I’d be happy to tell you how I built this bike. But Vonk is not open source. Vonk is a commercial product based on license fees and paid support. Nevertheless we want to continue to support the FHIR community as we already do with the FHIR .Net API and Forge. In short it is possible to use Vonk for free if you support the FHIR community in any way with that usage. Just contact us to see if you’re proposed usage fits this goal.

What happens to the old parts?

I kept them in my shed as spares. As for Spark: This is up to the community. Furore has put a lot of effort in Spark and provides all of this effort to the community. It’s open source, available on GitHub. But Furore will neither port Spark to STU3 nor provide support for DSTU2.

Name

I never gave my bike a name. But ‘Vonk’ means two things. First, it is the Dutch word for Spark. After struggling with our company name Furore we thought the FHIR community was up for the next Dutch challenge. Second it reminds us of our dear collegue Hans Vonkeman who has passed away far too young and thus it is a kind of a tribute.

And now I’ve been at the keyboard long enough. Off for a ride. Do you ride along? Visit the getting started to see how you can get a trial Vonk FHIR Server as binaries or in a Docker container.

Prefer to ride along face to face? I’ll be at the HL7 WGM in Madrid next week, albeit not by bike. Or visit the FHIR DevDays here in Amsterdam in November. There I will be by bike.

Cheers, Christiaan
FietsCK-07