[#3502] - JRViewer and Event Dispatch Thread

Category:
Bug report
Priority:
Low
Status:
Confirmed
Project: Severity:
Trivial
Resolution:
Open
Component: Reproducibility:
Always
Assigned to:

hello,
I use the JRViewer class on my swing application, with the substance look and feel. When I show one report and try to print in the printer (the btnPrint button, second in the toolbar), the class throws this error:

org.jvnet.substance.api.UiThreadingViolationException: Component creation must be done on Event Dispatch Thread
at org.jvnet.substance.utils.SubstanceCoreUtilities.testComponentCreationThreadingViolation(SubstanceCoreUtilities.java:2312)
at org.jvnet.substance.SubstancePanelUI.createUI(SubstancePanelUI.java:57)
at sun.reflect.GeneratedMethodAccessor7.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:243)
at javax.swing.UIDefaults.getUI(UIDefaults.java:751)
at javax.swing.UIManager.getUI(UIManager.java:1016)
at javax.swing.JPanel.updateUI(JPanel.java:109)
at javax.swing.JPanel.<init>(JPanel.java:69)
at javax.swing.JPanel.<init>(JPanel.java:92)
at javax.swing.JPanel.<init>(JPanel.java:100)
at javax.swing.JRootPane.createGlassPane(JRootPane.java:527)
at javax.swing.JRootPane.<init>(JRootPane.java:347)
at javax.swing.JDialog.createRootPane(JDialog.java:617)
at javax.swing.JDialog.dialogInit(JDialog.java:599)
at javax.swing.JDialog.<init>(JDialog.java:450)
at sun.print.ServiceDialog.<init>(ServiceDialog.java:123)
at javax.print.ServiceUI.printDialog(ServiceUI.java:188)
at sun.print.RasterPrinterJob.printDialog(RasterPrinterJob.java:856)
at sun.print.PSPrinterJob.printDialog(PSPrinterJob.java:421)
at net.sf.jasperreports.engine.print.JRPrinterAWT.printPages(JRPrinterAWT.java:182)
at net.sf.jasperreports.engine.print.JRPrinterAWT.printPages(JRPrinterAWT.java:86)
at net.sf.jasperreports.engine.JasperPrintManager.printPages(JasperPrintManager.java:354)
at net.sf.jasperreports.engine.JasperPrintManager.printReport(JasperPrintManager.java:245)
at net.sf.jasperreports.view.JRViewer$21.run(JRViewer.java:1201)
at java.lang.Thread.run(Thread.java:619)

This is because substance look and feel is more restrictive with the swing threads. Changing the Thread with SwingUtilities.InvokeLater resolves the problem, see attachment.

AttachmentSize
File -JRViewer.java61.69 KB
Plain text icon diff.txt135 bytes
File JRViewer.diff1.29 KB
File JRPrinterAWT.diff1.48 KB
kavid's picture
4
Joined: Feb 21 2007 - 11:06pm
Last seen: 3 years 11 months ago

12 Comments:

#1

The substance look and feel can be found at https://substance.dev.java.net/ . This bug appears on version 5.0 or later.
I put a diff file, with the differences between JRViewer.java and my changes.

#2

This is indeed a problem.

However, my concern on the proposed fix is that if printing is performed on the event dispatch thread, then the JR viewer would become unresponsive until the report is rendered to produce the print job (which can be an expensive operation).

Ideally, JRPrinterAWT should support doing PrintJob.print() on a worker/background thread.

Keeping this open as it needs more investigation.

Regards,
Lucian

#3

I have the same problem with jasper reports 3.1.4. You can see my complete stack trace here:

http://jasperforge.org/plugins/espforum/view.php?group_id=102&forumid=10...

#4

I think the "proper" way to fix this is to perform the GUI updates on the EDT, while still printing on a separate thread. That way the GUI remains responsive, without violating the EDT rules. I've attached diffs of JRViewer and JRPrinterAWT that do this. There may be other EDT violations that I haven't come across, but these changes appear to fix the print button under Substance 5.

Adam

#5

The behavior of the patches with the 3049 revison is perfect.

Thank you,
Luis Alejandro

#6

The correction doesn't seem to be in JasperReport 3.7.0.
When will this patch (3049 revision) find its way to the main code path?

Temporarily I've found overwriting the JRViewer with my own subclass works well.

Thanks

Martin

#7

The patch was used with that revision 3049, but it's not applied in the main branch.

There is a solution, but I haven't test it:
http://jasperforge.org/plugins/mantis/view.php?id=4545

Thank you,
Luis Alejandro

#8

Hallo Luis.

This solution is also from me.
http://jasperforge.org/plugins/mantis/view.php?id=4545 [^]

However it is a bit crude, as it requires to recompile all the sources for Jasper-Reports, which is why subclassing JRViewer works much better. Additionaly one can still update to the newest versions of JasperReports, whichout having to download all the sources and recompile everything.

Thanks

Martin
Still waiting to be able to get rid of my subclass though with a newer version of Jasper-Reports

#9

Sorry, but.. why is an EDT violation marked as severity 'trivial'? Our application's default LAF is Substance.. but it doesn't matter at all, its an EDT violation, and it happens whatever the LAF.. the difference is that some LAFs validate it.

Thanks

#10

Just call JasperPrintManager.printReport in event dispatch thread, and this issue won't happen.

java.awt.EventQueue.invokeLater()

#11

The problem is that we are sending the report to print, through the JRViewer itself. Using JasperPrintManager.printReport doesn't work in that instance

#12

http://jasperforge.org/plugins/mantis/view.php?id=4545 is not a safe solution; a SwingWorker needs to be used to ensure no Swing components are being modified off of the EDT. The following solution is what I have been applying to each version of jasperrports since 3.5.x. I hope this makes eventually makes it into a release.

void btnPrintActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btnPrintActionPerformed
{//GEN-HEADEREND:event_btnPrintActionPerformed
// Add your handling code here:

btnPrint.setEnabled(false);
final SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
try{
JasperPrintManager.printReport(viewerContext.getJasperPrint(), true);
}catch(Exception ex){
if (log.isErrorEnabled())
{
log.error("Print error.", ex);
}
}
return null;
}

@Override
protected void done() {
btnPrint.setEnabled(true);
}
};
worker.execute();
}

Feedback
randomness