I have been delving more into the RM lately, trying to get a deeper understanding of how that part of the CDR works.
I am paying particular attention to the EHR class structure below.
I created an EHR and then used the resulting ehr_id to store a collection of compositions.
When I retrieved the EHR, I expected to see the EHR.compositions attribute set, but it’s not. The documentation at EHR Information Model suggests it should be.
Have I misunderstood? If so, when would this attribute be set?
It is this final step, when I retrieve the EHR record, that I expected to see the EHR.composition attribute set, but it’s not. I appreciate it is optional in the EHR class, but didn’t know whether this is just an implementation decision by the ehrBase developers, or whether it should not be set at all.
I think it is an implementation decision which is the same for Better and Ocean CDRs. Not sure about others . You can understand why, as a mature ehr may have thoussnds of compositions which are easily retreivable by other means eg aql
According to the specifications, @richard.kavanagh is correct to expect EHR.compositionsattribute to contain a list of references to the compositions for the EHR.
If the CDR returns an EHR without a populated EHR.compositions, a user will correctly consider, there are no compositions for the EHR. The EHR class lacks a function to return the number of compositions for the EHR. For comparison, VERSIONED_OBJECT class has the version_count() function. This class has other functions that solve the issue presented for the EHR class. The important difference between these two classes is that VERSIONED_OBJECT doesn’t have a “versions” attribute but EHR has the compositions attribute. VERSIONED_OBJECT has a function all_versions() to get the list of versions.
The implementations can decide how they store the EHR.compositions but (current) specifications are clear that if there are compositions for an EHR, they must be returned in the EHR.compositions.
openEHR REST API has endpoints for single COMPOSITION requests. There is no way to get a list of all COMPOSITION.uid for an EHR.
Maybe we should consider removing the EHR.compositions attribute (and contributions, folders) from the EHR class. These attributes could be replaced with functions as in VERSIONED_OBJECT class.
I agree - though as per @borut.jures response, if none of the seasoned veterans of openEHR are using it, then it probably makes sense to remove it. The document specifications are there to help new entrants as much as anyone else, so making things easier is a benefit.
I make use of AQL for this use case. The use of AQL queries vs API requests is interesting, as the AQL fills in many potential gaps left by the APIs, especially around accessing data across different EHRs.
I’m not arguing it should be there, I’m just challenging the specifications that say it should be.
Personally, I think it should be removed primarily due to the performance implications of resolving it. The puzzling part (to me) is that’s always been the case and there have presumably been opportunities in the past to amend areas like this, based on implementation experience.
There’s a difference between the RM spec and the REST API. The API doesn’t work with RM objects directly, it works with API oriented objects which I always said should be part of the SM and the JSON schemas.
In conclusion: don’t expect the REST API to return “real” or “full” RM objects.
At first I accepted this explanation, but later I realised that most of the REST API uses RM classes. When a different class is used it is explicitly documented (e.g., UPDATE_AUDIT instead of AUDIT_DETAILS in the CONTRIBUTION payload).
All responses except EHR use RM classes. It appears that EHR is the only response omitting a non-empty list attribute.
I understand that no CDR embeds references to compositions in its EHR table. This is also why I propose removing these attributes and adding functions to indicate the existence of these relationships. This change would just update the specs to reflect the de-facto use of the EHR class.
Since the attributes are all optional, replacing them with functions wouldn’t be a breaking change?
The key to look for differences is when OBJECT_REF is used.
You’ll also see CONTRIBUTION having versions directly inside in the API, where OBJECT_REF is used in the RM.
My point isn’t that the RM is not used, is that isn’t used in all the API endpoints, so it shouldn’t be expected that all API endpoints return RM objects.
I haven’t implemented all the endpoints yet, but I checked the result examples and they are RM objects. In my view, strictly returning RM instances is also expected, as the API returns openEHR data which uses RM. We probably don’t want to introduce a “parallel” RM for the REST API responses.
I’m focusing on responses. The payloads cannot always use RM as you already mentioned.
Are my observations correct?
All responses except EHR use RM classes. It appears that EHR is the only response omitting a non-empty list attributes.
Since the attributes are all optional, replacing them with functions wouldn’t be a breaking change?
@pablo We agree about the payloads. This thread is about responses.
Richard notified us about the unexpected response returned by the EHR endpoint.
Pablo’s conclusion is: “don’t expect the REST API to return “real” or “full” RM objects.” Is this documented in the openEHR specifications?
My observation is that all responses except EHR use RM classes. It appears that the EHR response is the only one omitting non-empty list attributes. Since the attributes are all optional, replacing them with functions wouldn’t be a breaking change. I asked if my understanding is correct.
Proposal to @SEC is to consider removing the compositions, contributions, folders attributes from the EHR class. These attributes could be replaced with functions as in VERSIONED_OBJECT class.
Let me try to frame this from a different angle if that’s OK for you. You are right to question the lack of values for some of the EHR attributes when using the REST API. I think you raise a valid point and this is good feedback for the SEC.Except the nature of the feedback may be a little bit different depending on how one interprets your observation
It’s understandable that you are looking at the canonical specification for openEHR and expecting to see a faithful representation of the EHR in the REST API. However there is a transition going from the specification to the rest API, which is easy to miss and I think we should specify this somewhere to avoid confusion.
That transition is taking an object model and projecting it to a REST API. Unfortunately that changes the expressiveness and semantics of what we can represent. When REST is implemented over the HTTP protocol, which is the most common implementation by far, we end up having to squeeze the much richer semantics of an object model into a different formalism. That formalism has only a bunch of HTTP verbs and a few other mechanisms to encode what we can express in a much richer way in an object model (the serialisation of RM is just one part of that restriction).
Sometimes facts get lost in translation when we build a REST API around an object model and sometimes they get translated inconsistently.And sometimes it’s not even about expressiveness because one could argue that you can find a way of expressing whatever semantics you want to express using a REST API, which is probably true in theory. In practice you get bitten by the practicality of implementation, which may render the choices you made for semantic completeness of the API irrelevant, because the execution of the semantics is not feasible.
The situation you are raising here is a combination of these challenges.The compositions attribute can be set but then, as others have indicated, the actual implementation may have to fill the result with thousands of object references, which that attribute’s type in the object model. You would then have to use the information in those object reference instances to arrive at the actual compositions. The problem from an API designer’s point of view is even if the REST API populated that attribute and ignored the obvious feasibility and scalability issues, it still wouldn’t give you the sufficient information you would require to identify the compositions of interest (OBJECT_REF is rather simple). So this is the semantics being translated into rest, not being as practical as the implementation of the object model, say in a programming language. So we’re looking at both semantic translation and practicality challenges here. That’s two out of the three I mentioned.
The third one, one could argue, is inconsistency. You could say that the EHR status is being populated (as per your screenshot), which is an object ref, and the compositions are not populated so that’s inconsistent. The underlying issue is mostly feasibility, as I explained above, but that leads to inconsistency here.
The problem is (and I am hoping this may motivate readers of this thread to appreciate the difficulty of managing the specifications) that REST API is an implementation technology specification, so we cannot indicate something that is specific to a particular implementation in the technology-agnostic part of the specification. As in, this attribute may not be populated in the REST API (implementations) because … That has to go to the REST spec, and we have to make this semantic boundary clear to the readers of the specs, that’s what my 2 pennies would be a SEC member. I would suggest the best we can do in the RM specs is to say something in the lines of: these things may/will change when exposed via implementation related technologies, beware.
Great point! I think it gives us, as the spec maintainers and implementers, some food for thought. We are exposing openEHR at the REST API level by defining RM types (subject to above losses/issues) as the unit of semantics for clinical data. The COMPOSITION is an envelope and the actual clinical semantics is indicated by the actual types of the values of the content attribute. So at the REST API surface level the clinical semantics of data is not directly exposed. AQL provides somewhat of a back channel to filter the compositions you are interested in. Don’t get me wrong by the way, I’m not suggesting that AQL is a workaround in this case. One could equally argue that it is opening up the strength of openEHR by design at the REST API level, so it this is a design choice. The alternative could have been to have a REST API that is defined at the level of actual clinical concepts and I’m sure at this point you are thinking of one such design, chosen by our friends at the HL7 side of the grass, known to us as FHIR Such a choice comes with its own ups and downs, which I cannot possibly go into here.
As far as I’m concerned you have provided very valuable feedback, thanks for that. I agree that the specifications should say something. It’s just that what I think they should say isn’t necessarily what you suggest they should say I can assure you this thread will turn into a discussion in the next REST API workgroup meeting, which @sebastian.iancu leads.
Everything I said above is my personal opinion btw, the rest of the SEC and/or implementers can disagree, but I thought I should offer some perspective into your observation.
Thanks to everyone who has taken the time to read and respond to my original question; it wasn’t intended to generate this much discussion.
I have my answer, so I will move on to the next challenge and leave it to others to debate what (if anything) needs to change.
My final comment is that for people who sit outside the internal openEHR groups, the only information available is what is written in the public specs. So for the wider community (and hopefully a rapidly growing wider community), this needs to be as accurate and up-to-date as possible.
Just as a general thought, what the RM says is the logical storage model, meaning it is what would be materialised in memory on a server, and through an API that wanted to expose exactly that model.
In which case, the EHR object would appear with all its compositions, i.e. OBJECT_REF objects.
This is often not what you want in certain APIs, so the main REST API, or any other specific API can of course be engineered to be some view / projection of the RM, even to the extent of not exposing the EHR at all, but rather EHR cursor objects or whatever else is convenient. APIs are all about convenience after all, and you can never have too many, I am told
I searched Archie and EHRbase codebases if EHR.compositions is ever used in their code. I’m not surprised that it isn’t. Isn’t this a valid reason to at least consider removing this attribute from the EHR class?
@thomas.beale EHRbase is not materialising EHR.compositions in memory on a server as this could be a large list of objects and because they don’t need this data in the EHR in-memory instance. I believe none of the other CDRs load this list into memory.
I already mentioned that documenting that EHR has COMPOSITIONS is important, but I still believe replacing the discussed attributes with functions is the proper way to do it. The same pattern is already used by other classes.
This is not only about the REST API. It is about the RM specifications.
My question about whether replacing the optional attributes with functions would constitute a breaking change has already been ignored 3 times ( ). If the answer is that this is not a breaking change, my proposal doesn’t affect any implementation. It just brings RM specifications in sync with their de facto use.
Resistance to even considering updating the specifications is unbelievable.
I DON’T have my answer, but I will follow Richard’s lead and move on to the next challenge.