Report Manager

ReportManager provides interface to generate and render reports. It's the main service in report module, which integrates together:

  • long running tasks (LRT) - report generation can take some time, so report is generated as long running task. You can see the result or progress, when report is generated, on both places - from report and LRT agenda. Report generation can be canceled (or killed) the same way as LRT. Report shares LRT's result state (RUNNING, CANCELED etc.).
  • attachments - when report is generated, then his output data are stored as attachment by AttachmentManager. We chosen json format for report output data (as default), array or simple json object can be used. Any other format can be used for storing generated data too, but custom renderers has to be provided - abstract renderers work with json. This generated json data can be loaded again by AttachmentManager and be provided to various report renderers, which "transforms" json (or other) data to any other formats - this rendered report can be downloaded by client (rest endpoint).
  • common dynamic forms - it's used as report filter. Filter is saved and it's used for searching data, when report is generated. Filter can be used even by report renderer.
  • generate - finds report executor for given report and generates report output - json data in attachment. Look out - generating is executed as LRT. This method returns report with filled identifier and state (CREATED) only. When LRT is completed (asynchronously), then report data will be available (reload report is needed by its identifier). Report data can be loaded as input stream by AttachmentManager - report has reference to data, report.getData() returns attachment identifier.
  • render - generated report can be rendered by selected renderer (e.g. as json, xlsx, csv). Returned RptRenderedReportDto contains rendered report as input stream.
  • getExecutors - returns registered reports (~report executors). Returns disabled reports too, its used for already generated reports. Only enabled report can be generated.
  • getRenderers - returns registered renderers to selected report. Returns disabled renderers too, will be used on module overview. Only enabled renderer are shown for generated reports.

ReportExecutor (~report) generates single report - returns json data in attachment. Use abstract class AbstractReportExecutor for implementing custom report (contains some boring parts) and then implement method generate by your needs.

  • Report can be registered in custom module.
  • Use @Component with module prefix name and @Description with user friendly description - will be show on frontend.
  • Report can be disabled / enabled by application configuration.
  • Dynamic common forms are used as report filter (read more bellow).
  • Report should provide data secured by report creator identity (e.g. use find(filter, READ) method).
  • Report data are stored as attachment. This generated json data can be loaded by AttachmentManager in renderers.

Dynamic common forms are used for storing report filter. Report executor provides form definition with attributes, which can be filled in filter ⇒ executor can use this filter for searching data. IdmFormDefinitionService is used for read and update form definition for given report. Filter attributes can be added and changed (see compatible vs incompatible changes).

Report is generated by event processing (event type GENERATE), registered processors to this event type:

  • -1000 - generate report output json data
  • 0 - save report metadata after report is completed / failed
  • 1000 - send notification (websocket as default) about report is completed / failed. Notification templates reportGenerateFailed and reportGenerateSuccess are provided in report module.

You can create your own processor in custom module before / after each phase of report generation (or e.g. disable notification).

Use streams (JsonGenerator, temp files) to generate report (see example). Report can work with large data.
Don't forget to use @Enabled annotation for reports in custom module. When module is disabled, then report has to be disabled too (respectively report will not be available at all).

Renders generated report to single format. This rendered output can be given to download on rest endpoint. Use abstract clases AbstractReportRenderer, AbstractXlsxRenderer, AbstractCsvRenderer, AbstractJsonRenderer for implementing custom renderer (contains some boring parts) and then implement method render by your needs.

Report can be rendered by more renderers. One renderer can render more reports. Use RendererRegistrar interface or AbstractRendererRegistrar class to register renderer to report.

Use streams (JsonParser, temp files) to render report (see example). Report can work with large data.
Don't forget to use @Enabled annotation for renderers in custom module. When module is disabled, then renderer has to be disabled too (respectively renderer will not be available at all).

Generated reports are secured under group REPORT. Authorization policies are implemented:

  • by stloukalp