9 Replies Latest reply on Jul 12, 2018 9:44 AM by ehodges

    java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11

    ehodges

      I'm running WildFly 11 on JDK 9.0.4.  Our enterprise app uses Jasper for its reports.  Our enterprise app code tries to compile Jasper reports.  Jasper's JasperCompileManager class tries to load the class "com.sun.tools.javac.Main" to compile the Java code generated from the Jasper JRXML files.

       

      Class.forName("com.sun.tools.javac.Main") throws a ClassNotFoundException at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198).

       

      References to "com.sun.tools.javac.Main" compile, but throw a NoClassDefFoundError at runtime.

       

      Attempts to load "com.sun.tools.javac.Main" fail with a NoClassDefFoundError.

       

      When I run code on the same JDK outside WildFly, it is able to reference and use com.sun.tools.javac.Main.

       

      Any ideas why the JBoss ModuleClassLoader can't load this class?

        • 1. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
          cviniciusm
          • 2. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
            ehodges

            That doesn't apply to my question.  I'm running WildFly on the JDK.  Main is available in other Java apps run on the same JDK.  There's something about WildFly that seems to be preventing my code from using Main.

            • 3. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
              jewellgm

              See the section entitled "Accessing JDK classes".

               

              Class Loading in WildFly - WildFly 10 - Project Documentation Editor

               

              Although the article is for wildfly 10, it is also applicable to wildfly 11.

              1 of 1 people found this helpful
              • 4. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
                ehodges

                Thank you!  That made it work.

                 

                The only down side is, up until today I've been able to avoid any WildFly/JBoss specific things in my EAR.

                • 5. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
                  ehodges

                  If anyone else needs to make Jasper compile JRXML files on Java 9 under Wildfly, this will help:

                   

                   

                  <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">

                      <deployment>

                          <dependencies>

                              <system export="true">

                                  <paths>

                                      <path name="com/sun/tools/javac"/>

                                      <path name="com/sun/tools/javac/code"/>

                                      <path name="com/sun/tools/javac/comp"/>

                                      <path name="com/sun/tools/javac/file"/>

                                      <path name="com/sun/tools/javac/main"/>

                                      <path name="com/sun/tools/javac/model"/>

                                      <path name="com/sun/tools/javac/parser"/>

                                      <path name="com/sun/tools/javac/processing"/>

                                      <path name="com/sun/tools/javac/tree"/>

                                      <path name="com/sun/tools/javac/util"/>

                                      <path name="com/sun/tools/javac/jvm"/>

                                      <path name="com/sun/tools/javac/api"/>

                                  </paths>

                              </system>

                          </dependencies>

                      </deployment>

                  </jboss-deployment-structure>

                  • 6. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
                    jewellgm

                    I understand.  For what it's worth, even with this file embedded in your ear, other app servers would simply ignore it.  Your ear isn't "locked" to wildfly with just this change, so to speak.

                     

                    It can be extremely difficult to keep a deployment completely agnostic of the app server it's deployed in.  Things have improved tremendously over the years, but it's still not perfect.

                    • 7. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
                      ehodges

                      Well, that fixed the first problem.  Jasper can now find "com.sun.tools.javac.Main", but when Jasper tries to compile a report the compiler can't find the Jasper classes.  Classes like 'net.sf.jasperreports.engine.fill.JREvaluator".

                       

                      Those classes are on the classpath.  When I test this outside of WildFly the com.sun.tools.javac.Main compiler can find the Jasper classes.

                       

                      I tried adding paths to the Jasper packages in the deployment structure XML file, but something in WildFly is still blocking them.

                      • 8. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
                        jewellgm

                        I'm not sure I understand completely how your deployment is configured.  Are the Jasper jars in the ear's lib directory, or the embedded war's WEB-INF/lib directory?  Or are they in some arbitrary location on the filesystem?  If they are in the filesystem, you'll need to create a module.  The module itself can point to dependencies anywhere, a dependency to the the module can be added to the jboss-deployment-structure.xml.

                         

                        For modules, anything that is provided with wildfly will be in the $WILDFLY_HOME/modules/system/layers/base directory.  For people that create their own modules, they are typically placed directly $WILDFLY_HOME/modules.

                         

                        The same article that I linked to above shows examples of how to modify the jboss-deployment-structure.xml file to add dependencies to "normal" modules in the section above the Accessing JDK Classes.

                         

                        Understanding the wildfly classloading mechanism is something that a lot of newcomers have problems with.  It may seem burdensome at first, but it really is pretty great.  All of the restrictions are meant to prevent issues such as having multiple instances of a class loaded, and not knowing which definition is being used.  Of course, those things can still happen, but it's usually because the deployments themselves are embedding things that they shouldn't be.

                        • 9. Re: java.lang.NoClassDefFoundError: com/sun/tools/javac/Main in WildFly 11
                          ehodges

                          The Jasper jars are in our EAR.

                           

                          In addition to the Jasper jars, our reports have dependencies on our own classes.  Some of those are deployed in the EAR and others are deployed in apps.  We provide our own classloader that makes classes in those apps available.  The apps can be deployed without restarting the enterprise application.

                           

                          I solved our problem by adding the Eclipse ECJ compiler to our EAR.  Jasper looks for that compiler first.  That compiler uses our enterprise app's classloader, so it can see all of the classes in our EAR and our apps.  The com.sun.tools.javac.Main compiler used WildFly's ModuleClassLoader, not ours.

                           

                          Thanks for your help.