# Understanding how to commit contributions to an EHR Server with XML **Category:** [Technical (archive)](https://discourse.openehr.org/c/technical-archive/156) **Created:** 2012-10-05 18:14 UTC **Views:** 4 **Replies:** 14 **URL:** https://discourse.openehr.org/t/understanding-how-to-commit-contributions-to-an-ehr-server-with-xml/15209 --- ## Post #1 by @pablo Hi all, I'm studying the change_control package to create a simple example of data commit to an EHR Server (to be used in a future course). I'm also reading the service examples published on the wiki (Ocean & Marand EHR Services). As I understand it, when an EMR app (local) wants to commit data to an EHR Server (global/shared), all committed data (e.g. a list of Version) should be referenced by a Contribution. Also, each Version references the container Contribution. All references are managed using OBJECT_REF instances. My idea is to make the commits using XML messages (following openEHR XSDs) with only one message per commit. I don't know if I can represent both references using openEHR XML (Contribution->Version & Version->Contribution). I suppose this operation [1] on the Ocean's EHR Services is resolving both references internally: void CommitContribution(HierObjectId ehrId, AuditDetails commitAudit, OriginalVersion[] versions) Another assumption on that service, is the AuditDetails has the Attestation to sign all the committed Versions (the signature for all the Versions is calculated using the same AuditDetails object). I've seen Version XML examples where the Version has a reference to a Contribution, but the referenced Contribution is a mistery for me :) (it could be really helpful if someone can share an XML example of a Contribution). Any ideas, pointers & corrections are very welcome! (BTW: I don't want to implement a full version-controlled environment, just want to make a simple commit process the right way). [1] http://www.openehr.org/wiki/display/spec/Ocean+Informatics+EHR+Service+Interface --- ## Post #2 by @pablo Hi all, I found there is no CONTRIBUTION XSD defined on the openEHR XDS, and if it exists, I can't commit CONTRIBUTIONs using only one XML message, because CONTRIBUTION references (using OBJECT_REF) the VERSIONs I need to commit, but each VERSION also references (by OBJECT_REF) the container CONTRIBUTION. The main problem here is: the instances of those classes (CONTRIBUTION and VERSION) are distributed objects. So if I send 2 messages to the EHR Server, one to create the CONTRIBUTION and other to create VERSIONs, the fisrt CONTRIBUTION.versions will be empty on the server, so invalid for a while (until it's VERSIONS are committed). So, I'm beginning to suspect that I need a little protocol to be defined here. The other option is to define my own XSD for an envelope that could include both, CONTRIBUTION and it's VERSIONs. I prefer to define a protocol than new custom XSDs. Does anyone that implemented a service like this came to the same conclusion? All your comments will be of great help, thank you. --- ## Post #3 by @system Hi! A CONTRIBUTION points to the IDs of it's contained VERSIONED_OBJECTs and the VERSIONED_OBJECTs at the same time points to their related CONTRIBUTION, thus it is probably easiest to finalize them in the same transaction in most systems if they are stored/retrieved as separate objects. (You have probably already figured that out, I am just trying to avoid misunderstandings by newcomers that might be reading.) In the LiU EEE REST based approach we have added a temporary writing space called "Contribution Builder" where you can add/modify a collection of VERSIONED_OBJECTs until you are satisfied and then make a call to get them committed into the EHR in a combined CONTRIBUTION. Another option is of course to send a collection of VERSIONED_OBJECTs (from a client) with e.g. a bit of XML-wrapping (also including metadata for the CONTRIBUTION). We have not finished specifying and testing an XML serialization for that yet, but that could of course be done (now we use a Java-based object as collection to pass data from the Contribution Builder). I have now uploaded an old XSD (from some experiments 2010) containing definition of CONTRIBUTIONs (and some other stuff) as an attachment to [http://www.openehr.org/wiki/display/dev/Persistence](http://www.openehr.org/wiki/display/dev/Persistence) - It should be considered as an experimental non-official pre-alpha version... (The LiU EEE REST design paper has been submitted for review, see [http://www.openehr.org/wiki/display/projects/Projects+Home](http://www.openehr.org/wiki/display/projects/Projects+Home) Contact me if you need a personal login to our tiny demo-server.) Best regards, Erik Sundvall [erik.sundvall@liu.se](mailto:erik.sundvall@liu.se) [http://www.imt.liu.se/~erisu/](http://www.imt.liu.se/~erisu/) Tel: +46-13-286733 --- ## Post #4 by @thomas.beale to enable this, a small piece of extra XSD would be needed, to define a contribution as a single XML artefact. This doesn't currently exist, but sounds useful. - thomas --- ## Post #5 by @thomas.beale well actually, you need both. The additional XSD part should be relatively easy - it's just a case of modelling a joined up network of objects. You do it by matching up the Contribution Uid references with Composition version uids. A simple outer container structure will be needed I guess. Then you will need an XML-oriented EHR service interface, which contains some of the existing functions (any stateful stuff like login, session setup etc) and functions for committing content, like xmlCommitContribution (XmlContrib aContrib) - thomas --- ## Post #6 by @system Except as an experiment at: [http://www.openehr.org/wiki/download/attachments/786486/EEE-v1.xsd?version=1&modificationDate=1349637658932](http://www.openehr.org/wiki/download/attachments/786486/EEE-v1.xsd?version=1&modificationDate=1349637658932) ...as described in my mail 12 hours ago, did that mail reach the list? Best regards, Erik Sundvall [erik.sundvall@liu.se](mailto:erik.sundvall@liu.se) [http://www.imt.liu.se/~erisu/](http://www.imt.liu.se/~erisu/) Tel: +46-13-286733 --- ## Post #7 by @yampeku Yes it did :\) --- ## Post #8 by @thomas.beale yep, it did - I just read things out of order due to my threading settings ;-) --- ## Post #9 by @Heath_Frankel3 Hi Pablo, You need to understand that some of the RM classes are functional object rather than data objects and hence are not currently considered serializable, VERSION_OBJECT, EHR and perhaps CONTRIBUTION are examples of these. There is no specific statement about this in the specifications, and it can be reconsidered and clarified as we better understand this, but you can recognise classes in this category when they use object references rather than containment. VERSIONED_OBJECT has a counter-part of X_VERSIONED_OBJECT defined in the EHR EXTRACT specification which is serializable and has an existing schema located at [http://www.openehr.org/releases/1.0.2/its/XML-schema/Extract.xsd](http://www.openehr.org/releases/1.0.2/its/XML-schema/Extract.xsd) (linked from [http://www.openehr.org/releases/1.0.2/its/XML-schema/index.html](http://www.openehr.org/releases/1.0.2/its/XML-schema/index.html)). Looking specifically at Contribution, it only has a uid and a list of object references so it isn’t very useful unless you have a use case that wants to list all the contributions for a particular EHR or similar. There may be the need for an X_CONTRIBUTION class in future. The kind of thing you are trying to do is more related to the service model than the Reference Model and as you know there is only vendor specific specifications in this area. From Thomas’ service overview you see there are two layers a EHR Service and a Virtual EHR Service. Not sure it is quite understand what distinguishes the two of these but there is some indication that the Virtual EHR provides aggregation of lower layer services including the EHR and Demographic services while also providing helper functionality such as contribution building and query result management. Another key differentiator is granularity of service calls, the Virtual EHR has fine grained, more frequent calls while the EHR service has course grained, less frequent calls. The Contribution Builder functionality that Erik references fits into the Virtual EHR layer while the CommitContribution operation on the Ocean EHR Service you reference below is at the EHR Service layer. The later expects something like the former to build the contribution to be submitted as a complete contribution. The implementation of the Ocean EHR Service operation below leaves the contribution to be constructed by the EHR Service, however the contribution UID can be specified in the version(s) being committed along with the audit details provided in the operation parameters. So as Erik indicates, the contribution object is finalized in the same transaction as the VERSION objects but the work to build the contribution object is done by the EHR Service. Ocean also has a Virtual EHR service which provides contribution builder functionality, it uses the EHR Service CommitContribution operation to finalize the contribution to storage. So from this perspective, the additional piece of XSD required is actually specified in the service specification as an operation message rather than a RM schema. This can be aligned with the definition of the EHR EXTRACT schema since they are really extract operation messages and we do need to consider how this works in a RESTful paradigm so that we can align the message types used in a SOAP service with a REST service. The problem that I have identified in my implementations over the years is that the use of the openEHR RM classes of AUDIT_DETAILS and VERSION are not very useful in the commit contribution operation, especially if there is some work being done on the service side, whether it is at the Virtual EHR service or EHR Service layer. Attributes such as system_id and time_committed are obvious candidates to be set by the service not by the client but the RM state that these are mandatory and my most recent work provides a service operation message that excludes these from the commit contribution message type but instead has the other RM attributes necessary (e.g. change_type and description) for the service itself to build the valid RM objects to be persisted. This CONTRIBUTION_VERSION class is a potential candidate to be added to the Extract or Service models to support contribution operations. I feel it is truly a high priority for us to start aligning the various implementation APIs ASAP before we get too many more candidates, at least a minimum core set of operations. I think we have enough experience to get this started, I think the process is close to being finalised so now we just need contributors. Heath --- ## Post #10 by @Heath_Frankel3 Hi Erik, I notice that you have provided a schema for VERSIONED_OBJECT which doesn’t align with the RM class and overlaps with the X_VERSIONED_OBJECT already defined in the extract.xsd. I think we should leave VERSIONED_OBJECT as not serializable and use the X_VERSIONED_OBJECT class as the serializable class as what I believe is intended by the specifications. I agree we should add the EHR_STATUS and EHR_ACCESS types, there is an existing issue at SPECPR-26 for this. I like the idea of the extended VERSION_OBJECT classes but this only has value if this can be done in a way that makes the data element strongly typed. Regards Heath --- ## Post #11 by @pablo Hi Erik, Just one correction, CONTRIBUTION points to a ser of VERSION, not VERSIONED_OBJECT. From your & Thomas comments, I've designed this little protocol: 1. createContribution: client sends a XML contribution (based on [EEE-v1.xsd](http://www.openehr.org/wiki/download/attachments/786486/EEE-v1.xsd?version=1&modificationDate=1349637658000)) to the server with references to Versions that will be added later (Versions are in the client) 1. addVersion: adds a Version to a contribution (the XML version is based on openEHR Version.xsd), the reference to the correspondent contribution is in Version.contribution. A contribution is committeable when all referenced versions are added to the server. 1. commitContribution: the client tries to finalize the transaction & the contribution / versions / compositions are added to a EHR on the server (shared record). What do you think of this approach? I think I found an issue (or just a confusion of names) on the specs about object_ids: 1. common_im p. 56 describes VERSION.uid as **owner_id**, creating_system_id, version_tree_id, there is also an operation VERSION.owner_id(). 1. common_im p. 40 says VERSION.**owner_id**() extracts the uid of the owning VERSIONED_OBJECT. 1. common_im p. 46 says the VERSION.uid is **object_id**, creating_system_id, version_tree_id. 1. common_im p. 46 says the **object_id** part of the VERSION.uid is a copy of the uid of the container VERSIONED_OBJECT. 1. common_im p. 53 the **owner_id** attribute is mentioned on VERSIONED_OBJECT to be the EHR id. If I understand the idea: VERSION points to VERSIONED_OBJECT and VERSIONED_OBJECT points to EHR, is that right? What do you think about leaving the name owner_id for the pointer to the EHR and object_id for the pointer to the VERSIONED_OBJECT? --- ## Post #12 by @pablo Hi Heath, thanks for your comments, you mentioned really important issues. --- ## Post #13 by @Heath_Frankel3 Hi Pablo, I think we have an excellent opportunity here to take this offline with Erik to work up a combined logical service specification and RESTful technical service specification as a candidate for the openEHR service model. It looks like you’re looking for a Virtual EHR Service. The other one you may want to look at if you haven’t already is the Marand Think!EHR at [http://openehr.org/wiki/display/spec/Marand+Think%21EHR+service+interface](http://openehr.org/wiki/display/spec/Marand+Think%21EHR+service+interface) (although it is under the EHR Service area I consider this more like a Virtual EHR Service due to its operation granularity). In the interest of consolidation you should consider using something like this but since Erik has already implemented a RESTful service you should be looking at something closer to his API. See comments below. Heath From your & Thomas comments, I've designed this little protocol: 1. createContribution: client sends a XML contribution (based on [EEE-v1.xsd](http://www.openehr.org/wiki/download/attachments/786486/EEE-v1.xsd?version=1&modificationDate=1349637658000)) to the server with references to Versions that will be added later (Versions are in the client) *[HKF: ] Agree, but you may want to not provide any data in this operation like in the Think!EHR specification, since you probably don’t know what the contribution looks like yet, even the commit audit. You can think of this as creating a placeholder to which you versions. Rather than not return a response message you may want to return the empty Contribution object with service side attributes populated such as system_id, contribution uid and a temporary commit_time, this allows you to reference the contribution in subsequent calls.* 1. addVersion: adds a Version to a contribution (the XML version is based on openEHR Version.xsd), the reference to the correspondent contribution is in Version.contribution. A contribution is committeable when all referenced versions are added to the server. __*[HKF: ] The Think!EHR has operations such as CreateComposition and ModifyComposition, perhaps these don’t quite align with a RESTful approach but logically what you are trying to achieve here is some context to apply preconditions ensuring a composition does or does not already exist. It also allows you to just provide the composition object and have the version maintenance done for the caller. Having said that I find that not exposing the version can be a bit limiting at times in more complicated situations.*__ __*The Think!EHR maintains a session context so there is no need to provide a reference to the contribution but in a more stateless paradigm you would need to provide a reference to the contribution, the most obvious place to do this is using the Version object.*__ __*My more recent thinking regarding the response to these operations is to return the updated contribution object since it only has references the versions it contains this is not too verbose.*__ 1. commitContribution: the client tries to finalize the transaction & the contribution / versions / compositions are added to a EHR on the server (shared record). __*[HKF: ] This is where the contribution audit details are more likely to be known, by using the contribution object most recently returned in a previous operation you can submit the entire contribution object to commit its contents. Again the finalized contribution would be returned.*__ What do you think of this approach? I think I found an issue (or just a confusion of names) on the specs about object_ids: 1. common_im p. 56 describes VERSION.uid as **owner_id**, creating_system_id, version_tree_id, there is also an operation VERSION.owner_id(). 1. common_im p. 40 says VERSION.**owner_id**() extracts the uid of the owning VERSIONED_OBJECT. 1. common_im p. 46 says the VERSION.uid is **object_id**, creating_system_id, version_tree_id. 1. common_im p. 46 says the **object_id** part of the VERSION.uid is a copy of the uid of the container VERSIONED_OBJECT. 1. common_im p. 53 the **owner_id** attribute is mentioned on VERSIONED_OBJECT to be the EHR id. If I understand the idea: VERSION points to VERSIONED_OBJECT and VERSIONED_OBJECT points to EHR, is that right? __*[HKF: ] Right*__ What do you think about leaving the name owner_id for the pointer to the EHR and object_id for the pointer to the VERSIONED_OBJECT? *[HKF: ] I think the class specification is not really able to be modified but the descriptive text could be made more clear. I agree that object_id is a better term and a term I use a lot. In the case of the VERSIONED_OBJECT owner_id it needs to be generic because It is used for demographic records (repositories) as well as health records.* --- ## Post #14 by @Heath_Frankel3 Hi Pablo, You need to understand that some of the RM classes are functional object rather than data objects and hence are not currently considered serializable, VERSION_OBJECT, EHR and perhaps CONTRIBUTION are examples of these. There is no specific statement about this in the specifications, and it can be reconsidered and clarified as we better understand this, but you can recognise classes in this category when they use object references rather than containment. VERSIONED_OBJECT has a counter-part of X_VERSIONED_OBJECT defined in the EHR EXTRACT specification which is serializable and has an existing schema located at [http://www.openehr.org/releases/1.0.2/its/XML-schema/Extract.xsd](http://www.openehr.org/releases/1.0.2/its/XML-schema/Extract.xsd) (linked from [http://www.openehr.org/releases/1.0.2/its/XML-schema/index.html](http://www.openehr.org/releases/1.0.2/its/XML-schema/index.html)). Looking specifically at Contribution, it only has a uid and a list of object references so it isn’t very useful unless you have a use case that wants to list all the contributions for a particular EHR or similar. There may be the need for an X_CONTRIBUTION class in future. I _think_ I understand this part, but at the implementation level (and using REST services as plan to do) means some things should be serialized. *[HKF: ] I agree there is a need to serialize the contribution, but we need to understand the true requirements. Do we need a new X_CONTRIBUTION class that contains VERSION objects or is the existing CONTRIBUTION class with object references sufficient for use in the context I suggested in the other email. Collaborative specification and implementation experience will help answer this.* I know there are a lot of ways of serializing things like Versions contained in a Contribution, e.g. I can send different params in the HTTPRequest body, each one being one Version XML (this emulated the Ocean's CommitContribution service), __*[HKF: ] Not sure what you mean here*__ or I can send only one XML on the body for the whole Contribution, this second way is what I try to do). __*[HKF: ] You indicated otherwise in your previous email*__ The kind of thing you are trying to do is more related to the service model than the Reference Model and as you know there is only vendor specific specifications in this area. From Thomas’ service overview you see there are two layers a EHR Service and a Virtual EHR Service. Not sure it is quite understand what distinguishes the two of these but there is some indication that the Virtual EHR provides aggregation of lower layer services including the EHR and Demographic services while also providing helper functionality such as contribution building and query result management. Another key differentiator is granularity of service calls, the Virtual EHR has fine grained, more frequent calls while the EHR service has course grained, less frequent calls. This little project is about a simple EHR Service to commit and retrieve Compositions in XML format (the granularity level here is the Composition). I understand a lot of this has to do with the service, but behind that interface I have to build a persistence layer, so understanding the model is also important (and I'm not an expert on the change_control package, so this is a great learning experience for me too). As I mentioned, I don't want (and I can't) build a complete version controlled EHR server, this is just a little system so my students can play around with my EHRGen tool (I use it to generate different EMR systems), committing/retrieveing compositions to/from a shared EHR server. __*[HKF: ] Which is why it makes sense to align with an existing implementation so that you could look at replacing it with a more enterprise scale implementation in the future.*__ The problem that I have identified in my implementations over the years is that the use of the openEHR RM classes of AUDIT_DETAILS and VERSION are not very useful in the commit contribution operation, especially if there is some work being done on the service side, whether it is at the Virtual EHR service or EHR Service layer. Attributes such as system_id and time_committed are obvious candidates to be set by the service not by the client but the RM state that these are mandatory and my most recent work provides a service operation message that excludes these from the commit contribution message type but instead has the other RM attributes necessary (e.g. change_type and description) for the service itself to build the valid RM objects to be persisted. This CONTRIBUTION_VERSION class is a potential candidate to be added to the Extract or Service models to support contribution operations. I found the same problem: the change_control objects are distributed objects, so at one moment in time some parts of an object may be on the server, some other parts on the client and other parts not yet created. This is very unclear on the specs since it lacks time based diagrams to show what objects are created at what time and when. This could be a good improvement to the specs, what do you think? __*[HKF: ] I think we can look at this as we develop a service model specification and an online reference implementation will demonstrate this in practice.*__ I feel it is truly a high priority for us to start aligning the various implementation APIs ASAP before we get too many more candidates, at least a minimum core set of operations. I think we have enough experience to get this started, I think the process is close to being finalised so now we just need contributors. Let me know if I can help and how. I'm always open to collaboration :D __*[HKF: ] As I said in the last response, I think you little project is a good opportunity to collaborate and test an openEHR service model candidate*__ Heath --- ## Post #15 by @pablo Hi Heath, sorry for the delay, a new project came up :) I'm available to discuss this offline and really want to help on this topic. In the meantime, I've tested some stuff here, simplified my previous proposed protocol to only one operation: commit(UID ehrId, List versions) This operation is included in a REST interface and I plan to support the same operations in a SOAP interface. The REST interface includes operations to get patient information (demographics and ehr stuff are on the same app right now), get patient's ehr, get ehr compositions, etc. I also tested some query building and testing capabilties over XML compositions. I can send you some screen shots of these tests (I have a simple query bulider, a simple chart view to graph dv_quantities returned on query results, and query results rendered as tables. I also created a small EMR app for data input that generates openEHR XML and commits them to the server using commit(ehrId, versions). These stuff is *very* basic, but is a start, and helped me big time in understanding a lot about the version control and service model. Heath & Erik, please feel free to send me a PM at pablo.pazos@cabolabs.com to talk more about this on a specs level. Kind regards, Pablo. --- **Canonical:** https://discourse.openehr.org/t/understanding-how-to-commit-contributions-to-an-ehr-server-with-xml/15209 **Original content:** https://discourse.openehr.org/t/understanding-how-to-commit-contributions-to-an-ehr-server-with-xml/15209