cuba-platform / reports

CUBA Reports Addon
https://www.cuba-platform.com/
Apache License 2.0
9 stars 4 forks source link

Error when running report within a report (IllegalStateException: Execution context already started) #228

Closed PolinaSannikova closed 4 years ago

PolinaSannikova commented 4 years ago

Environment

Description of the bug or enhancement

Trying to create a PDF report with a groovy script custom template. The report should run several other PDF reports and collate them. However, an error appears, which seems to be related to running a report within a report.

  1. Make sure there is a PDF report with code "TEST" in the system, which has input parameter of type Entity, with name "Entity". Please see attached example report (it users sec$User as input entity). Test.zip

  2. Create a groovy script, intended to be used in a custom template report, which, for a list of input entities, would run report "TEST" for each of them and merge these reports in one big PDF. Example script attached: TestMergedGroovy.zip

  3. Create a report which has input parameter "Entities" - list of the same entities as in the report created in step 1. This report would use the script created in step 2. Example report attached: Test Merged.zip

  4. Run the report from step 3.

alexbudarov commented 4 years ago

@PolinaSannikova this problem was solved in the PdfReportMerger Sherlock class, please look into its implementation.

(For everyone): It launches report in another thread pool executor:

ThreadPoolTaskExecutor reportThreadExecutor = AppBeans.get("reportTaskExecutor")
Authentication authentication = AppBeans.get(Authentication.NAME);
Future<byte[]> future = reportThreadExecutor.submit(() -> {
    authentication.begin("ReportScheduling");
    try {
        Map<String, Object> reportParams = new HashMap<>(params);
        reportParams.put(entityName, entity);
        return reporting.createReport(singleReport, reportParams).getContent();
    } finally {
        authentication.end();
    }
})
// ...
byte[] result = future.get()