I just wanted to follow up on this thread. Our outreach team draws a map of where each patient lives when the patient is enrolled. This map is later used to track a patient who becomes lost to follow-up. We are hoping to include images of these maps in OpenMRS. We were hoping to use the rest api to get and post images to OpenMRS. But after reading this thread, it seems like this may not be possible? Anyone have any success use the REST API to get and post images without making changes to the core?
First of all there is no ‘image REST resource’, so the short answer is no.
However you can save images as complex obs of course. But I can say, for having played a bit with this for VDUI, that the current implementation of the obs resource doesn’t quite handle the case of complex obs. For instance we had to create a custom ComplexObsResource extending ObsResource to properly handle deletion and certain types of edits. See here.
By the way this example shows that you don’t really have to worry about (not the core but) the REST Web Services module, you can just add resources or extend existing resources through your own module(s) anyway.
In the context of VDUI I scratched my head a lot over this one: should I really be text book REST-compliant for the upload/download of the data behind the complex obs?
This would mean Base64-encoding/decoding all the time. At first I thought that there would be a performance issue, and there is one but I don’t think it is really meaningful. However for VDUI this option was not really working anyway since not every content can just be Base64-encoded, especially when you don’t know in advance which MIME types you will have to handle. And that’s the use case for VDUI: it implements the handling of certain MIME types in a specific way but otherwise it deals with the content in a generic manner.
But if you know that you will always deal with images, then you can certainly create - say - an ImageObsResource and ensure that POST, GET, DELETE… etc are implemented according to your needs.
Let’s take another look at it. We’d like to implement RESTWS-297.
The approach suggested in the issue description and relevant issue in openmrs-api TRUNK-4964 doesn’t sound right to me.
I suggest not to use over-engineered dedicated handlers from openmrs-api and instead always use BinaryDataHandler to store files POSTed by regular HTTP means as multipart/form-data instead of encoding them in JSON payloads. It’s a client, who sends data and gets it back that best knows how to handle that data.
+100 for not over-engineering. However either with the multipart or the Base64 approach, I believe it requires changes in core and of course in REST due to the nature of POST (using reflection instead of static setters).
Side note: this is something we are going to need at PIH shortly as well. I need to catch up on this thread, but I tagged RESTWS-297 as something we could potentially work on during the OMRS16 hackathon.
Not all Obs use a binary data handler, so we can’t use a single handler to accomplish this, also note that Obs are immutable, it would be wrong to have to update them just to set the complex data since it would happen in a separate http resuest, one should be able to post an Obs along with its complex data in one rest call to avoid ‘updating’ it which otherwise would result in a void and create new operation, for this reason we need to update the core api for it to be possible
If I’m understanding you right, this is a no-go. Concepts are free to declare any type of handler, and the REST API needs to support all of them.
I would think we must support a POST of json-encoded binary data (since this is the “easiest” for a REST API client, right?), and we could also support multipart/form-data as a nice-to-have.
But the job of taking these posts, extracting the data, and streaming it to into the underlying Java API should be solvable purely in the REST module without needing to change the Java interfaces, right?
Also, creating or updating an obs with complex data should be doable as a single REST call that works atomically.
@darius or anyone who used handlers, would you care to explain what is the reasoning behind having different handlers in openmrs-api? Why do we need them? I don’t quite understand the concept behind them…
Here’s the only place where I found the usage of ImageHandler:
As it occurs to me in this example the only purpose of the handler is to indicate that it is an image. The methods implemented by the handler doesn’t seem to be used at all…
Anyway, I think I know how to handle it now and can do a first stub at implementing it. I don’t see a need to change openmrs-api at the moment to address the issue.
Adding support for base64 json-encoded binary data should be easy as well, though it should be used for smaller files only as it increases bandwidth usage by ~30%.
@raff, you’re not wrong to say that the ComplexObsHandler interface is overengineered.
The key historical point is that Burke designed it long long ago (before 17 Aug 2010, when we switched from Ant to Maven). The intention was that intelligent handlers for different datatypes in the API could support multiple views in different UIs.
(It holds up pretty well for having been written >6 years ago.)
Great @raff, I like a lot that you’ve gone through the two possibilities: (1) either everything embedded in the JSON or (2) any byte array added as a POST request file alongside the JSON.
In the latter, could you explain how this new upload(..) method is triggered even though you simply save the complex obs through the usual URI?
Is it Spring that knows that if the input is a MultipartFile then it has got to be the only possible route since that’s the only method having this type as an argument?