The documentation points to using ImageHandler to get the ComplexData out of a saved complex obs (images in my case). So I registered ImageHandler with the concept complex that I use to save images.
But how does that fit with REST webservices? Is there any service out there that would return the complex data when provided a complex obs’s UUID?
When using uicommons’s Angular wrapper for the obs REST service, I only see this as the value:
Which is generated by ImageHandler and is my image’s metadata, but how do I get back the image as a byte[]?
I have already looked around a little but Bahmni doesn’t seem to be using complex obs, and openmrs-module-patientimage uses person attributes.
I don’t think ImagenHandler can help you in any way. The obs services requires an input stream to be open in the controller, the key point is how to obtain the binary contents from the JSON payload (my proposal was to send it Base64 encoded).
But is there somewhere a web service that could already do that? Even if it is not RESTful then, for the time being. By ‘that’ I mean returning the saved complex data given the obs UUID?
Look at what is suggested in this article (‘Complex Obs Support’) under WebImageHandler.
Isn’t that what this ComplexObsServlet already does?
Note that I have already handled the upload, and I’m not using any existing REST service indeed. I have implemented my own controller receiving a MultipartFile from the client. I was just wondering if there was a way to get back the saved complex obs?
It seems that RESTWS-297 is about saving a complex obs.
I suppose you can use the existing servlet for retrieving the complex obs data.
IIRC there was a controller to save the obs but I can’t find it in core (nor the JSP).
I am mildly keen on bringing a dependency on openmrs-module-legacyui just because of this servlet. I may just then copy the parts that I find useful for our use case.
But thanks for confirming that this servlet is indeed the way to go, as per the current state of things.
@darius, @lluismf, I could look into bringing the missing bits in openmrs-module-webservices.rest if you could point me in the right direction.
The servlet already exists in core but only implements doGet (not doPost). To reuse the post then you need the controller in legacyui (or create your own). That’s why it seems interesting to add a doPost in the complex obs servlet.
There was a discussion months ago about how to implement this in REST but no agreement was reached. IMO passing the contents in Base64 is easy (but slower). To be honest I don’t really know what’s the best solution to send binary data in a REST call.
Unfortunately ComplexObsServlet takes an internal obs ID as an input parameter.
Is there a simple way to get an obs’s UUID from its internal ID? I don’t seem to find the internal ID anywhere in the full JSON representation of an obs.
Actually it would be simpler, just open a stream (Base64InputStream?) and invoke the Complex Obs API that will do this work for you (reading the stream and creating a file in the complex obs repository).
The problem with doing this in a generic way, is that you need to know the mimeType of the incoming stream or Base64. It may not always be an image and there may not be an appropriate xxxHandler for it. I think our approach of using a xxxHandler was an example of over-engineering.
It should be left to the client to provide the Accept type and open the complex obs in any way that they can. The server doesn’t need to know what Handler is required.
I recommend that you use something like Apache Tika, to detect the stream and set the appropriate contentType when sending the complexObs
Thanks guys for your input.
Whilst developing a Patient Images module I was wondering whether I should try to make it as REST/JSON friendly as possible, hence this thread. But I won’t go down that route, I am just extending core’s ImageHandler and using a custom PatientImageComplexData and that is enough for now and for our needs.
I saw that from core 1.12+ ComplexData holds a mime type member, which is something I needed and that I added to my extending class.
(Q.) Any chance that this could be backported to 1.11.x?
@sunbiz, I came across Apache Tika too and I eventually settled for a quick workaround without using it, and that was enough for our needs.
However when I was working on the content type detection (and mapping to file extensions) I wanted to bring it as a dependency and I was hitting this issue that it was not found on OpenMRS Nexus repo.
On our organization we are trying something similar. We want to connect a third party desktop application (Ultrasound Image software) with OpenMRS, so everytime we obtain an ultrasound image from pregnant women, the third party software would store (upload) this image on a OpenMRS database associating it with the encounters, patients, … we previously created.
Our first approach was to do this through the REST API (GET would obtain info about the person and concept uuids and POST would create the obs), but after reading the whole thread doesn’t seem to be a good approach anymore.
So my question is, how is the easiest way to achieve this in your opinion?
The only reason why I am turning away from REST is because I have extended core’s ImageHandler, and ImageHandler saves images (byte[]) on the disk.
The consequence is that wiring Base64 encoded JSON payloads between server and client would require encoding and decoding those images every time they are being manipulated. After a quick trial on the download side only, I found that the performance loss was not worth it at all.
However, if you don’t care about ImageHandler and that you use some other handler that somehow saves the Base64 encoded content on the disk, then you can certainly go that way.
Be advised that there is currently no REST POST interface to do so, but it is fairly trivial to implement it anyway. At least it was really trivial to implement it for GET when I was experimenting with it.