I have a problem with an accounting web application that was recently enhanced with printing using Jasper Reports. Being an accounting application, it has been decided that it is being deployed to the accountant's workstation which is a Mac Book Pro laptop with regular backups of the MySQL database. So installing it on a serious server machine is out of the question.
The user has Java8 / Tomcat8 stack and runs the server from command line. The application worked so fine until now.
Every time the user prints a report using Jasper (code later), a tray icon will open displaying the Java Control Panel icon.
Clicking on that icon does nothing, it is just annoying. I could see that the window (from the Finder top bar) is called Bootstrap
. No menu action except Exit
is available. Clicking Exit kills Tomcat server.
Code follows:
@Override
public byte[] generateReportPdf(List<?> dtos, String jasperFilename, Locale locale)
{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try
{
JasperPrint jasperPrint = createJasperPrint(dtos, jasperFilename, locale);
JRPdfExporter exporter = new JRPdfExporter();
SimplePdfExporterConfiguration config = new SimplePdfExporterConfiguration();
config.setEncrypted(true);
config.set128BitKey(true);
config.setOwnerPassword(PSW_CRYPT_PDF);
config.setPermissions(PdfWriter.ALLOW_PRINTING);
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(byteArrayOutputStream));
exporter.setConfiguration(config);
exporter.exportReport();
}
catch (Exception e)
{
logger.error(e.getMessage(), e);
throw new RuntimeException("PDF error", e);
}
finally
{
try
{
byteArrayOutputStream.close();
}
catch (IOException e)
{
logger.error(e.getMessage(), e);
}
}
return byteArrayOutputStream.toByteArray();
}
private JasperPrint createJasperPrint(List<?> dtos, String jasperFilename, Locale locale) throws JRException
{
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = classLoader.getResourceAsStream(JASPER_REPORT_FOLDER + jasperFilename + ".jrxml");
JasperDesign jasperDesign = JRXmlLoader.load(inputStream);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
//JasperReport jasperReport = (JasperReport) JRLoader.loadObject(classLoader.getResource(JASPER_REPORT_FOLDER + jasperFilename + ".jasper"));
// set mas pages and timeout
jasperReport.setProperty(MaxPagesGovernor.PROPERTY_MAX_PAGES_ENABLED, "true");
jasperReport.setProperty(MaxPagesGovernor.PROPERTY_MAX_PAGES, "50");
jasperReport.setProperty(TimeoutGovernor.PROPERTY_TIMEOUT_ENABLED, "true");
jasperReport.setProperty(TimeoutGovernor.PROPERTY_TIMEOUT, "60000");
jasperReport.setProperty("net.sf.jasperreports.default.font.name", "DejaVu Sans");
jasperReport.setProperty("net.sf.jasperreports.default.pdf.embedded", "true");
jasperReport.setProperty("net.sf.jasperreports.default", "DejaVu Sans");
JRBeanCollectionDataSource jrDataSource = new JRBeanCollectionDataSource(dtos, false);
HashMap<String, Object> parameters = new HashMap<>();
parameters.put(JRParameter.REPORT_LOCALE, locale);
return JasperFillManager.fillReport(jasperReport, parameters, jrDataSource);
}
Why does it happen only on Mac? How to prevent the tray icon from appearing? We developers are running either Windows 10 or SUSE Linux hosts, and we are not having this issue on our machines, not even on a SIT environment running Windows 7.
JasperReports uses AWT for things like text measurements and image processing. When a Java process runs in a graphical environment (i.e. as a process of a user who is logged into a desktop environment session), the AWT classes use the environment for graphical processing by default. Mac OS interprets the graphical processing as an evidence that the process has some kind of UI, and thus includes the Java process as an application in the taskbar.
If you don't want that to happen, you can force the Java process into headless AWT mode by adding -Djava.awt.headless=true
to the Java options in Tomcat. That would result in AWT using a headless graphical environment implementation instead of the desktop environment.