-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
O3-1494: Added REST APIs for O3 Report Admin pages #33
base: master
Are you sure you want to change the base?
Conversation
omod/pom.xml
Outdated
<dependency> | ||
<groupId>org.hamcrest</groupId> | ||
<artifactId>hamcrest-all</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.openmrs.module</groupId> | ||
<artifactId>uiframework-api</artifactId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you intentionally forcing O3 distributions to have to load the uiframework module? It would have been better if we can avoid this. 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, not sure why you need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll remove it, it was needed for FileDownload
class
@@ -13,11 +13,40 @@ | |||
*/ | |||
package org.openmrs.module.reportingrest.web.controller; | |||
|
|||
import org.apache.commons.lang3.StringUtils; | |||
import org.apache.commons.lang3.time.DateUtils; | |||
import org.apache.commons.logging.Log; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is our convention for logging: https://wiki.openmrs.org/display/docs/Java+Conventions#JavaConventions-loggingLogging
} | ||
} | ||
|
||
@RequestMapping(value = "/preserveReport", method = RequestMethod.POST) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How different is preserveReport
from saveReport
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this not be done as an operation on the existing reportRequest
endpoint, to preserve that report request (eg. changing the status)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dkayiwa I'll change it to saveReport
, preserve came from UI.
@mseaton Generally, this is a quick migration of legacy UI's org.openmrs.module.reportingui.fragment.controller.ReportStatusFragmentController
, this directly relates to actions on UI.
The existing ReportRequestResource
is a CrudResource
- should I just add an endpoint method there?
Or do you mean, that if there is an update call, which changes request's status from COMPLETED to SAVED, then it should run the ReportService.savereport()
?
/** | ||
* {@link Resource} for {@link ReportDesign}s, supporting standard CRUD operations | ||
*/ | ||
@Resource(name = RestConstants.VERSION_1 + ReportingRestController.REPORTING_REST_NAMESPACE + "/designs", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about reportDesign
instead of designs
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Please follow existing naming conventions. reportDesign
is appropriate.
@@ -0,0 +1,111 @@ | |||
/** | |||
* The contents of this file are subject to the OpenMRS Public License | |||
* Version 1.0 (the "License"); you may not use this file except in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the current license header: https://github.com/openmrs/openmrs-core/blob/2.6.4/api/src/main/java/org/openmrs/Address.java#L1-L9
private FileDownload processAndDownloadReport(String reportRequestUuid, ReportService reportService) { | ||
ReportRequest reportRequest = reportService.getReportRequestByUuid(reportRequestUuid); | ||
if (reportRequest == null) { | ||
throw new IllegalArgumentException("Report request not found"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It helps to include the report request uuid in the error message.
try { | ||
convertedObject = DateUtils.parseDate((String) value, "MM/dd/yyyy"); | ||
} catch (ParseException e) { | ||
LOGGER.error("Error while parsing date"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we pass the exception as the second parameter of the above?
throw new IllegalArgumentException("reportDefinitionUuid parameter is required"); | ||
} | ||
|
||
ReportDefinition reportDefinition = getReportDefinitionService().getDefinitionByUuid(reportDefinitionUuid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when no report definition is found with the given uuid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed it to return an empty result, as "no report definition found, then there are no report requests related to that not existing report definition in the system", previously it would return all requests.
But I guess, an exception/404 would be an option too.
|
||
if (type.equals(Date.class)) { | ||
try { | ||
convertedObject = DateUtils.parseDate((String) value, "MM/dd/yyyy"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use org.openmrs.module.webservices.rest.web.ConversionUtil.convert(value, Date.class)
} | ||
} | ||
|
||
if (type.equals(Integer.class)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use ConversionUtil.convert?
convertedObject = Integer.valueOf((String) value); | ||
} | ||
|
||
if (type.equals(Location.class)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use ConversionUtil.convert?
@Override | ||
public DelegatingResourceDescription getRepresentationDescription(Representation representation) { | ||
final DelegatingResourceDescription description = new DelegatingResourceDescription(); | ||
description.addProperty("reportDefinition", Representation.FULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the only representation that you support?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we didn't need anything else to support the O3 UI.
Changed to DRAFT, becuase it's not adapted to review changes in openmrs/openmrs-module-reporting#249 |
omod/pom.xml
Outdated
<dependency> | ||
<groupId>org.hamcrest</groupId> | ||
<artifactId>hamcrest-all</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.openmrs.module</groupId> | ||
<artifactId>uiframework-api</artifactId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, not sure why you need this?
|
||
@RequestMapping(value = "/runReport", method = RequestMethod.POST) | ||
@ResponseStatus(HttpStatus.OK) | ||
public void runReport(@RequestBody RunReportRequest runReportRequest) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain what this endpoint does that the existing reportRequest
endpoint does not do? Can we improve what we have if needed or do we really need this new endpoint?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current ReportRequestResource
just saves a ReportRequest
in DB, as-is.
The runReport
creates ReportRequest
and adds it to execution queue - maybe better name would be queueReport
as from ReportService.queueReport
.
Generally, this is migration of org.openmrs.module.reportingui.page.controller.RunReportPageController
.
Would it make sense for ReportRequestResource
to queue every new ReportRequest
?
We were hesitant to modify anything already in use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pwargulak - It's been a long time since I've looked at this, but my first reaction is that it definitely would make the most sense for the ReportRequestResource
to queue every new ReportRequest
. So basically:
- If the report request does not already exist with the given uuid, call
reportService.queueReport(ReportRequest)
, otherwise callsreportService.saveReportRequest(ReportRequest);
|
||
@RequestMapping(value = "/cancelReport", method = RequestMethod.DELETE) | ||
@ResponseStatus(HttpStatus.OK) | ||
public void cancelReport(@RequestParam String reportRequestUuid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be handled by the DELETE operation on the existing reportRequest
endpoint, maybe based on certain parameters that dictate whether the goal is to cancel or purge the report request? Or maybe as a POST or PUT operation on the reportRequest
endpoint that aims to change the status to CANCELLED?
} | ||
} | ||
|
||
@RequestMapping(value = "/preserveReport", method = RequestMethod.POST) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this not be done as an operation on the existing reportRequest
endpoint, to preserve that report request (eg. changing the status)?
reportService.saveReport(report, StringUtils.EMPTY); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these operations that take in a reportRequestUuid
seem like they might be better done within the reportRequest
resource / endpoint
@Override | ||
protected PageableResult doSearch(RequestContext context) { | ||
String statusesGroup = context.getParameter("statusesGroup"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this hard-coding like this with these statusGroups. Why is this needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It adds groups to ReportRequest.Status
:
- ran - all statuses which mean a report was executed
- processing - all statuses which mean report is being executed
- scheduled - all statuses which mean it's an execution according to schedule
We could change the statusesGroup
parameter to status
and allow comma-separated list here, moving the grouping of Status to the FE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pwargulak - I think that would be preferable. Basically, allow the endpoint to accept multiple values for status
and interpret this as an OR
condition. I wouldn't accept a csv input, rather I would just get the array of parameter values out of the request for the status
parameter name, and treat this as an "or".
} | ||
|
||
return new AlreadyPaged<ReportRequest>(context, reportRequests, reportRequestsDTO.getReportRequestCount() > (long) pageNumber * pageSize, reportRequestsDTO.getReportRequestCount()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand the placement of this if/then block. Let's just do things consistently and always use the paging endpoint. If no paging parameters are supplied, it should default to returning all like it currently does.
import java.util.Comparator; | ||
import java.util.List; | ||
|
||
@Resource(name = RestConstants.VERSION_1 + ReportingRestController.REPORTING_REST_NAMESPACE + "/scheduledReport", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this class be handled by hitting the reportRequest
endpoint with appropriate parameters to only return scheduled reports? Or can't we make it do so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically, this is reportDefinition left join reportRequest
- one request.
With existing APIs, we would need to REST GET reportDefinition
and reportRequest
then join them on FE side.
Used on a page which shows a table of all Reports with their related execution schedule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. OK. Couldn't we accomplish this without adding the ScheduledReport
class, and just return a List where each simple object contains a reportDefinition
-> ReportDefinition
and scheduledReports
-> List<ReportRequest>
object?
Then, in the frontend, you'd hit this endpoint and it would give you all available report definitions, and any scheduled reports for them, or an empty list if none.
omod/src/main/resources/config.xml
Outdated
@@ -15,6 +15,7 @@ | |||
<require_module version="${serializationxstreamVersion}">org.openmrs.module.serialization.xstream</require_module> | |||
<require_module version="${reportingVersion}">org.openmrs.module.reporting</require_module> | |||
<require_module version="${webservicesRestVersion}">org.openmrs.module.webservices.rest</require_module> | |||
<require_module version="${uiframeworkModuleVersion}">org.openmrs.module.uiframework</require_module> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this should not require uiframework. This needs to be removed.
pom.xml
Outdated
<artifactId>uiframework-api</artifactId> | ||
<version>${uiframeworkModuleVersion}</version> | ||
<scope>provided</scope> | ||
</dependency> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dependency needs to be removed.
@mseaton Just want to confirm with you, that the ReportRequest REST API should perform some additional actions based on ReportRequest's status change, instead having separate endpoints for invoking the actions. For example, |
I'm fine either way, but would be good if we could make our existing endpoints behave as we think they should. |
@mseaton @dkayiwa @ibacher @djazayeri we would like to get back to this and make the code ready for merging. We applied previous remarks from code review. Can you take a look at this once again? |
Summary
This change adds REST APIs used on O3 Admin pages, including:
See the related issue.
Issue
https://openmrs.atlassian.net/browse/O3-1494