openEHR API implementation in Rust

Hi there!
I want to implement an API from scratch, to be an alternative to EHRBase. I’ve already started some work here: ehrust (not sure about the name). I’m reading the documentation mainly from here. Are there any other good sources I should look up?
I’m wondering if I should make it as similar as possible as EHRBase? I’m not entirely about the exact specifications of the responses and how to structure the database.

2 Likes

It is indeed the right link of generic API specifications, release 1.0.3. If you would want to do something less generic and do 1:1 with EhrBase, you have to look it up in their repo / docker.
About openEHR API specs, I would add two things:

  • that there is besides others also a generated Rust codebase, in a development branch in the repo.
  • will start soon working on v2 of of the specs from your link above, so consider this aspect in your plan.
1 Like

One thing I wasn’t entirely sure was, that EHRBase uses headers a lot to return minimal data and I was looking through the specifications if there’s anything about that, but I guess there isn’t?

About the generated Rust codebase, could you please link it, I’m not having any luck finding it.

Can you say roughly when the V2 spec is going to be released? Are there going to be massive breaking changes that I should worry about and postpone my project?

Please note it is not only an API, you’ll need to implement the persistent model, the data management flows (versioning), the query processing, etc.

1 Like

Yes I’m aware of that. I thought starting at the API and seeing what it needs and uses and then implementing that. There’s only so much I can learn in a given time :sweat_smile:

1 Like

It’s a very interesting are to work with, specially n a new technology stack, though it’s painful, been there, done that with EHRServer some years ago, and it gave me knowledge I wouldn’t get anywhere else. The advice I would give to my past self is: design your data model thinking in the query mechanism you will implement as the first thing. The API is the easier part but requires the rest of the components to be in place. Best of luck!

1 Like

Okay so start from back to front, thank you!
I still have to read up on the AQL and by data model, you mean how I’ll structure things in the database like tables and such?

You should also have a look at the Platform Services specification - that gives the abstract semantics; then you can separate REST specific semantics (HTTP headers and the like) cleanly.

1 Like

I suspect @Pablo was indirectly suggesting the opposite!! openEHR is designed to work at a logical level from a client perspective, essentially hiding the database layer from client apps and services.

My strong suggestion (to everyone) is to get your head around the service layer and how openEHR works logically, compositions, aql, templates etc by using an existing CDR and the standard openEHR API.

There will be lots of opportunity to build some middleware type code in Rust as a convenience wrapper, and to understand how templates can be used to drive other artefact generation - see Pablo’s work.

CDR building is serious engineering and database design / optimisation / indexing is a critical part of that and non-trivial. I’m sure you have the capacity to do it but get very comfortable with the openEHR paradigm before you go there. By all means delve into the OSS projects like EhrBase and Pablo’s cloud server to see how they have tackled the challenge but I’d really hesitate to putting real effort into this until you are up and running using an exiting CDR.

One thing I’m unsure about is, that archetypes use a lot of class inheritance that Rust doesn’t have. I’m wondering how I’ll solve this problem.

In practice, you are not working with individual archetype but rather templates, and in the xml/json representations that we use in the REST APIs , a lot of these inheritances are flattened out. However beyond my ‘clinical hacker’ territory to comment further.

1 Like

Do you mean the archetype meta-model, i.e. what we call Archetype Object Model (AOM2)?

Or archetypes themselves - which are instances of that model. Since you are implementing, I would think you mean AOM2. You can see what it looks like in Java by looking at Archie. @pieterbos and other implementers of Archie will show you around.

Since Rust doesn’t have inheritance per se, I would imagine that you will need to use traits and so on. There would be common Rust community tricks for achieving what inheritance achieves.

Aside: I have been contemplating what other new languages might be interesting for openEHR, as have many others. I’m currently messing around with Kotlin (so are others, more seriously). @NeoEHR is using Dart. Java, C#, and PHP seem to be default languages for implementers. These languages all have inheritance. I am not 100% if Rust is a really good fit for meta-models (which tend to contain inheritance), although it seems to me it should be really good at APIs. And in API design, you can flatten out most if not all inheritance to concrete types. Maybe that will help?

1 Like

Yes I meant the AOM2. I still have to read further into it but the Archie repo will come in very handy to get a better idea how it all looks like thank you!

There is a few ways to get around inheritance, as you mentioned traits are one way, another potential way is to use Enums, duplicate fields or simply have a base field that represents the parent class.

I agree with @thomas.beale about the lack of inheritance in Rust. Java has polymorphism. Dart doesn’t so I used single inheritance with implements:

class Template extends AuthoredArchetype implements Serializable {
class AuthoredArchetype extends Archetype implements AuthoredResource, Serializable {
class Archetype implements Serializable {
abstract class AuthoredResource extends Object implements Serializable {

Archie (Java) implements this as:

public class Template extends AuthoredArchetype {
public class AuthoredArchetype extends Archetype {
public class Archetype extends AuthoredResource {
public abstract class AuthoredResource extends ArchetypeModelObject {
public abstract class ArchetypeModelObject extends OpenEHRBase implements Serializable, Cloneable {

@pintariching Can you please write how Rust would handle this (so that Thomas and I learn a bit about Rust :blush:). This example doesn’t use polymorphism.


I personally like Dart but I wonder if TypeScript would be a better option :thinking:
At least to help web developers work with openEHR without learning it (TypeScript could also be used for the backend but there are many other options on the server-side).
(Dart already has a Dart → JavaScript compiler which I used to create a JavaScript SDK for openEHR)

@pintariching I have to suggest that you generate your AM/RM classes in Rust.
There are different release versions of AM/RM and your app/server must work with many different versions (you cannot control which version another hospital is using to send data to your openEHR CDR).
openEHR uses BMM files to specify the AM/RM models. They can be used by your generator to write 100s of required classes for you :wink:

Im going to make bold, and probably unpopular statement here.

Walk away from AOM2 /ADL: (for now) or listen to @NeoEHR.

As an run-time implementer you really do not need to understand this stuff. It is for tooling designers and even if you want to get into tooling / utility writing , there are much easier starting points.

Get to understand how the REST API works, how to hook it up to an app/ querying etc. By all means build some libs/utilities in Rust. Get it working. Understand how new or updated template manifest them selves in new data structures. Understand where you might have to flatten out some inheritance to work in Rust and have a look in the underlying RM to see how/if that might be improved.

By all means dip into archetypes and templates from the perspective of design-time tooling/utility support but start with the .opt operational template format or even better the simpler Web template format. Basically these are 'compiled/ aggregated constraint definitions.

Ducks for cover!!

@ian.mcnicoll Where were you with the same advice when I popped-up here :wink:

However @pintariching idea probably includes the CDR. He/she/they used API but it looks like a CDR was meant (based on):

@pintariching Can you share more about your project so that we don’t confuse you too much?
(but listen to Ian regardless of what your project is :blush:)

1 Like

I would have to look what each class extends. If it just extends with functions then In Rust I’d maybe write it like this:

struct AuthoredRespource;
trait Archetype {}
trait AuthoredArchetype {}
impl Archetype for AuthoredResource {}
impl AuthoredArchetype for AuthoredResource {}

and so on. However if there are fields added, then I’d probably do it like:

struct AuthoredResource;
struct Archetype {
    resource: AuthoredResource,
}
struct AuthoredArchetype {
    resource: AuthoredResource
}

And so on. I’m unsure if this is the right order on what inherits what so excuse me for it :sweat_smile:

1 Like

Okay honestly I wasn’t entirely sure what I was getting myself into but now it’s becoming more clear. I want to implement a CDR like EHRBase, so mostly the API, the Query things and such. For all of this it’s clear to me that I firstly need to be able to parse a Template and be able to validate it, which brings me to all of the AOM/ADL things. However I didn’t realize I could auto generate classes like @NeoEHR mentioned which is going to be a major help in development at least until I understand how it completely under the hood.

1 Like

You could skip most of the ADL if you decide to use JSON OPT2.

There is Nedap’s Visual Studio Code extension to convert ADSL into JSON: ADL and AQL visual studio code extension

1 Like

“For all of this it’s clear to me that I firstly need to be able to parse a Template and be able to validate it, which brings me to all of the AOM/ADL things”

To store data in the CDR, no you don’t!! You just send the instance data json blob, and tell it the name of the template to validate against (already uploaded and registered). the CDR will do the validation and give you validation errors.

If you want to do client-side validation, you do want to be able to parse the template, for this (at least for staters) I would strongly suggest you look at the Web template produced by both ehrBase and Better. THis is derived from the .opt which is pure AOM-based XML but is quite hard to get your head around.

Even I can work out Web templates!! - here is a Typescript [Asciidoc generator] (GitHub - freshehr/wt2doc: Asciidoc generator for Archetype Designer web templates) based on parsing a Web template (forked from work by @bna .

That is the fastest way to get to grips with the constraints involved, and expressed partly by the underlying RM but then with further constraints at archetype-level. Lots of opportunity to add value and experiment with tooling an utilities

Once that makes sense by all means get into .opt syntax/parsing/code generation as various including @Neo4j have done.

This is really clever and powerful technology but it does have a number of concepts that challenge almost everyone at first and its’s easy to be overwhelmed at the start . I always urge people to start at the client layer and work deeper into back-end stuff, even if that is the end goal.

The 2-level modelling paradigm and the way that archetypes graft onto the RM semantically is particularly mind-bending at first.

Great questions and keep asking!!

2 Likes