我正在做一个用Sping Boot (v.2.7.5)和Java 17构建的项目,它必须处理XML。它从一大堆XSD文件生成源代码,并使用API将XML上传到第三方。它必须处理XML的编组和解组,以及名称空间等。不过这不是问题。
在应用程序的一部分中,从磁盘获取文件,将其解组为Java对象(属于生成的类类型之一),然后使用对象的设置器之一将一些信息添加到对象中,然后使用API将xml内容上传到第三方。
问题是,当应用程序几乎同时要解组两个文件时(Sping Boot 将它们作为单独的调度作业来处理,因此不会在同一个函数或类似的函数中处理它们),其中一个成功,另一个(按处理顺序第二个)抛出异常:
javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
...
Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:92)
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:125)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:230)
这太奇怪了!如果JAXB-API实现不在类路径上,它怎么能成功呢?
应用程序使用Gradle构建,build.gradle包含以下内容:
dependencies {
....
// JAXB
implementation "javax.xml.bind:jaxb-api:2.3.1"
runtimeOnly "com.sun.xml.bind:jaxb-impl:2.3.3"
}
很明显,JAXB-API的实现在类路径上!
我已经尝试了所有的各种实现,Glassfish,EclipseLink MOXy等各种版本,都有同样的问题。
更奇怪的是,当我在IDE中运行应用程序时,我没有收到这个错误,而是在应用程序被打包到Docker容器中时(它在生产环境中的Kubernetes集群中运行)收到了这个错误。
有人遇到过这样的事情吗?
1条答案
按热度按时间gj3fmq9x1#
事实证明,编组器和解组器在JAXB中不是线程安全的,如下所述:https://javaee.github.io/jaxb-v2/doc/user-guide/ch06.html#d0e6879
我还更新到了jaxb-impl的2.3.7版,这可能对正在解决的问题没有真实的的影响,但我想把它放在那里以防万一。
解决方案是每次创建一个新的解组器,并在一个非静态方法中完成。