docs: @VisibleForTesting
      public final Print getJasperPrint(
              final String jobId, final PJsonObject requestData,
              final Configuration config, final File configDir, final File taskDirectory)
              throws JRException, SQLException, ExecutionException {
          final String templateName = requestData.getString(Constants.JSON_LAYOUT_KEY);
  
          final Template template = config.getTemplate(templateName);
          final File jasperTemplateFile = new File(configDir, template.getReportTemplate());
          final File jasperTemplateBuild = this.workingDirectories.getBuildFileFor(
                  config, jasperTemplateFile, JasperReportBuilder.JASPER_REPORT_COMPILED_FILE_EXT,
                  LOGGER);
  
          final Values values = new Values(jobId, requestData, template, taskDirectory,
                                           this.httpRequestFactory, jasperTemplateBuild.getParentFile());
  
          double maxDpi = maxDpi(values);
  
          final ProcessorDependencyGraph.ProcessorGraphForkJoinTask task =
                  template.getProcessorGraph().createTask(values);
          final ForkJoinTask<Values> taskFuture = this.forkJoinPool.submit(
                  task);
  
          try {
              taskFuture.get();
          } catch (InterruptedException exc) {
              // if cancel() is called on the current thread, this exception will be thrown.
              // in this case, also properly cancel the task future.
              taskFuture.cancel(true);
              Thread.currentThread().interrupt();
              throw new CancellationException();
          }
  
          // Fill the resource bundle
          String resourceBundle = config.getResourceBundle();
          if (resourceBundle != null) {
              values.put("REPORT_RESOURCE_BUNDLE", ResourceBundle.getBundle(
                      resourceBundle, values.getObject(Values.LOCALE_KEY, Locale.class),
                      new ResourceBundleClassLoader(configDir)));
          }
  
          ValuesLogger.log(templateName, template, values);
          JasperFillManager fillManager = getJasperFillManager(
                  values.getObject(
                          Values.CLIENT_HTTP_REQUEST_FACTORY_KEY, MfClientHttpRequestFactoryProvider.class));
  
          checkRequiredValues(config, values, template.getReportTemplate());
  
          final JasperPrint print;
          if (template.getJdbcUrl() != null) {
              Connection connection;
              if (template.getJdbcUser() != null) {
                  connection = DriverManager.getConnection(
                          template.getJdbcUrl(), template.getJdbcUser(), template.getJdbcPassword());
              } else {
                  connection = DriverManager.getConnection(template.getJdbcUrl());
              }
  
              print = fillManager.fill(
                      jasperTemplateBuild.getAbsolutePath(),
                      values.asMap(),
                      connection);
  
          } else {
              JRDataSource dataSource;
              if (template.getTableDataKey() != null) {
                  final Object dataSourceObj = values.getObject(template.getTableDataKey(), Object.class);
                  if (dataSourceObj instanceof JRDataSource) {
                      dataSource = (JRDataSource) dataSourceObj;
                  } else if (dataSourceObj instanceof Iterable) {
                      Iterable sourceObj = (Iterable) dataSourceObj;
                      dataSource = toJRDataSource(sourceObj.iterator());
                  } else if (dataSourceObj instanceof Iterator) {
                      Iterator sourceObj = (Iterator) dataSourceObj;
                      dataSource = toJRDataSource(sourceObj);
                  } else if (dataSourceObj.getClass().isArray()) {
                      Object[] sourceObj = (Object[]) dataSourceObj;
                      dataSource = toJRDataSource(Arrays.asList(sourceObj).iterator());
                  } else {
                      throw new AssertionError(
                              String.format("Objects of type: %s cannot be converted to a row in a " +
                                                    "JRDataSource", dataSourceObj.getClass()));
                  }
              } else {
                  dataSource = new JREmptyDataSource();
              }
              checkRequiredFields(config, dataSource, template.getReportTemplate());
              print = fillManager.fill(
                      jasperTemplateBuild.getAbsolutePath(),
                      values.asMap(),
                      dataSource);
          }
          print.setProperty(Renderable.PROPERTY_IMAGE_DPI, String.valueOf(Math.round(maxDpi)));
          return new Print(getJasperReportsContext(
                  values.getObject(
                          Values.CLIENT_HTTP_REQUEST_FACTORY_KEY, MfClientHttpRequestFactoryProvider.class)),
                           print, values, maxDpi, task.getExecutionContext());
      }