Fetching complex obs's data via Angular/REST?

Tags: #<Tag:0x00007f299904fca8> #<Tag:0x00007f299904fb68>

@mksd, yes, you just need to upgrade RESTWS. The code is not released yet so you need to use 2.17-SNAPSHOT. Looking forward to your feedback.

Hey @mogoodrich (and @mseaton)

Have you ever had a chance to try out VDUI 1.1 then? This one is Core 1.10.2+ compatible and we would be really curious to know if PIH would find use in it, or what would be missing to it to make it more useable. Your feedback would be highly appreciated and valued.

I also intend to use @raff’s Uploadable's pattern on the VisitDocumentResource to get it closer to being 100% REST compliant.

Acknowledgments for the Uploadable interface go to @gutkowski :slight_smile:

Sorry, @mksd, I never did have a chance to look at this again, but thanks for the reminder. I did just confirm that it does fire up properly now in OpenMRS 1.10.4, thanks for that! I’ll see if I can get it integrated and have our team take a look at it in the coming weeks.

Take care, Mark

1 Like

I commented on the commit, I think it’s wrong to assume that all complex data will be encoded as base 64, some complex data can be very large and will only get much larger after encoding it as base 64, so in such cases we would expect a client to specify the value as a unique identifier that an obs handler can use to obtain the actual data, could be from another source e.g via http using the identifier, this is the primary reason why we want the rest API to leave the business of decoding the value into complex data to the obs handlers.

@raff should confirm but I believe that his commits allow for both ways. One can wire the complex data as Base64 encoded content within the JSON request/responses ; or can wire any file alongside the JSON (leveraging the Uploadable pattern).

Not much larger, about 30% more. If you’re really uploading a very large image that takes 15 min to upload, it’s not a drama to wait 5 min. more.

The issue is not really space as such, it’s more to do with the fact that as a developer I should be able to post a complex Obs with a unique reference to complex data as a value that my obs handle can take and know how to use it to fetch the actual complex data

I don’t get it. How do you upload the complex data in the first place?

@wyclif, have a look at 2 tests at https://github.com/openmrs/openmrs-module-webservices.rest/blob/master/omod-1.9/src/test/java/org/openmrs/module/webservices/rest/web/v1_0/controller/openmrs1_9/ObsController1_9Test.java#L119-L162

It should be then clear that you can post your file either as base64 embedded in json or “as is” using the multipart/form-data approach. You always fetch the file as is from /obs/(uuid)/value (it’s never encoded in base64 when you fetch it back).

1 Like

@raff I think that Wyclif is suggesting you should be able to post Obs.valueComplex and have this stored verbatim.

This means that the client of the API must provide the URI where the complex obs data is stored right? And currently if I’m not wrong is just a file path. I don’t think it’s a good idea.

@lluismf why do you think that it is not a good idea? Am asking for simply learning purposes. :smile:

IMHO the location of the complex observations should be transparent for the client of the API. Now it’s the file system, in the future it can be a CMS repository or any other persistence mechanism.

@lluismf my understanding was that the location being referred to here is the source (which the client has to know), not destination (where openmrs eventually stores it)

What am trying to say is that I should be able to post a complex obs with the value as a unique identifier and not really the actual complex data itself. E.g I would like to post a complex obs where the value is a uuid for instance, in this case only my obs handler would know how to look up the actual complex data by this uuid, it could be from a rest end point, it could be from the file system, the point is it shouldn’t be rest API to figure this out but rather the obs handler.

There is value in supporting the behavior above, one is that it’s very likely that complex data like documents are stored in shared document repositories which are usually separate systems, in this case only an obs handler can really find the document. In resource constrained areas or those with low internet speeds, I believe they would prefer to use unique references to complex data and not have to post actual complex data especially when it starts getting large in size.

Okay, got you @wyclif. The code I committed can be further extended to support your use case of passing identifiers/uris. I think it deserves a separate issue.

As for now we have support for passing base64 encoded binary data in json or posting a file as is through the form-data approach. One can also fetch binary data stored on the server as is at /obs/{uuid}/value (the link is provided in the /obs/{uuid} response under the value field).

I am little confused about the REST resource for Complex Obs. I am referring to 2 source files in webservices rest.

  1. ObsResource1_8
  2. ObsComplexValueController1_8

In ObsResource1_8, why do we assume that the complex value will always be raw data (raw view)? Do we assume that the valueComplex always to be serialized content? What if it was a json block or a reference to a “location” or “address_entry” or “provider” etc? Also the value representation for “RAW VIEW” gives out very little information about the data to be fetched from /obs/{uuid}/value.

       "value": {
            "display": "raw file",
            "links": {
                "rel": "self",
                "uri": "http://localhost:8080/openmrs/ws/rest/v1/obs/e2821620-66ff-11e7-9951-0242ac110002/value"
            }
        }

IMHO, it ought to give out more info. maybe - display should be the string interpretation of the data, or indication of what type of value the /value will return.

       "value": {
            "display": "Location: General OPD",
            "links": {
                "rel": "self",
                "type": "application/json",
                "uri": "http://localhost:8080/openmrs/ws/rest/v1/obs/e2821620-66ff-11e7-9951-0242ac110002/value"
            }
        }

I would expect corresponding behavior from the “ObsComplexValueController”. The code gives impression [ObsComplexValueController.getFile()] that the expected content is a file. Depending on the “accept” header (led by the previous link type), the corresponding type should be serialized and sent and not just byte stream (file or image). e.g. for “application/json” serialize to a json response.

Thoughts? Of course the above arguments are not valid if you are saying that valueComplex to be always serialized content (and not meant for references to another resource or a complex representation through JSON).

So we do want to support passing not only raw data, but I haven’t had time to implement it. RAW_VIEW is supported by all handlers (although not enforced by API, see TRUNK-5020), thus it got prioritized. We have the following handlers in openmrs-core https://github.com/openmrs/openmrs-core/tree/master/api/src/main/java/org/openmrs/obs/handler so there’s nothing to support jsons or uris out of the box. The closest it gets is the text handler.

I’d suggest creating 2 issues for openmrs-core to add json and uri handlers. It would be handy not to have to post jsons or uirs as base64 so I’d add a line checking if the value is base64 encoded or not somewhere around here.

Our obs handlers are created to support multiple views. We could add an info about the default mime-type returned when there’s no view parameter specified or even provide separate links for each supported view and the returned mime-type. Note that mime-type was added to ComplexData in openmrs-api 1.11+.

ComplexData has the title field, which is a string representation of the data. We could easily use that for the display property.

The issue with accessing ComplexData is that it may be inefficient as some custom handlers may access or even process the data when creating the object.