Menu

ViewPart NoClassDefFoundError

2009-07-15
2013-04-16
  • Bill Andreopoulos

    Hello,
    I am new to eclipse RCP plugins, and I am adding a ViewPart extension which includes a Jasper report. The report should be displayed when an action from a menu is generated.
    However, I get these errors when I click on the menu.
    Please, any ideas why these are generated?
    Thanks.
    ________________________________________________
    java.lang.NoClassDefFoundError: com/jasperassistant/designer/viewer/ViewerComposite
        at java.lang.Class.getDeclaredConstructors0(Native Method)
        at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
        at java.lang.Class.getConstructor0(Unknown Source)
        at java.lang.Class.newInstance0(Unknown Source)
        at java.lang.Class.newInstance(Unknown Source)
        at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:170)
        at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:867)
        at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:243)
        at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:51)
        at org.eclipse.ui.internal.WorkbenchPlugin$1.run(WorkbenchPlugin.java:267)
        at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
        at org.eclipse.ui.internal.WorkbenchPlugin.createExtension(WorkbenchPlugin.java:263)
        at org.eclipse.ui.internal.registry.ViewDescriptor.createView(ViewDescriptor.java:63)
        at org.eclipse.ui.internal.ViewReference.createPartHelper(ViewReference.java:328)
        at org.eclipse.ui.internal.ViewReference.createPart(ViewReference.java:230)
        at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:594)
        at org.eclipse.ui.internal.Perspective.showView(Perspective.java:2131)
        at org.eclipse.ui.internal.WorkbenchPage.busyShowView(WorkbenchPage.java:1062)
        at org.eclipse.ui.internal.WorkbenchPage$19.run(WorkbenchPage.java:3773)
        at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
        at org.eclipse.ui.internal.WorkbenchPage.showView(WorkbenchPage.java:3770)
        at org.eclipse.ui.internal.WorkbenchPage.showView(WorkbenchPage.java:3746)
        at report.jasper.ReportAction2.<init>(ReportAction2.java:25)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
        at java.lang.reflect.Constructor.newInstance(Unknown Source)
        at java.lang.Class.newInstance0(Unknown Source)
        at java.lang.Class.newInstance(Unknown Source)
        at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:170)
        at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:867)
        at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:243)
        at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:51)
        at org.eclipse.ui.internal.WorkbenchPlugin$1.run(WorkbenchPlugin.java:267)
        at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
        at org.eclipse.ui.internal.WorkbenchPlugin.createExtension(WorkbenchPlugin.java:263)
        at org.eclipse.ui.internal.PluginAction.createDelegate(PluginAction.java:122)
        at org.eclipse.ui.internal.PluginAction.runWithEvent(PluginAction.java:223)
        at org.eclipse.ui.internal.WWinPluginAction.runWithEvent(WWinPluginAction.java:229)
        at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:583)
        at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:500)
        at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:411)
        at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
        at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003)
        at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3823)
        at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3422)
        at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2384)
        at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2348)
        at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2200)
        at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:495)
        at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288)
        at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:490)
        at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
        at Application.start(Application.java:33)
        at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
        at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386)
        at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1236)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1212)
    Caused by: java.lang.ClassNotFoundException: com.jasperassistant.designer.viewer.ViewerComposite
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findClassInternal(BundleLoader.java:483)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:399)
        at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:387)
        at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:87)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
        ... 67 more

     
    • Michael Schmidt

      Michael Schmidt - 2009-07-15

      It looks like it is not finding a jasperassistant package.  Perhaps there is a problem in your dependencies.  In my application, I bundled all the .jar files necessary for JasperReports (JasperReports, swtJasperViewer, etc.) into a separate plug-in with necessary components visible to my main application plug-in.  I set up my viewpart to that multiple reports can be opened and then it is isimply a matter of creating the report and opening it via swtJasperViewer.  I'd be happy to send you the code.  You can e-mail me back channel at MichaelMSchmidt@msn.com.

       
  • marco

    marco - 2010-06-29

    Hi,

    I have the same problem, and I found out that it is quite common. Unfortunately I did not succeed with the drafted solutions which were either to register plugins as buddies or tweak the class loader. Probably I miss some details.

    Michael, would you please share relevant parts of your code. Did you do one of the two things I mentioned above?

    Thanks,
    Marco

     
  • marco

    marco - 2010-06-29

    Michael, how did you put the required packages into the dependencies plug-in, just by adding the jars to the build path or even by putting the source code there?

    /m

     
  • Michael Schmidt

    Michael Schmidt - 2010-06-29

    I tried to create a .zip file with the code but there doesn't seem to be any way to attach it, so I'll try to do the explanation in-line.
    First, create a new plug-in to contain the .jar files.  I created a "libraries" directory within the new plug-in and put the libraries there.  Here is the manifest.mf for the library plug-in

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: JasperReports Plug-in
    Bundle-SymbolicName: us.mschmidt.jasperlibs
    Bundle-Version: 1.4.0
    Bundle-Vendor: Michael Schmidt
    Bundle-RequiredExecutionEnvironment: JavaSE-1.6
    Bundle-ClassPath: libraries/ris_tagger.jar,
     libraries/commons-beanutils-1.8.2.jar,
     libraries/spring-beans-2.5.5.jar,
     libraries/spring-core-2.5.5.jar,
     libraries/commons-collections-3.2.1.jar,
     libraries/commons-digester-1.7.jar,
     libraries/commons-logging-1.1.jar,
     libraries/iText-2.1.7.jar,
     libraries/jasperreports-fonts-3.7.2.jar,
     libraries/jasperreports-3.7.2.jar,
     libraries/swtjasperviewer-1.2.0.jar,
     .
    Export-Package: com.jasperassistant.designer.viewer;
      uses:="org.eclipse.jface.window,
       net.sf.jasperreports.view,
       org.eclipse.swt.graphics,
       org.eclipse.swt.widgets,
       net.sf.jasperreports.engine",
     net.sf.jasperreports.engine,
     org.apache.commons.digester;
      uses:="org.apache.commons.logging,
       org.apache.commons.collections,
       javax.xml.parsers,
       org.xml.sax.helpers,
       org.xml.sax"
    Require-Bundle: org.eclipse.swt;bundle-version="3.6.0",
     org.eclipse.jface;bundle-version="3.6.0",
     org.eclipse.core.runtime;bundle-version="3.6.0"
    

    Here is the build.properties for the library plug-in

    source.. = src/
    output.. = bin/
    bin.includes = META-INF/,\
                   .,\
                   libraries/commons-collections-3.2.1.jar,\
                   libraries/commons-digester-1.7.jar,\
                   libraries/commons-logging-1.1.jar,\
                   about.html,\
                   libraries/swtjasperviewer-1.2.0.jar,\
                   libraries/ris_tagger.jar,\
                   libraries/spring-beans-2.5.5.jar,\
                   libraries/spring-core-2.5.5.jar,\
                   libraries/commons-beanutils-1.8.2.jar,\
                   libraries/iText-2.1.7.jar,\
                   libraries/jasperreports-3.7.2.jar,\
                   libraries/jasperreports-fonts-3.7.2.jar
    

    In your main plug-in, add the library plug-in too the dependencies in your .product file.  It should also appear in the "Required Bundles" section of the manifest.mf. 

    I stack reports in a view in my perspective.  Here is the Perspective code that includes this.

    package us.mschmidt.akinoowin;
    import org.eclipse.ui.IFolderLayout;
    import org.eclipse.ui.IPageLayout;
    import org.eclipse.ui.IPerspectiveFactory;
    import us.mschmidt.akinoowin.views.ReportView;
    import us.mschmidt.akinoowin.views.TasksView;
    public class Perspective implements IPerspectiveFactory {
        public static final String PERSPECTIVE_ID = "us.mschmidt.akinoowin.perspective";
        public void createInitialLayout(IPageLayout layout) {
            layout.addStandaloneView(TasksView.VIEW_ID, false, IPageLayout.LEFT,
                    0.25f, layout.getEditorArea());
            layout.getViewLayout(TasksView.VIEW_ID).setCloseable(false);
            layout.getViewLayout(TasksView.VIEW_ID).setMoveable(false);
            final IFolderLayout folder = layout.createFolder("reports", IPageLayout.BOTTOM, 
                    0.80f, layout.getEditorArea());
            folder.addPlaceholder(ReportView.ID_VIEW + ":*");
        }
    
        /**
         * Override to provide useful information when the class toString method is
         * called.
         * 
         * @return  the information String
         * @see     java.lang.Object#toString()
         */
        @Override
        public final String toString() {
            return "us.mschmidt.akinoowin.Perspective is the application's perspective";
        }
    
    }
    

    Here is the viewer that uses swtJasperViewer to display the report.

    package us.mschmidt.akinoowin.views;
    import net.sf.jasperreports.engine.JasperPrint;
    import org.eclipse.swt.SWT;
    import org.eclipse.swt.layout.GridData;
    import org.eclipse.swt.layout.GridLayout;
    import org.eclipse.swt.widgets.Composite;
    import org.eclipse.ui.part.ViewPart;
    import com.jasperassistant.designer.viewer.ViewerComposite;
    public class ReportView extends ViewPart {
        public static final String ID_VIEW = 
            "us.mschmidt.akinoowin.views.ReportView";
        //Using the SWTJasperViewer
        private ViewerComposite viewerComposite;
        /**
         * Create contents of the view part
         * @param parent
         */
        @Override
        public void createPartControl(final Composite parent) {
            final Composite container = new Composite(parent, SWT.NONE);
            final GridLayout layout = new GridLayout();
            container.setLayout(layout);
            viewerComposite = new ViewerComposite(container,SWT.BORDER);
            viewerComposite.setLayoutData(new GridData(GridData.FILL,GridData.FILL,true,true));
        }
        /**
         * Required method, not used here.
         */
        @Override
        public void setFocus() {
            // Set the focus
        }
        /**
         * Sets the JasperPrint object for this ReportView instance.
         * 
         * @param printObject   the JasperPrint object
         */
        public void setJasperDocument(final JasperPrint printObject) {
            viewerComposite.getReportViewer().setDocument(printObject);
        }
        /** 
         * Override to provide useful information when the class tostring() method is
         * called.
         * 
         * @return  the descriptive information
         * @see         java.lang.Object#toString()
         */
        @Override
        public String toString() {
            return "akamai.dbreports.ReportView implements the JasperReports viewer";
        }
    }
    

    Finally, I create the report in a thread using the Jobs implementation.  Here is one of the implementations that shows how to do the classloader switching.

    package us.mschmidt.akinoowin.dbutilities;
    import java.io.File;
    import java.sql.Connection;
    import java.util.Map;
    import net.sf.jasperreports.engine.JRException;
    import net.sf.jasperreports.engine.JasperCompileManager;
    import net.sf.jasperreports.engine.JasperFillManager;
    import net.sf.jasperreports.engine.JasperPrint;
    import org.eclipse.core.runtime.IProgressMonitor;
    import org.eclipse.core.runtime.IStatus;
    import org.eclipse.core.runtime.Status;
    import org.eclipse.core.runtime.jobs.Job;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.ui.IWorkbenchPage;
    import org.eclipse.ui.PartInitException;
    import org.eclipse.ui.PlatformUI;
    import us.mschmidt.akinoowin.views.ReportView;
    import us.mschmidt.akinoowin.constants.XmlConstants;
    import us.mschmidt.akinoowin.constants.ApplicationConstants;
    import us.mschmidt.akinoowin.Application;
    import us.mschmidt.akinoowin.ApplicationActionBarAdvisor;
    import us.mschmidt.akinoowin.extras.ApplicationLogger;
    /**
     * Generates JasperReports in a helper thread.
     */
    public class ReportListJob extends Job {
    
        private final String fileName;
        protected final String reportName;
        private final String jrFile;
        private final Map<String, String> parms;
        private String errMsg;
        private JasperPrint jPrint;
        private boolean ranOK;
        /**
         * The class constructor.
         * 
         * @param jobName       the name of this job instance
         * @param nameVal       the report name
         * @param fileVal       the .jasper file for this report
         * @param parmVals  the map of parameters
         */
        public ReportListJob(final String jobName, final String nameVal, 
                final String fileVal, final Map<String, String> parmVals) {
            super(jobName);
            reportName = nameVal;
            fileName = fileVal;
            jrFile = XmlConstants.REPORTS_DIR + fileName;
            parms = parmVals;
        }
        /**
         * The job runnable.
         * 
         * @param monitor   the job progress monitor
         * @return              the job IStatus
         */
        @Override
        protected IStatus run(final IProgressMonitor monitor) {
            Connection conn = null;
            jPrint = null;
            ranOK = true;
            errMsg = null;
            // Begin the task monitor
            monitor.beginTask("Report " + reportName, 7*ApplicationConstants.JOB_STEP);
            // Classloader swapping is required, so back up the default classloader
            final Thread thread = Thread.currentThread();
            final ClassLoader eclipseLoader = thread.getContextClassLoader();
            monitor.worked(ApplicationConstants.JOB_STEP);
    
            try {
                // Begin the job monitor
                monitor.worked(ApplicationConstants.JOB_STEP);
    
                // make sure Jasper report file exist
                final File f = new File(jrFile);
                if (!f.isFile()) {
                    errMsg = "Cannot find Jasper file";
                    ranOK = false;
                    ApplicationLogger.logInfo("ReportList error: Unable to find Jasper file " + jrFile);
                    return Status.CANCEL_STATUS;
                }
    
                // Acquire a database lock
                Application.getConnectionManager().acquireLock();
                monitor.worked(ApplicationConstants.JOB_STEP);
    
                // Connecting to the database
                conn = Application.getConnectionManager().getConnection();
                if (null == conn) {
                    ApplicationLogger
                        .logInfo(Application.getConnectionManager().getMessage());
                    ApplicationLogger
                        .logInfo("Report job unable to acquire database connection");
                    ranOK = false;
                    errMsg = "ReportList error: No database connection";
                    return Status.CANCEL_STATUS;
                }
                monitor.worked(ApplicationConstants.JOB_STEP);
    
                // Load custom classloader
                thread.setContextClassLoader(JasperCompileManager.class.getClassLoader());
                monitor.worked(ApplicationConstants.JOB_STEP);
                // Fill the report with data from
                // the database using the passed parameters.
                jPrint = JasperFillManager.fillReport(jrFile, parms, conn);
                monitor.worked(ApplicationConstants.JOB_STEP);
            }catch(final JRException e){
                errMsg = "JasperFill error";
                ranOK = false;
                ApplicationLogger.logError("ReportList JR error" + e.getMessage(), 
                        e.getCause());
            }finally{
                // Close the database connection and release the lock
                Application.getConnectionManager().closeConnection();
                Application.getConnectionManager().releaseLock();
                monitor.worked(ApplicationConstants.JOB_STEP);
    
                // Replace custom classloader with the original classloader.
                thread.setContextClassLoader(eclipseLoader);
                monitor.worked(ApplicationConstants.JOB_STEP);
    
                // End the monitor
                monitor.done();
    
                // Make sure a JasperPrint object was created
                if (null == jPrint) {
                    ranOK = false;
                    if (null == errMsg) {
                        errMsg = "JasperPrint object not created";
                        ApplicationLogger.logInfo("ReportList error:  JasperPrint object not created");
                    }   
                }
    
                // Display results
                showResults();
            }
            return Status.OK_STATUS;
        }
        /**
         * Output results to a view upon completion of task.
         * 
         * @param jp    the JasperPrint object
         * @param b     boolean true if job ran, false if errors occurred
         */
        protected final void showResults() {
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    if (!ranOK) {
                        if (null == errMsg) {
                            errMsg = "Unable to create report";
                        }
                        ApplicationActionBarAdvisor.postMessage(errMsg, true);
                        return;
                    }
                    try {
                        final ReportView rv = (ReportView) PlatformUI.getWorkbench()
                            .getActiveWorkbenchWindow().getActivePage().showView(
                                    ReportView.ID_VIEW, reportName, IWorkbenchPage.VIEW_VISIBLE);
                        rv.setJasperDocument(jPrint);
                    } catch (final PartInitException e) {
                        ApplicationLogger.logError("ReportList View error " + e.getMessage(), 
                                e.getCause());
                    }
                }
            });
        }
    }
    

    Hopefull, that's everything folks will need.

     
  • marco

    marco - 2010-06-30

    Michael,

    Thanks a lot for your post.

    I immediately tried it. I got unresolvable types, and I had to add the following to my plug-in's build.properties:

    jars.extra.classpath = platform:/plugin/org.foo.bar.jasperReports/lib/commons-collections-3.1.jar,\
                           platform:/plugin/org.foo.bar.jasperReports/lib/commons-beanutils-1.7.0.jar,\
                           platform:/plugin/org.foo.bar.jasperReports/lib/commons-digester-2.0.jar,\
                           platform:/plugin/org.foo.bar.jasperReports/lib/commons-logging-1.0.jar,\
                           platform:/plugin/org.foo.bar.jasperReports/lib/iText-2.1.7.jar,\
                           platform:/plugin/org.foo.bar.jasperReports/lib/jasperreports-3.7.3.jar,\
                           platform:/plugin/org.foo.bar.jasperReports/lib/swtjasperviewer-1.2.0.jar
    
    The type net.sf.jasperreports.engine.JasperPrint cannot be resolved. It is indirectly referenced from required .class files ReportGen.java
    
    The project was not built since its build path is incomplete. Cannot find the class file for net.sf.jasperreports.engine.JasperPrint. Fix the build path then try building this project
    

    I think this brings the whole thing about separate plug-in and dependency to absurdity.

    And then when I run it get the a similar error

    java.lang.NoClassDefFoundError: net/sf/jasperreports/engine/JasperCompileManager
    

    already for the statement to change the classloader:

    thread.setContextClassLoader(JasperCompileManager.class.getClassLoader());
    

    I do not run this code in a job but in a simple menu handler. But this should not make a difference. But what else might I be missing?

    Your help very much appreciated.

    Thanks,
    Marco

     
  • Michael Schmidt

    Michael Schmidt - 2010-06-30

    There's something wrong in your implementation, but I'm not sure what.  Here are some ideas to start with.
    1.  The necessary .jar files (referenced in the manifest.mf and build.properties files) must be copied to your libraries plug-in (let's call it JasperLibs).  You might need to do a "Refresh" on JasperLibs to make sure the copied .jar files register with the workspace.  Make sure the manifest.mf export packages is like my example - this exposes the necessary methods to your main plug-in.
    2.  The JasperLibs plug-in must be referenced in your main plug-in .product file and as a required bundle in its manifest.mf. 
    3.  You absolutely do not have to include the JasperLibs .jar files in your main plug-in build.properties file.
    4.  In my sample code, ignore references to ris_tagger.jar.  That is a custom .jar file that I created for my specific application.

    I encourage you to keep trying and I will try to help you out.  It is worthwhile to have the Jasper libraries in a separate plug-in from a code maintenance perspective - updates are easier to manage.

     
  • marco

    marco - 2010-06-30

    Michael,

    1. and 3. Stating the plug-in dependency from main to dependency plg-in was not enough. I had to add the jars.extra.classpath in the main plg-in's build.properties. Otherwise I could not avoid the the type not resolved errors. I no clue why.

    2. I do not have an application. The plug-in are currently intended for direct deployment onto the platform. I don't have a product either yet, just the plug-ins.

    Actually I do not even understand how your approach could work. You request the ClassLoader from a class (JasperCompileManager) which cannot be addressed from the current ClassLoader. How can this work???

    /m

     

Log in to post a comment.