Requirement for a random UUID during POST

Hello Team,

This attempt has been to create a new Patient by POSTing a JSON payload using an API client (POSTMAN in this case) to a locally running OpenMRS SDK server (2.12.2) with the latest FHIR2 module installed.

The first JSON that was POSTed to the end-point “http://localhost:8080/openmrs/ws/fhir2/R4/Patient” was like below:

{
  "resourceType": "Patient",
  "identifier": {
    "extension": [{
      "url": "http://fhir.openmrs.org/ext/patient/identifier#location",
      "valueReference": {
        "reference": "Location/58c57d25-8d39-41ab-8422-108a0c277d98",
        "type": "Location"
      }
    }],
    "use": "official",
    "type": {
      "text": "OpenMRS ID"
    },
    "value": "1000GW"   
  },
  "name": [
    {
      "given": [
        "Myname"
      ],
      "family": "MyFam"
    }
  ],
  "gender": "male",
  "birthDate": "1998-07-08",
  "address": [
    {
      "state": "Mystate",
      "city": "MyCity",
      "country": "MyCountry"
    }
  ]
}

This was returning a 500 server error: “Failed to call access method: org.hibernate.exception.ConstraintViolationException: could not execute statement

Next, as suggested by a TALK thread, a randomly generated UUID was added to all the main elements of the JSON like below:

{
  "resourceType": "Patient",
  "identifier": {
    "extension": [{
      "url": "http://fhir.openmrs.org/ext/patient/identifier#location",
      "valueReference": {
        "reference": "Location/58c57d25-8d39-41ab-8422-108a0c277d98",
        "type": "Location"
      }
    }],
    "use": "official",
    "type": {
      "text": "OpenMRS ID"
    },
    "value": "1000GW",
    "id": "7c7e89db-538a-411a-a1e2-4fdff74a3a86"
  },
  "name": [
    {
      "given": [
        "Myname"
      ],
      "family": "MyFam",
      "id": "7c7e89db-538a-411a-a1e2-4fdff74a3a86"
    }
  ],
  "gender": "male",
  "birthDate": "1998-07-08",
  "address": [
    {
      "state": "Mystate",
      "city": "MyCity",
      "country": "MyCountry",
      "id": "7c7e89db-538a-411a-a1e2-4fdff74a3a86"
    }
  ]
}

The second POST was successful. The question here is regarding the UUID that needs to be added to the JSON: What purpose is it really serving? It never gets used later and does not become a part of the Patient record in any way. To retrieve the newly created Patient the UUID that needs to be used is a totally different one (which gets alloted by the server during POST).

Thank you.

This sure sounds like a bug. I would assume that (1) you shouldn’t need to supply a UUID when creating a patient + person and (2) if you do supply a UUID it would be used as the UUID.

/cc @ibacher

well some two things you need to be curious about is

  • make sure that a Location with UUID: 58c57d25-8d39-41ab-8422-108a0c277d98 exists. You can check this with a with GET to /openmrs/ws/rest/v1/location/58c57d25-8d39-41ab-8422-108a0c277d98 on the same running server.
  • make sure that "value": "1000GW" is not assigned to any other patient as it is mapped to the patient-identifier.

I happened to work on a Fhir-Patient-Resource but a random-UUID was generated on every successful post

Both the things you have mentioned have been taken care of:

The location with the particular UUID (58c57d25-8d39-41ab-8422-108a0c277d98) does exist on the server and the OpenMRS ID with the value “1000GW” has not been allotted to any other patient.

Otherwise the second POST that I have mentioned would not have been successful. Please note that the second POST was ‘Successful’ with the above location UUID and OpenMRS ID.

Also, after the second POST that I have mentioned a new UUID does get generated for the Patient resource and this needs to be used to GET back the Patient.

Thanks!

@burke Yes that is true. There is no need to supply a UUID during POST as a new UUID gets allotted by the server any way. In this situation, for some reason the need for a dummy UUID is being enforced during POST and that dummy UUID does not get utilised during any future calls to the Server.

Another thing to note @nischith

  • On every post, the patient resource is first translated to its OMRS type, (FHIR_Patient is translated to Openmrs_Patient) saved, translated back to its FHIR-type and then returned to the caller.

  • So the "id": "7c7e89db-538a-411a-a1e2-4fdff74a3a86", supplied here becomes the UUID of the OpenMRS Patient Identifier.

  • In OpenMRS, a patient is mapped to an Identifier whose UUID must not be null.

  • Possibly, currentPatient.setUuid(patient.getId()) assigns a null to the org.openmrs.PatientIdenfier Table hence the server complains with 500 constraints violation with the first Payload.

PS A new UUID is generated for every patient resource in case the payload didn’t set the id Property. openmrs-module-fhir2/BaseFhirService.java at master · openmrs/openmrs-module-fhir2 · GitHub so the id you supplied in the second payload becomes the PatientIdentifier uuid and not the Patient uuid

@jnsereko

Yes, the explanation that you have given does seem correct and it clarifies a lot of things. The mandatory id that needs to be supplied is the UUID of the Patient identifier type.

Apart from this, a few observervations that I want to share are:

  1. The JSON payload of the second POST (mentioned by me earlier) works well but is probably not according to the Patient resource structure defined by FHIR and may be Identifier type UUID (if needed) needs to be defined as a new Extension.

  2. May be it is enough to mention either the Identifier type name or the Identifier type UUID in the JSON payload and there is no need to mention both.

  3. As of now the Identifier type UUID needs to be a part of all the three JSON elements/ fields namely: “identifier”, “name” and “address”. May be one mention of the Identifier type UUID should be sufficient (as part of the “identifier” field).

But, thanks a lot for the solution @jnsereko!

1 Like

If this really is the UUID of the OpenMRS Patient Identifier then it should be the same for two Patients both using OpenMRS IDs. But the server throws an error if it is the same for two Patients and demands a different UUID every time.

@jnsereko hope you see the issue here. Please let me know what you think.

What i am sure of is that every patient should have a unique identifier uuid…

May be we should add ability to randomly generate a Patient_Identifier_uuid in case id was is null, just like the way it was done at https://github.com/openmrs/openmrs-module-fhir2/blob/master/api/src/main/java/org/openmrs/module/fhir2/api/impl/BaseFhirService.java#L82

@jnsereko I tried looking around for a reasonable explanation for this but could not find one. There already is a unique Patient UUID to identify every Patient record. So, why is there a need for another unique Identifier UUID? this unique Identifier UUID never gets used later in any future calls to the server, so what purpose is it really serving?

Thanks!

Short version: Every OpenMRS object has a UUID associated with it. So each patient has a UUID (really the UUID of the Person), each Patient Identifier has a UUID because the patient identifier is a different object from the patient itself (and separately addressable via the REST interface or Java API). You definitely may end up reusing the patient identifier UUID if you need to update the identifier object (API docs).

The reason we have UUIDs for every object is so we can unique refer to the instance of that object. This is especially important for issues like synching data between OpenMRS instances (how do I know which ID this is?).

The FHIR API probably shouldn’t be requiring you to create those when creating a patient… I had thought that because everything derives from BaseOpenmrsObject and BaseOpenmrsObject populates the UUID in it’s constructor, there shouldn’t really be any need to supply the UUID. I don’t know why this doesn’t work. It can be reported as an issue in our issue tracker.

@ibacher Thanks a lot for all the details. So, it is more of a OpenMRS requirement than a FHIR one.

As discussed earlier in this thread, probably the approach of allotting a UUID for every Object if none is supplied during POST should work and this should happen in the appropriate Translator Classes.

If the Patient UUID is NULL during a CREATE/ POST operation, a UUID gets alloted by the server here

I was thinking of applying a similar approach to every Object in the Translator Classes.

As suggested, I will go ahead and create a Ticket for this and start working on it.

Thanks again!

A Ticket has been created at:

https://issues.openmrs.org/browse/FM2-482

@ibacher Though BaseOpenmrsObject populates the UUID in its constructor, that value can get overwritten in places like this

So, what happens here is that a null value will replace the Patient Identifier UUID assigned by BaseOpenmrsObject if the Patient CREATE/ POST JSON payload doesn’t explicitly have a Patient Identifier UUID.

Similarly for the other JSON objects.

I will update the Ticket with this information and if things seem alright I could submit a PR to fix this.

Thanks!

I suppose that explains it. Better to do something like:

if (identifier.hasId()) {
    patientIdentifier.setUuid(identifier.getId());
}

Yes and that if block needs to be applied to all the Objects. I have made the changes and will be submitting a Pull request soon.

Accordingly, a PR has been submitted at: