Standard Java libraries NoClassDefFoundError

Hello all,

Apologies if my mistake is something relatively noobish; I’m not particularly familiar with Java so I’m learning as I go.

I’ve created a Java library for Lucee to enable local printing from a .CFM file by creating a custom <cf_print> tag. The code is working perfectly within the Java IDE (Eclipse) and is pretty much done. It -was- working in Lucee as an exported JAR (as an incomplete version). However, somewhere along the line, I started getting Lucee 6.0.1.83 Error (java.lang.NoClassDefFoundError) on some of the javax.print sub-classes, such as javax.print.attribute.standard.Media, or pretty much anything under javax.print.attribute.standard, whenever trying to call a method which contains them, through a .CFM file running within the Lucee environment.

I was able to call these classes from Lucee using earlier versions of the program, however those seem to have broken now too. Also, certain classes within javax.print are still working, like I think one of them is javax.print.attribute.PrintRequestAttributeSet.

I understand that the error is saying it was able to find these resources at compile time, but not at runtime, and given that they were working but stopped, this makes me believe that something changed within our Lucee config that’s causing my JAR to no-longer find this library. However, I’ve been unable to find any cause or solution.

It also strikes me as odd, since these libraries have been part of Java for quite some time, that my JAR can’t find them from within Lucee.

We wrote a simple CFM (not using a custom Java library) to show the available Java classes within Lucee, and the ones in question do show up. Not sure why my JAR can’t see them.

I don’t think we have any particular security setting blocking access or anything like that, nothing that we would’ve enabled at this point anyways.

It probably is something I’m doing wrong or some misconfiguration, but I’d appreciate any help navigating!

(Below is a very trimmed down, quick&dirty version of my full program that I wrote as a test.)

(JavaxPrintTest.java)
// import javax.print.*;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.PrintServiceLookup;
import javax.print.PrintService;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Fidelity;
import javax.print.attribute.standard.Media;
import javax.print.attribute.standard.MediaTray;

public class JavaxPrintTest {
    public static void main(String[] args) {
    	System.out.println(showPrintServices());
    }
	public static String showPrintServices() {
        String myString = "";
		PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
        myString += "Number of print services: " + printServices.length + "\r\n";
        for (PrintService printer : printServices) {
        	
            myString += "Printer: " + printer.getName() + "\r\n";
        }

        String printer = "HP LaserJet 600 M601 M602 M603 PCL6";
		PrintService printService = findPrintService(printer); // Look up print service based on printer name
        // MediaTray tray = findMediaTray(printService, "Tray 5");        
        myString += ShowMediaTray(printService, "Tray 5");
			attributes.add(Fidelity.FIDELITY_FALSE);
        return myString;
	}

    // Utility method to find a print service by its name
    private static PrintService findPrintService(String printerName) {
        PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
        for (PrintService service : printServices) {
            if (service.getName().equalsIgnoreCase(printerName)) {
                return service;
            }
        }
        return null;
    }

    // Utility method to find a specific media tray by name within the available print service
    private static String ShowMediaTray(PrintService service, String trayName) {
        if (service == null) {
            return null;
        }
        
        // Fetch all available media (paper trays, etc.) from the print service
        Media[] medias = (Media[]) service.getSupportedAttributeValues(Media.class, null, null);
        String MediaVal = ""; 
        if (medias != null) {
        	// Iterate over the media to find the specified tray
    		for (Media media : medias) {
    			MediaVal += media + "\r\n";
    		}
        }
        return MediaVal;
    }
}

OS: Windows Server 2022 Standard (21H2)
Java Version: 11.0.6 (AdoptOpenJDK) 64bit
Tomcat Version: Apache Tomcat/9.0.34
Lucee Version: Lucee 6.0.1.83

As far as I inderstand, the Lucee engine is not finding your library for some reason. How are you embedding the compiled Java classes to your cf_print custom tag? Please share the code of your custom tag and the full exception that is being generated.

Sure, so I’m not using a custom tag for this test version. For this, I’m just calling the Java function directly using <cfscript>.

(c:\inetpub\wwwroot\print_test\LuceeJavaxPrintTest.cfm)
<cfscript>
    // Create an instance of your Java class
    JavaXPrintTestInstance = CreateObject("java", "com.cigcustom.lucee.JavaxPrintTest");
    
    message = JavaXPrintTestInstance.showPrintServices();
    
    // Output the result
    WriteOutput(message);
</cfscript>

Here is the error I get when running this .CFM in Lucee:

Lucee 6.0.1.83 Error (java.lang.NoClassDefFoundError)
Message	javax/print/attribute/standard/Fidelity
Stacktrace	The Error Occurred in
C:\inetpub\wwwroot\print_test\LuceeJavaxPrintTest.cfm: line 5
3:     JavaXPrintTestInstance = CreateObject("java", "com.cigcustom.lucee.JavaxPrintTest");
4:     
5:     message = JavaXPrintTestInstance.showPrintServices();
6:     
7:     // Output the result

Java Stacktrace	lucee.runtime.exp.NativeException: javax/print/attribute/standard/Fidelity
  at com.cigcustom.lucee.JavaxPrintTest.showPrintServices(JavaxPrintTest.java:28)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
  at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:56)
  at lucee.runtime.java.JavaObject.call(JavaObject.java:265)
  at lucee.runtime.java.JavaObject.call(JavaObject.java:287)
  at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787)
  at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1998)
  at print_test.luceejavaxprinttest_cfm$cf.call(/print_test/LuceeJavaxPrintTest.cfm:5)
  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:1028)
  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:951)
  at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:65)
  at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:45)
  at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2715)
  at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2701)
  at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2672)
  at lucee.runtime.engine.Request.exe(Request.java:45)
  at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1259)
  at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1205)
  at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
  at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
  at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:432)
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  at java.base/java.lang.Thread.run(Unknown Source)
 Caused by: java.lang.NoClassDefFoundError: javax/print/attribute/standard/Fidelity
  ... 45 more

The code runs fine within Eclipse, and returns a list of installed printers, as well as a list of media types available on a specific printer within our environment.

Here is the custom tag code for <cf_print>:

(c:\lucee\tomcat\lucee-server\context\customtags\cf_print.cfm)
<cfparam name="attributes.printer">
<cfparam name="attributes.source">
<cfparam name="attributes.attributeStruct">
<cfparam name="attributes.pages">

<cfscript>
	CreateObject("java", "com.cigcustom.lucee.CFPrint03_CIG").printFile(attributes.printer, attributes.source, attributes.attributeStruct, attributes.pages);
</cfscript>
(c:\inetpub\wwwroot\print_test\LuceePrintWorld3.cfm)

<cfset plain_printer_settings=StructNew()>
<cfset plain_printer_settings["mediatype"] = "Plain">
<cfset plain_printer_settings["pagescaling"] = "none">

<cf_print printer="HP LaserJet 600 M601 M602 M603 PCL6" source="c:\temp\Multipage_Test.pdf" attributeStruct="#plain_printer_settings#" pages="1">

That returns a similar error, but in this case on javax.print.attribute.standard.Media

Lucee 6.0.1.83 Error (java.lang.NoClassDefFoundError)
Message	javax/print/attribute/standard/Media
Stacktrace	The Error Occurred in
/print.cfm: line 9
called from C:\inetpub\wwwroot\print_test\LuceePrintWorld3.cfm: line 5
Java Stacktrace	lucee.runtime.exp.NativeException: javax/print/attribute/standard/Media
  at com.cigcustom.lucee.CFPrint03_CIG.findSupportedMedia(CFPrint03_CIG.java:274)
  at com.cigcustom.lucee.CFPrint03_CIG.handlePrintAttributes(CFPrint03_CIG.java:151)
  at com.cigcustom.lucee.CFPrint03_CIG.printFile(CFPrint03_CIG.java:93)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
  at java.base/java.lang.reflect.Method.invoke(Unknown Source)
  at lucee.runtime.reflection.pairs.MethodInstance.invoke(MethodInstance.java:56)
  at lucee.runtime.java.JavaObject.call(JavaObject.java:265)
  at lucee.runtime.java.JavaObject.call(JavaObject.java:287)
  at lucee.runtime.util.VariableUtilImpl.callFunctionWithoutNamedValues(VariableUtilImpl.java:787)
  at lucee.runtime.PageContextImpl.getFunction(PageContextImpl.java:1998)
  at print_cfm$cf.call(/print.cfm:9)
  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:1028)
  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:951)
  at lucee.runtime.PageContextImpl.doInclude(PageContextImpl.java:943)
  at lucee.runtime.tag.CFTag.doInclude(CFTag.java:319)
  at lucee.runtime.tag.CFTag.cfmlStartTag(CFTag.java:245)
  at lucee.runtime.tag.CFTag.doStartTag(CFTag.java:179)
  at print_test.luceeprintworld3_cfm$cf.call(/print_test/LuceePrintWorld3.cfm:5)
  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:1028)
  at lucee.runtime.PageContextImpl._doInclude(PageContextImpl.java:951)
  at lucee.runtime.listener.ClassicAppListener._onRequest(ClassicAppListener.java:65)
  at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:45)
  at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2715)
  at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2701)
  at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2672)
  at lucee.runtime.engine.Request.exe(Request.java:45)
  at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1259)
  at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1205)
  at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
  at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
  at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:432)
  at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
  at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
  at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  at java.base/java.lang.Thread.run(Unknown Source)
 Caused by: java.lang.NoClassDefFoundError: javax/print/attribute/standard/Media
  ... 54 more

The code for that full version is considerably more complex (and probably out of the scope of this post).

Both are experiencing the same issue, however, on the same subset of native Java libraries, only when run within Lucee. This code also works perfectly when running from Eclipse, and earlier versions did work through Lucee, but stopped somewhere down the line.

If I create a very simple printing JAR that doesn’t call these javax.print.attribute.standard classes, I am still able to print through Lucee. Just without the settings customization we need.

As far as compile, for the test program, I’m just exporting a JAR through Eclipse’s context menu. Only “Export generated class files and resources” is checked. No compression etc.

The JAR for the full program is getting exported as a Maven project, as it uses PDFBox. At first, I was trying to do this without Maven by putting the PDFBox libraries in our Lucee lib folder (c:\lucee\tomcat\lucee-server\context\lib) along with the program JAR, but I ran into struggles with that. Via Maven, I was able to combine PDFBox (as well as a req’d Log4j library) and my program into a fat JAR, which allowed the PDFBox calls to work within Lucee.

To me, it looks like some JAVA dependencies you are using in your IDE are not present in Tomcats JVM. My guess is the javax.print is not there.

That’s certainly what it seems like.

The weird thing though is that they were working. While working on earlier versions of the program, I was able to call classes like javax.print.attribute.standard.Fidelity and javax.print.attribute.standard.Media, through Lucee, and they were (more or less) working.

Additionally, because I can still do some of the functions within the javax.print library (like printing itself), it’s not as if the entire library is missing from Lucee. I find it really strange that I’m suddenly able to access only some of those functions, and wish I could backtrace what changed.

Also Lucee itself seems to see these classes fine. This .CFM’s output shows that Lucee does know they exist.

(C:\inetpub\wwwroot\print_test\javainfo.cfm)
<cfoutput>
<cfsavecontent variable="className_list">javax.print.PrintException
javax.print.PrintService
javax.print.PrintServiceLookup
javax.print.attribute.HashPrintRequestAttributeSet
javax.print.attribute.PrintRequestAttributeSet
javax.print.attribute.standard.Media
javax.print.attribute.standard.MediaSizeName
javax.print.attribute.standard.MediaTray
javax.print.attribute.standard.Chromaticity
javax.print.attribute.standard.Copies
javax.print.attribute.standard.Fidelity
javax.print.attribute.standard.JobName
javax.print.attribute.standard.JobSheets
javax.print.attribute.standard.MediaPrintableArea
</cfsavecontent>
<cfloop list="#className_list#" delimiters="
" index="className">
<cftry>
  <cfset classObject = CreateObject("java", className)>
  #className# is available.
  <cfcatch type="any">
    #className# is not available.
  </cfcatch>
</cftry>
<br>
</cfloop>
</cfoutput>
javax.print.PrintException is available.
javax.print.PrintService is available.
javax.print.PrintServiceLookup is available.
javax.print.attribute.HashPrintRequestAttributeSet is available.
javax.print.attribute.PrintRequestAttributeSet is available.
javax.print.attribute.standard.Media is available.
javax.print.attribute.standard.MediaSizeName is available.
javax.print.attribute.standard.MediaTray is available.
javax.print.attribute.standard.Chromaticity is available.
javax.print.attribute.standard.Copies is available.
javax.print.attribute.standard.Fidelity is available.
javax.print.attribute.standard.JobName is available.
javax.print.attribute.standard.JobSheets is available.
javax.print.attribute.standard.MediaPrintableArea is available.

So it seems like these are available to Lucee, but for some reason have become unavailable to my programs when being called through Lucee.

I’m not sure how I would track this down and fix it.

Okay so I decided to fire up a copy of Lucee Express on a VM, Once up and running (using AdoptOpenJDK 11 HotSpot), I copied my program JARs and relevant files over, and it worked right out the gate!

So there’s definitely a configuration issue on our production server, or maybe Java got corrupted or smthn somehow. I guess I can try reinstalling Java? Or what else should I try here?

I think I got it working!

I was putting my JAR files in C:\lucee\tomcat\lucee-server\context\lib. Noticed on the test VM that I didn’t have that folder; just had C:\lucee\lib, which is where I put it on that VM.

On the production server, I had both folders, so I moved my JARs to C:\lucee\lib\ on the production server, restarted Lucee, and my programs started working!

I did some research, and if I’m understanding this correctly, Tomcat is essentially what Lucee is using to ‘run’ the Java code and return any output. So there can be multiple instances of Tomcat associated with a webserver, should one want to segregate certain packages, but the C:\lucee\lib\ folder exposes these packages globally. In our case this is fine, since this package isn’t particularly sensitive.

However, that does lead me to think something is maybe bugged out with our Tomcat configuration, and maybe a reinstall/reconfiguration of that module might be in our future. At least now I have a direction I can take on that.