简体   繁体   中英

Jasper Reports as part of Java aplication

I am using a Java application that allows you to add extensions written in Java. I wish to run a JasperReports viewer within an extension. As a test I have this code:

package com.moneydance.modules.features.jasperreports;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JFrame;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.swing.JRViewer;

public class MyJasperReport extends JFrame{
    JasperReport report;
    public MyJasperReport(Main main)  throws JRException, IOException{
      String sourceFileName = "c://users/miker/workspace/JasperReports-6.7.0/test" + 
         "/jasper_report_template.jasper";
    Map<String,Object> parameters = new HashMap<>();
   JasperReport report =(JasperReport)JRLoader.loadObjectFromFile(sourceFileName);
   JRDataSource dataSource = new JREmptyDataSource();
   JasperPrint jasperPrint = null;
   JRViewer viewer = null;
   try {
       jasperPrint = JasperFillManager.fillReport(report, parameters,dataSource);
   }
   catch (JRException e) {
       e.printStackTrace();
   }
   if (jasperPrint != null) {
        viewer = new JRViewer(jasperPrint);
        if (viewer !=null) {
            getContentPane().add(viewer);
        }
    }
}

}

This fails with a null pointer exception on the line:

        btnSave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/net/sf/jasperreports/view/images/save.GIF")));

within the class JRViewerToolBar

If I run this in debug through Eclipse it works. If I include the JRViewer and JRViewerToolBar classes in my code and change the code to use the following snippet:

    public Image getIcon(String action) {
    try {
        loader = getClass().getClassLoader();
        java.io.InputStream in = 
                loader.getResourceAsStream(action);
        if (in != null) {
            ByteArrayOutputStream bout = new ByteArrayOutputStream(1000);
            byte buf[] = new byte[256];
            int n = 0;
            while((n=in.read(buf, 0, buf.length))>=0)
                bout.write(buf, 0, n);
            return Toolkit.getDefaultToolkit().createImage(bout.toByteArray());
        }
    } catch (Throwable e) { }
    return null;
}

where action is "/net/sf/jasperreports/view/images/save.GIF" it also works.

It is obviously a problem with determining the resource path. I suspect the app I am using uses its own class loader to load my extension.

The question is: Is there a way of loading the JasperReports classes so they behave themselves? Alternatively all I can see is having a modified version of JasperReports in my extension, which is going to introduce bugs and be a maintenance nightmare.

EDIT

This is not a duplicate of the File Resolver question. This is about the class loader used to load the Jasper classes from within an application.

The issue is the CLASS-PATH of Moneydance (the app being extended). The path contains the jars of Moneydance and the extension itself because the ClassLoader has been extended. The method getResourceAsStream has been overwritten but he method getResource has not so getResource does not find the Jasper resources. The solution I have come up with is to load an executable jar (using Spring Boot) containing the JasperReports code and build an interface into that jar.

I am using as custom class loader to load the background task that contains the Jasper classes. I can intercept the getResources method and find the resource in the jar.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM