Application Name: openmrs platform
Version Number: currently 1.11.x but soon 2.x
UI: legacy now and later with 2.x as well
Story/Question:
Dear @raff and @pascal and other experts
I have a question regarding lists/REST and pagination in modules.
Background: in radiology departments users of a RIS are working a lot with lists, lists of orders, reports, (with all different kinds of filters âtodayâs, last monthsâs studiesâ, âŠ)⊠So lists are/will be an important part in the radiology module
I am not happy for how we handle lists of RadiologyOrderâs at the moment and am looking for guidance, so we get it right for other domain objects like for example RadiologyReportâs.
Current status: We use https://www.datatables.net/ for our lists. The radiologyOrderList.jsp shows a list of RadiologyOrderâs. This is done by including a javascript function which calls a controller that returns RadiologyOrderâs in an html table, so actually a view not json . This table is then processed by datatables and the result put into another jsp.
Question: This procedure does not seem clean to me. Thoughts on solutions and concerns.
REST: I am thinking of creating a REST service inside the radiology module which handles GET requests for RadiologyOrders including pagination. This REST service would then be called by the datatables. My concern here is authentication. Since we are still using the legacy UI and will for the foreseeable future how would I handle that? If I understand correctly REST services currently only work with basic http authentication? Or is this only meant for applications that only use OpenMRS REST and therefore have to take care of authentication? I am using the legacy UI, so is the call to the RestController already authenticated if done in the users active session from the legacy UI?
Pagination: I understand that its not wise to just create a DAO like getAllRadiologyOrders() since users would soon get an out of memory error as amount of orders grows. How would I implement the pagination for the REST services? Can someone please point me to an example domain object of openmrs-core where I can see how this is done?
The REST module can do paging itself in memory (for resources with few items), or else rely on the service to do this (for resources with lots of data). See NeedsPaging and AlreadyPaged.
An example resource is drug. (this is a good example for the âsearchâ but not for âget allâ). The openmrs-core search would look something like this for drugs, though a more standard method signature for openmrs data is here in Encounter.
This sounds like a great idea to me! It will also enable developers to create an ecosystem of Radiology apps such as OWAs on top of your API. I think @judy might agree .
Most resources in the Web Services Module use paging. For a simple example, see the doSearch and doGetAll methods of the Location resource.
I think if you have an active authenticated session, then calls to REST resources should work without requiring explicit authentication. Just like visiting REST URLs in your browser work if you are logged in. For example, visiting http://demo.openmrs.org/openmrs/ws/rest/v1/location will not require authentication if you are logged in at demo.openmrs.org.
Further, you can confirm this by opening up the console on pretty much any page on demo.openmrs.org and running:
I thought I repeat the question I asked you on irc here, since I am having some doubts.
My question was:
I have a RadiologyOrderSearchHandler which gives me all RadiologyOrderâs for a given patient. I am using NeedsPaging to return the results. Now I consume the REST service using datatables with ajax in the legacyui, works well! The only challenge I have left is pagination. datatables expect the json response to contain ârecordsTotalâ, see Server-side processing do you have a suggestion for me on how to achieve that?
By creating a separate resource you mean I create for example a RadiologyOrderListResource which has as property results containing the RadiologyOrderâs and recordsTotal? how is recordsTotal being populated? I assume I need to either provide a RadiologyOrderService.getRadiologyOrdersByPatientCount(Patient) or execute a .size() on the RadiologyOrderService.getRadiologyOrdersByPatient(Patient) result. Where does this go?
Is this âmagicâ of translating Resources into the actual JSON result done by a Converter? Would I then need to write an own Converter?
Maybe as a little background for the moment my RadiologyOrderSearchHandler only has one SearchQuerywithRequiredParameters("patient"). But as a next step I want to expand on that, adding different kinds of SearchQueries/Paramters so users can for example get all RadiologyOrderâs that where ordered within a specific date range. Not sure if that would make any difference.
@pascal I think understood a little better right after I posted
So to your idea of another resource:
I create another resource which I call RadiologyOrderCountResource which has its own RadiologyOrderCountSearchHandler which provides the same type of queries as does the RadiologyOrderSearchHandler but only returns results with property recordsTotal. So I will have to make two REST calls with the same parameters, one for the count, second for the data, right?
would you suggest any specific naming convention? if the actual resource is radiologyorder then radiologyordercount
Another idea I had was that maybe I can use the links property in the response and if there is a next show a next button and if there is a previous show a previous button and leave the total count for now.
Furthermore I wanted to ask if there is a need for a count provided by OpenMRS REST services? I assume my use case is a generic one and others would probably benefit from such a property. Should we think of a way to add such a feature to the REST module?
I donât think there is currently any convention for getting counts. There is an idea here about using a custom HTTP header, but it might also be nice to use a subresource like GET /radiologyorder/count.
Back to your original question. Yes, the count feature would be a good addition to the rest object returned for multiple results. Since we decided to return âresultsâ and âlinksâ inside response body, we could add âtotalCountâ to the returned object as well. Most of our java api methods do not expose count so it would be more resource consuming to get the full count of results for some resources (count in memory). In addition in most cases it requires another db query to get the count. I think we should return it when specifically asked by REST client, which for example would append totalCount=true to request parameters.
On Pascalâs comment about adding a count resource or subresource I think the benefit of embedding totalCount in a response itself is that we can return it for virtually any query, e.g. implemented using SearchHandler.
Unfortunately no, no angular. I am developing on legacyui but thanks for the hint!
To me adding a new property to the request itself seems cleaner. But as you pointed out its probably best to only return it if explicitly requested via a parameter.
I currently donât have time. I might be able to provide someone who could implement it, an intern starting in July but cant say until 1 week from now.
Can you give me a starting point as to where this property would need to be added? I can then write up an issue in RESTWS.
*add method getTotalCount() in BasePageableResult (could return null so we donât break compatibility and will be overridden by subclasses who do support this)
in BasePageableResult.toSimpleObject() add property totalCount to ret if Context contains a request parameter totalCount=true
in NeedsPaging override getTotalCount returning unpagedResult.size()
in AlreadyPaged add member totalCount with a new constructor where I can initialize the member.
And then it is up to the SearchHanlder to populate the totalCount
Just want to know if I am thinking in a good direction. Thanks!!
@raff just updated the PR, I tested the new feature with the radiology module (RadiologyOrderSearchHandler uses NeedsPaging to return results, the totalCount is returned if requested), see image