O3: Cohort Endpoint Support

Hi There,

I’m trying to create a tool to quickly create a group of patients for use in the Group Sessions widget in use by ICRC. Broadly the task is to say “I want to create a new group”, set a group name, location, and select some patients which should be in the group. Here is what the mock up currently looks like

Currently there are two endpoints that this could be acheived with. POST ws/rest/v1/cohortm/cohort to create a cohort and POST ws/rest/v1/cohortm/ to add members to a cohort one by one after it is created.

I tried the first with body {“name”:“Magenta”,“cohortType”:“hello”} and got a response message: "[Some required properties are missing: location, definitionHandlerClassname, startDate]", and again with {"name": "Magenta", "location": "44c3efb0-2583-4c80-a79e-1f756a03c0a1"} and got response org.openmrs.module.webservices.rest.web.response.ConversionException: location on class org.openmrs.module.cohort.CohortM\n\tat org.openmrs.module.webservices.rest.web.resource.impl.BaseDelegatingResource.setProperty(BaseDelegatingResource.java:800)\n\.... I could be using this endpoint incorrectly, but it is hard to tell from the current documentation.

Even if that endpoint was working, for the workflow for this feature to work it would require 1 network requests to generate a cohort, followed by N async requests to fill in members one by one. I believe it would be much cleaner to support a new endpoint which would be passed the cohort metadata and a list of members in order to create the cohort and make links in one request. This would serve a better user experience.

Would it be possible to make such an endpoint?

Thank you, Zac

Example payload:

{
  "name": "Name of the new cohort",
  "location": "location-uuid",
  "members": [
    "uuid-1", "uuid-2", "uuid-3"
  ]
}

Generally, it’s pretty easy to create an endpoint that can take a set of sub-resources on creation. What’s harder to figure out is how things should work for updates. For example if you create a Cohort with cohortMembers: [a, b, c] and then later update the cohort with cohortMembers: [c, d] what’s the expected outcome? Do we:

  1. Add d
  2. Replace [a, b, c] with [c, d]

I’m not always sure what the right operation is. Right now, the 3.1.0-SNAPSHOT version of the Cohort module has an attempt to implement 2 above. Hopefully we can iterate a bit a figure out what makes sense here.

1 Like

I hadn’t even thought of the update action. For that I would be in favor of option 2. if a cohortUuid is passed as a payload key the endpoint can recognize it as a “replace” action and updates using method 2 as you stated above.

Here’s what would make sense to me for a REST API’s behavior in managing a list of members:

Method Behavior
POST Add members. Anyone already in the cohort is ignored. Anyone already in the cohort, but not in the given list remains in the cohort – i.e., if you post [B,C] to a cohort containing [A,B], the cohort becomes [A,B,C].
PUT Change memberships to the given list. Any members in the cohort and not in the given list are removed, any already in the cohort are left unchanged, and any new entries are added.
DELETE Any members in the list are removed. Any members who aren’t in the cohort are ignored
1 Like

@burke that’s a classic REST approach, which I also appreciate. @ibacher what is your preference here?

To me, those semantics make sense, but only if we have a separate /cohort/12345/members resource. I might also swap the POST and PUT semantics, but I feel less strongly about that.

So, what makes the most sense to me is probably something like this:

POST to /cohort (i.e., Cohort create) we accept a members property to initially populate the cohort.

POST to /cohort/12345 should probably be treated as invalid.

PUT to /cohort/12345, if it takes a list of members should replace the members with the list (so any existing members not in the list are removed; any new members are added).

DELETE request to /cohort/12345 either does a soft-delete or hard-delete of the Cohort and consequently of the memberships. (I’m suspicious of request bodies being sent with DELETE requests).

If we want to get fancy with list management, we should probably look into supporting the PATCH verb and JSON Patch or XML Patch to describe the changes (add this member, remove that one, etc.).

But we’re also a bit constrained by what the REST module already supports…

@dkayiwa could you take ownership of reviewing & resolving this endpoint need?

Hello, The cohort builder’s save cohort also required the same behaviour. I created this thread and started working on this. But I’m still trying to understand how the O3 rest module works. So I might need some help.

Here’s the issue I created. https://issues.openmrs.org/browse/RESTWS-898

1 Like

@dkayiwa would you be able to support @anjisvj to complete this work?

(Side note; Daniel is offline at the moment, so I imagine we’ll hear from him on monday :slight_smile: )

1 Like

During a call this morning @ibacher was saying that this might actually be supported already via cohortm/cohort endpoint, but wasn’t sure what the payload should look like. If anyone can post an example working request that would be sufficient to solve this :slight_smile: . Bonus points for adding it to the documentation.

@zacbutko i have removed the requirement for startDate,cohortType,location,definitionHandlerClassname and therefore you show now be able to create the cohort and its members with something like below:

{ "name": "Name of the new cohort", "cohortMembers": [{ "patient": "432edc73-26be-433b-84e6-18341a87d994" }] }

And attached is a sample module to test with: cohort-3.1.0-SNAPSHOT.omod (81.9 KB)

3 Likes

Hi @dkayiwa , This endpoint is still not working on dev3.

Using a POST to https://dev3.openmrs.org/openmrs/ws/rest/v1/cohortm/cohort with body { "name": "Name of the new cohort", "cohortMembers": [{ "patient": "8648a68d-1d68-4293-9d1a-a7a188b91418" }] } raw encoding JSON format. (text also doesn’t work) gives 400 error

"error": { "message": "[cohortMembers on class org.openmrs.module.cohort.CohortM]", "code": "org.openmrs.module.webservices.rest.web.resource.impl.BaseDelegatingResource:800", "detail": "org.openmrs.module.webservices.rest.web.response.ConversionException: cohortMembers on class org.openmrs.module.cohort.CohortM\n\tat org.openmrs.module.webservices.rest.web.resource.impl.BaseDelegatingResource.setProperty(BaseDelegatingResource.java:800)\n\tat org.ope...

@zacbutko i did run this CI build Reference Application - Distribution 3.x 206: Build result summary - OpenMRS Bamboo but although it runs successfully, it did not update the dev3 instance. That is exactly why i attached the compiled module, just incase you have another backend server to test it with.

1 Like

@dkayiwa @raff any idea why this is?

@dkayiwa @grace pushing to dev3 should be fixed now. I set a wrong image name for backend and needed to correct it.

1 Like

Hi @raff , do you know what button I can press to deploy to dev3?

@zacbutko it’s deployed by default in the Deploy step by Reference Application - Distribution 3.x - Deploy 215: Job result summary - OpenMRS Bamboo

Wait, then I’m confused. Doesn’t that mean that the endpoint should be working now? I’m still getting a 400 for POST to https://dev3.openmrs.org/openmrs/ws/rest/v1/cohortm/cohort with error

“error”: { “message”: “[cohortMembers on class org.openmrs.module.cohort.CohortM => patient on class org.openmrs.module.cohort.CohortMember => Privileges required: Get Patients]”, “code”: “org.openmrs.module.webservices.rest.web.resource.impl.BaseDelegatingResource:800”,

@dkayiwa, I couldn’t find a commit with the fix. Which commit should be deployed? Is the right version included in openmrs-distro-referenceapplication/pom.xml at master · openmrs/openmrs-distro-referenceapplication · GitHub ?

@zacbutko are you providing correct credentials?