Jasper 报告无法在没有 X11 的 Linux 服务器上工作:"Error initializing graphic environment."
Jasperreports not working on Linux server without X11: "Error initializing graphic environment."
我有一个大问题。我正在编写一个使用 Jasperreports 的应用程序。我在当地工作时一切都很好。但是,当我对我的应用程序进行 docker 化时,当我 运行 应该生成 PDF 文件的方法时,我收到一个错误:
Request processing failed; nested exception is net.sf.jasperreports.engine.JRRuntimeException: Error initializing graphic environment.
我发现 运行我的应用与
-DJava.awt.headless=true
问题会自行解决。但事实并非如此。
这是 Dockerfile
中的样子:
ENTRYPOINT [ "java", "-Djava.awt.headless=true", "-jar", "/var/generator/generator-0.0.1-SNAPSHOT.jar" ]
为了确保我没有忘记任何东西,这里是生成 PDF 文件的方法代码,可能那里有问题...
错误来自这一行:
mainReport = JasperFillManager.fillReport(report, invoiceMap, new JREmptyDataSource());
方法如下:
public byte[] generateInvoicePDF(Invoice invoice) {
/* Map to fill in main JasperReport */
Map<String, Object> invoiceMap = new HashMap<String, Object>();
invoiceMap.put("FIRST_NAME", invoice.getFirstName());
invoiceMap.put("LAST_NAME", invoice.getLastName());
invoiceMap.put("REGON", invoice.getRegon());
invoiceMap.put("NIP", invoice.getNip());
invoiceMap.put("BUSINESS_NAME", invoice.getBusinessName());
invoiceMap.put("BUSINESS_LOCATION", invoice.getBusinessLocation());
invoiceMap.put("ORDER_DATE", invoice.getOrderDate());
invoiceMap.put("RECEPTION_DATE", invoice.getReceptionDate());
invoiceMap.put("CONTRACT_DATE", invoice.getContractDate());
invoiceMap.put("CONTRACTOR_COMMENT", invoice.getContractorComment());
invoiceMap.put("INVOICE_NUMBER", invoice.getInvoiceNumber());
invoiceMap.put("INVOICE_ISSUE_DATE", invoice.getInvoiceIssueDate());
JasperPrint mainReport;
JasperPrint tableReport;
try {
InputStream invoiceJasper = InvoiceGeneratorServiceImpl.class.getResourceAsStream("/invoices/invoice.jrxml");
InputStream taskTableJasper = InvoiceGeneratorServiceImpl.class.getResourceAsStream("/invoices/invoice_sub.jrxml");
JasperDesign mainReportDesign = JRXmlLoader.load(invoiceJasper);
JasperDesign tableReportDesign = JRXmlLoader.load(taskTableJasper);
JasperReport report = JasperCompileManager.compileReport(mainReportDesign);
JasperReport table = JasperCompileManager.compileReport(tableReportDesign);
/* List to hold Items */
List<InvoiceTask> taskList = new ArrayList<>();
/* Add Items to List */
taskList.addAll(invoice.getInvoiceTasks());
/* Convert List to JRBeanCollectionDataSource */
JRBeanCollectionDataSource itemsJRBean = new JRBeanCollectionDataSource(taskList);
/* Map to hold Jasper report Parameters */
Map<String, Object> taskListMap = new HashMap<String, Object>();
taskListMap.put("TasksDataSource", itemsJRBean);
taskListMap.put("ADDITIONAL_COSTS", invoice.getAdditionalCosts());
mainReport = JasperFillManager.fillReport(report, invoiceMap, new JREmptyDataSource());
tableReport = JasperFillManager.fillReport(table, taskListMap, new JREmptyDataSource());
List<JasperPrint> printList = new ArrayList<>();
printList.add(mainReport);
printList.add(tableReport);
JRPdfExporter exporter = new JRPdfExporter();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
exporter.setExporterInput(SimpleExporterInput.getInstance(printList)); //Set as export input my list with JasperPrint s
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(byteArrayOutputStream));
SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
configuration.setCreatingBatchModeBookmarks(true); //add this so your bookmarks work, you may set other parameters
exporter.setConfiguration(configuration);
exporter.exportReport();
return byteArrayOutputStream.toByteArray();
} catch (JRException e) {
e.printStackTrace();
}
return new byte[0];
}
还有一点堆栈跟踪:
2019-04-24 08:43:57.338 ERROR 1 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is net.sf.jasperreports.engine.JRRuntimeException: Error initializing graphic environment.] with root cause
java.lang.NullPointerException: null
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) ~[na:1.8.0_201]
at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) ~[na:1.8.0_201]
at sun.awt.FontConfiguration.init(FontConfiguration.java:107) ~[na:1.8.0_201]
at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) ~[na:1.8.0_201]
at sun.font.SunFontManager.run(SunFontManager.java:431) ~[na:1.8.0_201]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
at sun.font.SunFontManager.<init>(SunFontManager.java:376) ~[na:1.8.0_201]
at sun.awt.FcFontManager.<init>(FcFontManager.java:35) ~[na:1.8.0_201]
at sun.awt.X11FontManager.<init>(X11FontManager.java:57) ~[na:1.8.0_201]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_201]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_201]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_201]
at java.lang.Class.newInstance(Class.java:442) ~[na:1.8.0_201]
at sun.font.FontManagerFactory.run(FontManagerFactory.java:83) ~[na:1.8.0_201]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[na:1.8.0_201]
at sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:201) ~[na:1.8.0_201]
at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:235) ~[na:1.8.0_201]
at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:263) ~[na:1.8.0_201]
at sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:94) ~[na:1.8.0_201]
at net.sf.jasperreports.engine.util.JRGraphEnvInitializer.initializeGraphEnv(JRGraphEnvInitializer.java:58) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.BaseReportFiller.<init>(BaseReportFiller.java:136) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRBaseFiller.<init>(JRBaseFiller.java:273) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:79) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.createBandReportFiller(JRFiller.java:251) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.createReportFiller(JRFiller.java:272) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:156) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:145) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:758) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:1074) ~[jasperreports-6.7.1.jar!/:6.7.1]
at com.generator.service.impl.InvoiceGeneratorServiceImpl.generateInvoicePDF(InvoiceGeneratorServiceImpl.java:68) ~[classes!/:na]
at com.generator.rest.ContractorController.getPdf(ContractorController.java:165) ~[classes!/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
这看起来像是缺少字体的问题。
如果您恰好在使用 Alpine,那么您可能会看到 issue #73,它具有相同的相关堆栈跟踪。根据那个问题,安装 ttf-dejavu
包应该可以解决你的问题。
将此添加到您的 dockerfile:
RUN apk add ttf-dejavu
我可以通过安装 fontconfig 和 urw-fonts 软件包来解决这个问题。
yum install fontconfig
yum install urw-fonts
我有一个大问题。我正在编写一个使用 Jasperreports 的应用程序。我在当地工作时一切都很好。但是,当我对我的应用程序进行 docker 化时,当我 运行 应该生成 PDF 文件的方法时,我收到一个错误:
Request processing failed; nested exception is net.sf.jasperreports.engine.JRRuntimeException: Error initializing graphic environment.
我发现 运行我的应用与
-DJava.awt.headless=true
问题会自行解决。但事实并非如此。
这是 Dockerfile
中的样子:
ENTRYPOINT [ "java", "-Djava.awt.headless=true", "-jar", "/var/generator/generator-0.0.1-SNAPSHOT.jar" ]
为了确保我没有忘记任何东西,这里是生成 PDF 文件的方法代码,可能那里有问题...
错误来自这一行:
mainReport = JasperFillManager.fillReport(report, invoiceMap, new JREmptyDataSource());
方法如下:
public byte[] generateInvoicePDF(Invoice invoice) {
/* Map to fill in main JasperReport */
Map<String, Object> invoiceMap = new HashMap<String, Object>();
invoiceMap.put("FIRST_NAME", invoice.getFirstName());
invoiceMap.put("LAST_NAME", invoice.getLastName());
invoiceMap.put("REGON", invoice.getRegon());
invoiceMap.put("NIP", invoice.getNip());
invoiceMap.put("BUSINESS_NAME", invoice.getBusinessName());
invoiceMap.put("BUSINESS_LOCATION", invoice.getBusinessLocation());
invoiceMap.put("ORDER_DATE", invoice.getOrderDate());
invoiceMap.put("RECEPTION_DATE", invoice.getReceptionDate());
invoiceMap.put("CONTRACT_DATE", invoice.getContractDate());
invoiceMap.put("CONTRACTOR_COMMENT", invoice.getContractorComment());
invoiceMap.put("INVOICE_NUMBER", invoice.getInvoiceNumber());
invoiceMap.put("INVOICE_ISSUE_DATE", invoice.getInvoiceIssueDate());
JasperPrint mainReport;
JasperPrint tableReport;
try {
InputStream invoiceJasper = InvoiceGeneratorServiceImpl.class.getResourceAsStream("/invoices/invoice.jrxml");
InputStream taskTableJasper = InvoiceGeneratorServiceImpl.class.getResourceAsStream("/invoices/invoice_sub.jrxml");
JasperDesign mainReportDesign = JRXmlLoader.load(invoiceJasper);
JasperDesign tableReportDesign = JRXmlLoader.load(taskTableJasper);
JasperReport report = JasperCompileManager.compileReport(mainReportDesign);
JasperReport table = JasperCompileManager.compileReport(tableReportDesign);
/* List to hold Items */
List<InvoiceTask> taskList = new ArrayList<>();
/* Add Items to List */
taskList.addAll(invoice.getInvoiceTasks());
/* Convert List to JRBeanCollectionDataSource */
JRBeanCollectionDataSource itemsJRBean = new JRBeanCollectionDataSource(taskList);
/* Map to hold Jasper report Parameters */
Map<String, Object> taskListMap = new HashMap<String, Object>();
taskListMap.put("TasksDataSource", itemsJRBean);
taskListMap.put("ADDITIONAL_COSTS", invoice.getAdditionalCosts());
mainReport = JasperFillManager.fillReport(report, invoiceMap, new JREmptyDataSource());
tableReport = JasperFillManager.fillReport(table, taskListMap, new JREmptyDataSource());
List<JasperPrint> printList = new ArrayList<>();
printList.add(mainReport);
printList.add(tableReport);
JRPdfExporter exporter = new JRPdfExporter();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
exporter.setExporterInput(SimpleExporterInput.getInstance(printList)); //Set as export input my list with JasperPrint s
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(byteArrayOutputStream));
SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
configuration.setCreatingBatchModeBookmarks(true); //add this so your bookmarks work, you may set other parameters
exporter.setConfiguration(configuration);
exporter.exportReport();
return byteArrayOutputStream.toByteArray();
} catch (JRException e) {
e.printStackTrace();
}
return new byte[0];
}
还有一点堆栈跟踪:
2019-04-24 08:43:57.338 ERROR 1 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is net.sf.jasperreports.engine.JRRuntimeException: Error initializing graphic environment.] with root cause
java.lang.NullPointerException: null
at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264) ~[na:1.8.0_201]
at sun.awt.FontConfiguration.readFontConfigFile(FontConfiguration.java:219) ~[na:1.8.0_201]
at sun.awt.FontConfiguration.init(FontConfiguration.java:107) ~[na:1.8.0_201]
at sun.awt.X11FontManager.createFontConfiguration(X11FontManager.java:774) ~[na:1.8.0_201]
at sun.font.SunFontManager.run(SunFontManager.java:431) ~[na:1.8.0_201]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
at sun.font.SunFontManager.<init>(SunFontManager.java:376) ~[na:1.8.0_201]
at sun.awt.FcFontManager.<init>(FcFontManager.java:35) ~[na:1.8.0_201]
at sun.awt.X11FontManager.<init>(X11FontManager.java:57) ~[na:1.8.0_201]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_201]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_201]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_201]
at java.lang.Class.newInstance(Class.java:442) ~[na:1.8.0_201]
at sun.font.FontManagerFactory.run(FontManagerFactory.java:83) ~[na:1.8.0_201]
at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_201]
at sun.font.FontManagerFactory.getInstance(FontManagerFactory.java:74) ~[na:1.8.0_201]
at sun.java2d.SunGraphicsEnvironment.getFontManagerForSGE(SunGraphicsEnvironment.java:201) ~[na:1.8.0_201]
at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:235) ~[na:1.8.0_201]
at sun.java2d.SunGraphicsEnvironment.getAvailableFontFamilyNames(SunGraphicsEnvironment.java:263) ~[na:1.8.0_201]
at sun.java2d.HeadlessGraphicsEnvironment.getAvailableFontFamilyNames(HeadlessGraphicsEnvironment.java:94) ~[na:1.8.0_201]
at net.sf.jasperreports.engine.util.JRGraphEnvInitializer.initializeGraphEnv(JRGraphEnvInitializer.java:58) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.BaseReportFiller.<init>(BaseReportFiller.java:136) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRBaseFiller.<init>(JRBaseFiller.java:273) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:79) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.createBandReportFiller(JRFiller.java:251) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.createReportFiller(JRFiller.java:272) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:156) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:145) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:758) ~[jasperreports-6.7.1.jar!/:6.7.1]
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:1074) ~[jasperreports-6.7.1.jar!/:6.7.1]
at com.generator.service.impl.InvoiceGeneratorServiceImpl.generateInvoicePDF(InvoiceGeneratorServiceImpl.java:68) ~[classes!/:na]
at com.generator.rest.ContractorController.getPdf(ContractorController.java:165) ~[classes!/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
这看起来像是缺少字体的问题。
如果您恰好在使用 Alpine,那么您可能会看到 issue #73,它具有相同的相关堆栈跟踪。根据那个问题,安装 ttf-dejavu
包应该可以解决你的问题。
将此添加到您的 dockerfile:
RUN apk add ttf-dejavu
我可以通过安装 fontconfig 和 urw-fonts 软件包来解决这个问题。
yum install fontconfig
yum install urw-fonts