Background
OpenMRS has an explicit API which has not been cleanly or explicitly exposed through web services. We have a REST module and SOAP-based module(s) where folks have done work in the area. We need a clear and explicit strategy for supporting web services.
Requirements
- A single OpenMRS module to support the core web service needs.
- This module will follow a RESTful approach
- The framework should allow new web service methods to be added with minimal effort
- At this point, we can leave the Java objects with Hibernate magic (all object properties assumed to exist) and convert the data to DTOs from our module. These DTOs may inform how we transform our API in the future though.
- Requirements for Version 1 of this module
API Service and Object Design
Action Plan
- Web services will be developed as an augmentation to the existing API... that is, we will not rewrite the current API and then expose them as web services... we will write the web services as an independent activity, hoping that they inform the further maintenance and redevelopment of the existing API.
- Support OAuth or an equivalent authentication scheme
- An upcoming web services sprint is scheduled. See Development Sprints and the ws sprint page: 2011-05-16 Development Sprint
Interested Parties and Mentors
Ben Wolfe (mentor)
Burke Mamlin
Darius Jazayeri
Saptarshi Purkayastha
See Also
Result / Output
See the REST Module for the documentation and final output.
9 Comments
Burke Mamlin
We need to find out what the convention is for REST-based service when creating objects. Is a handle for the new object returned in the response? Or is a redirect used? We're assuming errors are handled through HTTP error codes +/- response data about the error.
Roger Friedman
From what I've seen, most RESTful creates and edits return the created/edited object, so that if new objects are created, their IDs and history data and unsent required-with-default data will be created on the host side and returned as part of the object.
Darius Jazayeri
Thought examples:
1. Creating an encounter with observations
REST 1:
* POST to "patient/PATIENT_ID/encounters" with encounter metadata as parameters,
* then repeatedly POST to "patient/PATIENT_ID/encounters/ENCOUNTER_ID/obs"
REST 2: POST to "patient/PATIENT_ID/encounters" with xml the includes encounter metadata and obs
SOAP 1: web method call to createEncounter(EncounterDTO)
SOAP 2:
* web method call to createEncounter(patient, location, date, type)
* then repeated web method calls to createObs(encounter, obsDetails...)
2. Enrolling a patient in a program
REST: POST to "programs/PROGRAM_ID/enrollPatient" with patient=PATIENT_ID&date=DATE
SOAP: web method call to enrollPatientInProgram(patient, program, date)
Paul Biondich
So, Saptarshi... sitting here in a design conversation with Burke, Ben, and Darius... here are some questions/suggestions for you:
Darius Jazayeri
Questions for experts:
Ben Wolfe
e.g. getPatient(123, [includeProperties: ["preferredName", "birthdate", "gender"]])
My fear is that this ties the implementation to property names too closely. If we decide to change the model, these method calls fail. (or fail silently I suppose)
Darius Jazayeri
Iterating on Ben's last comment (notes here):
Random thoughts and comments
Domain Objects
Domain objects have:
CRUD method templates for domain object Xyz
Concept, as a fully-worked example
Concept Properties
Standard CRUD, applied to Concept
Other retrieval methods:
Collection properties of Concept
Concept names
Concept set members needs work
Concept subclasses (ConceptNumeric, ConceptComplex)
Question for the experts: which path to take for Concept subclasses?
Burke Mamlin
Do we want to consider addNamesToConcept() in addition or instead of addNameToConcept()?
Burke Mamlin
Darius, thanks for the documentation. FYI – I moved your notes to this page and did a little reformatting/tweaking.