Skip to content

NoClassDefFoundError: javax/naming/NamingException in a modular Application with logback.xml #1003

@Maran23

Description

@Maran23

I have a small modular Application that uses SLF4J - 2.0.17 with Logback - 1.5.25.
The Application is built by using JLink + JPackage.

When running the Application, the following Error is printed and the Application will not start:

Caused by: java.lang.NoClassDefFoundError: javax/naming/NamingException
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.joran.ModelClassToModelHandlerLinker.link(ModelClassToModelHandlerLinker.java:52)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.joran.JoranConfigurator.addModelHandlerAssociations(JoranConfigurator.java:95)
	at ch.qos.logback.core@1.5.25/ch.qos.logback.core.joran.GenericXMLConfigurator.processModel(GenericXMLConfigurator.java:215)
	at ch.qos.logback.core@1.5.25/ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:178)
	at ch.qos.logback.core@1.5.25/ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:123)
	at ch.qos.logback.core@1.5.25/ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:66)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.util.DefaultJoranConfigurator.configureByResource(DefaultJoranConfigurator.java:68)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.util.DefaultJoranConfigurator.configure(DefaultJoranConfigurator.java:35)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.util.ContextInitializer.invokeConfigure(ContextInitializer.java:134)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:101)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:67)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:51)
	at ch.qos.logback.classic@1.5.25/ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:44)
	at org.slf4j@2.0.17/org.slf4j.LoggerFactory.bind(LoggerFactory.java:201)
	at org.slf4j@2.0.17/org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:187)
	at org.slf4j@2.0.17/org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:511)
	at org.slf4j@2.0.17/org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:497)
	at org.slf4j@2.0.17/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:446)
	at org.slf4j@2.0.17/org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:472)
    ...
Caused by: java.lang.ClassNotFoundException: javax.naming.NamingException
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
	... 28 more

This can also be reproduced in the IDE with the following VM Argument:
--limit-modules=java.base,org.slf4j,ch.qos.logback.core,ch.qos.logback.classic

The module-info of my Application is defined with:

    requires org.slf4j;
    requires ch.qos.logback.core;
    requires ch.qos.logback.classic;

There is also a minimal logback.xml. It can be as minimal as the following to trigger the error:

<configuration>
</configuration>

Without a logback.xml (or completely empty file), this error is not triggered.

Investigation

The following is what I found out and possible solutions:

Logback-core requires static the java.naming module:

module ch.qos.logback.core {
    requires transitive java.xml;
    requires static java.sql;

    // required by the optional SMTPAppenderBase component
    requires static java.naming;

The comment seems outdated, as InsertFromJNDIModelHandler also uses javax.naming.
The stacktrace suggest that javax.naming is always neeeded when a logback.xml exists.

So one possible solution is to define that in my Applications module-info:

    requires java.naming;

But I do not need JNDI or the SMTPAppenderBase, and therefore the java module (I want to keep the Application as small as possible).
So I'm wondering if we can just not load the InsertFromJNDIModel when we do not have javax.naming bundled?

EDIT: PR created, I have a simple solution which I think makes the most sense as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions