解决使用Oracle JDBC + logback 1.2.5以上版本时报错Error during SAX paser configuration

2022-11-08

我的Ktor server项目要使用call logging功能,于是通过Gradle导入了最新版本(1.4.4)的logback:

implementation("ch.qos.logback:logback-classic:1.4.4")

然而在启动时报了这样的错误:

ch.qos.logback.core.joran.spi.JoranException: Error during SAX paser configuration. See https://logback.qos.ch/codes.html#saxParserConfiguration
    at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:96)
    at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:62)
    at ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(GenericXMLConfigurator.java:178)
    at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:159)
    at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
    at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
    at ch.qos.logback.classic.util.DefaultJoranConfigurator.configureByResource(DefaultJoranConfigurator.java:53)
    at ch.qos.logback.classic.util.DefaultJoranConfigurator.configure(DefaultJoranConfigurator.java:34)
    at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:98)
    at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:77)
    at ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:50)
    at ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:41)
    at org.slf4j.LoggerFactory.bind(LoggerFactory.java:152)
    at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:139)
    at org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:422)
    at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:408)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
    at io.ktor.server.engine.ApplicationEngineEnvironmentBuilder.<init>(ApplicationEngineEnvironmentJvm.kt:36)
    at io.ktor.server.engine.ApplicationEngineEnvironmentKt.applicationEngineEnvironment(ApplicationEngineEnvironment.kt:48)
    at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:90)
    at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:63)
    at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:38)
    at io.ktor.server.engine.EmbeddedServerKt.embeddedServer$default(EmbeddedServer.kt:30)
    at xxx.ApplicationKt.main(Application.kt:8)
    at xxx.ApplicationKt.main(Application.kt)
Caused by: javax.xml.parsers.ParserConfigurationException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.
    at oracle.xml.jaxp.JXSAXParserFactory.setFeature(JXSAXParserFactory.java:272)
    at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:89)
    ... 24 more
15:42:54,414 |-INFO in ch.qos.logback.classic.LoggerContext[default] - This is logback-classic version 1.4.4
15:42:54,437 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
15:42:54,448 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [file:/D:/Projects/IDEA/pacs-queuing-backend/build/resources/main/logback.xml]
15:42:54,520 |-ERROR in ch.qos.logback.core.joran.event.SaxEventRecorder@15ff3e9e - Error during SAX paser configuration. See https://logback.qos.ch/codes.html#saxParserConfiguration javax.xml.parsers.ParserConfigurationException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.
    at javax.xml.parsers.ParserConfigurationException: SAX feature 'http://xml.org/sax/features/external-general-entities' not supported.
    at     at oracle.xml.jaxp.JXSAXParserFactory.setFeature(JXSAXParserFactory.java:272)
    at     at ch.qos.logback.core.joran.event.SaxEventRecorder.buildSaxParser(SaxEventRecorder.java:89)
    at     at ch.qos.logback.core.joran.event.SaxEventRecorder.recordEvents(SaxEventRecorder.java:62)
    at     at ch.qos.logback.core.joran.GenericXMLConfigurator.populateSaxEventRecorder(GenericXMLConfigurator.java:178)
    at     at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:159)
    at     at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:122)
    at     at ch.qos.logback.core.joran.GenericXMLConfigurator.doConfigure(GenericXMLConfigurator.java:65)
    at     at ch.qos.logback.classic.util.DefaultJoranConfigurator.configureByResource(DefaultJoranConfigurator.java:53)
    at     at ch.qos.logback.classic.util.DefaultJoranConfigurator.configure(DefaultJoranConfigurator.java:34)
    at     at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:98)
    at     at ch.qos.logback.classic.util.ContextInitializer.autoConfig(ContextInitializer.java:77)
    at     at ch.qos.logback.classic.spi.LogbackServiceProvider.initializeLoggerContext(LogbackServiceProvider.java:50)
    at     at ch.qos.logback.classic.spi.LogbackServiceProvider.initialize(LogbackServiceProvider.java:41)
    at     at org.slf4j.LoggerFactory.bind(LoggerFactory.java:152)
    at     at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:139)
    at     at org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:422)
    at     at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:408)
    at     at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
    at     at io.ktor.server.engine.ApplicationEngineEnvironmentBuilder.<init>(ApplicationEngineEnvironmentJvm.kt:36)
    at     at io.ktor.server.engine.ApplicationEngineEnvironmentKt.applicationEngineEnvironment(ApplicationEngineEnvironment.kt:48)
    at     at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:90)
    at     at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:63)
    at     at io.ktor.server.engine.EmbeddedServerKt.embeddedServer(EmbeddedServer.kt:38)
    at     at io.ktor.server.engine.EmbeddedServerKt.embeddedServer$default(EmbeddedServer.kt:30)
    at     at xxx.ApplicationKt.main(Application.kt:8)
    at     at xxx.ApplicationKt.main(Application.kt)

本来以为是Ktor server和最新版本的logback不兼容,搜了半天也没见到有类似情况的bug report,只能一直降级logback,降到1.2.5才能正常运行。

但是在我另一个项目中,同样的Ktor和logback版本,却是没有问题的,这就很奇怪了……
于是再搜了一下,最后根据这个页面的回复,才知道原来是跟Oracle的JDBC驱动有关系……

解决方案就如页面中给出的,把xmlparserv2这个module从Oracle JDBC依赖中排除就好了:

Gradle Kotlin DSL:

implementation("com.oracle.database.jdbc:ojdbc8-production:21.7.0.0") {
    exclude(module = "xmlparserv2")
}

Gradle Groovy DSL:

implementation('com.oracle.database.jdbc:ojdbc8-production:21.7.0.0') {
    exclude(module: 'xmlparserv2')
}