Play Framework: PDF'ing шаблон, использующий JS библиотеку highcharts через Job

Это продолжение предыдущего сообщения, которое я сделал.

Вкратце о том, что происходит:

  • Я использую задание, которое выполняется ежечасно и генерирует PDF для отправки в качестве вложения в электронном письме
  • Задание не делает многого, но вызывает непосредственно контроллер для генерации PDF и отправки письма. Я вызываю контроллер для выполнения этой работы, поскольку я использую модуль PDF, который (в настоящее время) требует HTTP-запрос как часть обработки PDF. Вот как я вызываю контроллер через Job:

    WS.url("my/url/that/points/to/the/controller").get();

  • Моя предыдущая проблема с PDF шаблоном, включающим диаграмму Highcharts JS, заключалась в том, что она генерировала диаграмму на стороне клиента, что было слишком поздно для генерации PDF, и поэтому PDF получался без диаграммы. Чтобы обойти это, я теперь использую highcharts-serverside-export для генерации графика на стороне сервера

Если я использую те же классы, что и выше, и рендерю шаблон в браузере (т.е. иду через контроллер напрямую и игнорирую Job), график создается на стороне сервера, и представление корректно отображается в браузере.

Я создаю график в шаблоне, вызывая другой контроллер следующим образом:


Контроллер ChartGenerator просто создает график на стороне сервера в соответствии с документацией highcharts-serverside-export и вызывает метод Play's renderBinary.

Как я уже сказал, шаблон прекрасно отображается в браузере со сгенерированным на стороне сервера графиком. Однако при переходе через Job, который выполняется ежечасно, вызов ChartGenerator.go(), похоже, не работает. Консоль выдает следующее:

INFO  ~ /chartgenerator/go is not a URL; may be relative.

Есть ли у кого-нибудь идеи, как это можно исправить? Я доказал, что он работает без задания, и теперь нужно выяснить, почему при выполнении задания он не работает.

Edit: По предложению Пере, мой шаблон теперь вызывает класс ChartGenerator, делая следующее (обратите внимание на двойные @):

 

Я думаю, что это продвинуло меня немного дальше, теперь это выводится в логах:

Error during job execution (fun.EmailJob)
Execution exception (In /fun/EmailJob.java around line 19)
RuntimeException occured : java.util.concurrent.ExecutionException: java.util.concurrent.TimeoutException: No response received after 60000
...
09:23:54,687 WARN  ~ bad URL given: http:///chartgenerator/go
java.net.SocketTimeoutException: Read timed out

Если я нажму URL http:///chartgenerator/go в браузере, png файл highcharts отображается в браузере правильно. И, как и ожидалось, даже после этого двойного @ изменения, если я рендерю шаблон в браузере (без pdf'ing), шаблон рендерится правильно с графиком, сгенерированным на стороне сервера.

Edit #2: С этими проблемами, с которыми я, похоже, сталкиваюсь, вызывая контроллер из шаблона для рендеринга изображения (бинарного), я задаюсь вопросом, можно ли передать объект File (содержащий изображение) в качестве параметра в метод render(...) для шаблона. Так, например, допустим, контроллер, который рендерит шаблон, делает следующее:

File image = ... // PNG chart as built by the highcharts-serverside-export library
...
File emailAttachment = new File("attachment.pdf");
PDF.writePDF(emailAttachment, "myTemplate.html", image); // This calls the PDF module to render the PDF from the given template and write it to the attachment.pdf File object

Мне интересно, могу ли я как-то рендерить это изображение в шаблоне напрямую, без необходимости проходить через @@{...} путь?

Я пробовал поместить ${image} в шаблон, но это просто вывело attachment.pdf на экран (вроде как ожидаемо).

Edit #3: Вот как выглядит класс ChartGenerator:

public final class ChartGenerator extends Controller {
    public static void go() throws Exception {
        ChartOptions options = SamplesFactory.getSingleton().createColumnBasic();
        HighchartsExporter pngExporter = ExportType.png.createExporter();
        File chart = new File("column-basic.png");
        pngExporter.export(options, null, chart);
        response.setContentTypeIfNotSet("image/png");
        renderBinary(chart);
    }
}

Сейчас я просто генерирую пример графика на стороне сервера, чтобы доказать, что его можно выводить в pdf. Генерация примера графика выполняется в соответствии с документацией highcharts-serverside-export.

Edit #4: Я также попробовал добавить метод действия в контроллер, чтобы разрешить редактирование pdf в браузере, и сгенерированная на стороне сервера диаграмма highcharts также не отображается в pdf и по-прежнему возникает ранее упомянутое исключение. Таким образом, я могу исключить, что это проблема с рабочим процессом Job to Controller. (конечно, рендеринг шаблона без pdf'ing по-прежнему работает нормально)

Edit #5: Чтобы сузить круг возможных причин проблемы, я решил проигнорировать highcharts (вместе с библиотекой highcharts-serverside-export) и просто использовать простую библиотеку jfreechart для построения диаграмм на стороне сервера. Опять же, я могу вывести шаблон без pdf'ing, но как только я пытаюсь вывести шаблон, включающий диаграмму (выведенную с помощью вышеупомянутого вызова @@), он завершается неудачей по той же причине (т.е. указан неверный URL, java.net.SocketTimeoutException: Чтение прервано).

6
задан Community 23 May 2017 в 12:11
поделиться