danfickle / openhtmltopdf

An HTML to PDF library for the JVM. Based on Flying Saucer and Apache PDF-BOX 2. With SVG image support. Now also with accessible PDF support (WCAG, Section 508, PDF/UA)!

Home Page:https://danfickle.github.io/pdf-templates/index.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't generate PDFs under WildFly 13: java.lang.NoClassDefFoundError: org/w3c/dom/css/CSSPrimitiveValue

dilworks opened this issue · comments

Right now we're certifying our internal apps to work with the latest shiny stuff. Recently, the WildFly folks switched to a quarterly release model (starting with WF12), so I've decided to check if everything was working as intented with the latest release (as of June 21 that would be WF13). I got very surprised when I was unable to generate PDFs at all - instead I got the following stackdump:

12:58:46,211 ERROR [io.undertow.request] (default task-6) UT005023: Exception handling request to <redacted>.xhtml: java.lang.NoClassDefFoundError: org/w3c/dom/css/CSSPrimitiveValue
	at com.openhtmltopdf.css.constants.CSSName.<clinit>(CSSName.java:129)
	at com.openhtmltopdf.css.parser.CSSParser.declaration(CSSParser.java:1281)
	at com.openhtmltopdf.css.parser.CSSParser.declaration_list(CSSParser.java:728)
	at com.openhtmltopdf.css.parser.CSSParser.ruleset(CSSParser.java:757)
	at com.openhtmltopdf.css.parser.CSSParser.stylesheet(CSSParser.java:227)
	at com.openhtmltopdf.css.parser.CSSParser.parseStylesheet(CSSParser.java:78)
	at com.openhtmltopdf.context.StylesheetFactoryImpl.parse(StylesheetFactoryImpl.java:76)
	at com.openhtmltopdf.simple.extend.XhtmlCssOnlyNamespaceHandler.getDefaultStylesheet(XhtmlCssOnlyNamespaceHandler.java:384)
	at com.openhtmltopdf.context.StyleReference.getStylesheets(StyleReference.java:226)
	at com.openhtmltopdf.context.StyleReference.setDocumentContext(StyleReference.java:88)
	at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.setDocumentP(PdfBoxRenderer.java:297)
	at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.setDocumentP(PdfBoxRenderer.java:265)
	at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.setDocumentFromStringP(PdfBoxRenderer.java:276)
	at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.<init>(PdfBoxRenderer.java:217)
	at com.openhtmltopdf.pdfboxout.PdfRendererBuilder.buildPdfRenderer(PdfRendererBuilder.java:56)
	at <redacted>.reportes.OHPDFBoxProducer.generate(OHPDFBoxProducer.java:38)
	at <redacted>.reportes.PDFExportFilter.doFilter(PDFExportFilter.java:159)
	at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
	at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
	at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
	at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
	at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
	at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
	at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
	at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
	at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
	at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
	at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
	at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
	at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
	at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
	at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
	at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
	at io.undertow.server.Connectors.executeRootHandler(Connectors.java:360)
	at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
	at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
	at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.w3c.dom.css.CSSPrimitiveValue from [Module "deployment.<redacted>.war" from Service Module Loader]
	at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
	at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
	at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
	... 61 more

That's on a nearly out-of-the-box WildFly 13 setup (all I've done was to setup my JDBC drivers, datasources and JPA provider - nothing else!) using OpenJDK 8 (not 9, not 10 - good ol' Java 8).

I'm able to generate PDFs without issues under WF11 (didn't bothered testing with WF12).

AFAIK CSSPrimitiveValue IS a core Java class (I've checked - it's there on rt.jar) - so, what class of classpath shenanigans (no pun intended!) is playing WildFly on me this time?! For now this is a showstopper for our future WildFly deployments, as staying on WF11 is not a viable longtime option :/

Indeed, WF/JBoss classloaders were the culprit here.

The workaround is to create a jboss-deployment-structure.xml and declare there all the extra classes from rt.jar your .WAR will require. In my case, this:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1">
    <deployment>
        <dependencies>
            <system export="true">
                <paths>
                    <path name="org/w3c/dom/css"/>              
                </paths>
            </system>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Workaround source: https://stackoverflow.com/questions/12492717/jboss-7-1-1-add-rt-jar-of-jre-to-classpath

So yeah, that was supermegahyper fun... NOT! This also most likely means everything has been working on prior WF releases due to pure sheer luck!? I'm... confused. But hey, at least I can advance with testing here!

I just ran into this myself while trying to put openhtmltopdf on the module path.

Turns out CSSPrimitiveValue is JDK internal API (see here for a list of unsupported DOM packages). It probably never was officially supported, but good old classpath did not restrict access and so people depended on it. So Wildfly is correct here and openhtmltopdf is the culprit.

I'll look if we can remove it or replace it with something supported.

Edit: I looked through openhtmltopdf-core and most usages are just the constants from the two interfaces CSSPrimitiveValue and CSSValue, the other DOM packages are not used at all. There is only one implementation of those interfaces that is used for everything, PropertyValue. There are also a lot of casts that just assume PropertyValue, so this doesn't seem like an extension point. The other implementation, FSCssValue, is never used in the whole project. So putting all those constants on PropertyValue directly would get rid of the dependency.

@danfickle What do you think? Would you accept a pull request for this (including tests, of course)?

Hi @zimmi,

I'm working on this now. I think the easiest solution is to recreate CSSValue and CSSPrimitiveValue, or at least the parts we need (the constants), and then change the imports. I'll do this now.

On a related note, after many minutes Googling I can't seem to find a way to test the module path of something without a module-info.java. Any ideas?

OK, done!

Wow, that's awesome! You fixed everything while I was sleeping. :)
To your question: I think it's too early to test on the module path directly, that becomes much simpler once the minimum required Java version supports it and all dependencies are also modularized.

To avoid depending on internal API in the future, static analysis would be best I think. The maven-jdeps-plugin could be used for that. It's available since Java 8, so it should work.

Thanks everyone. Closing now. Please reopen if required.