使用docx4j将.docx转换为.pdf时生成空PDF并抛出NoSuchMethodError错误的解决方案求助
从你的栈跟踪信息java.lang.NoSuchMethodError: org.docx4j.jaxb.Context.getFopConfigContext()可以直接定位到核心问题:你混用了不同版本的docx4j依赖组件,导致API不兼容,最终触发错误并生成空PDF文件。
问题根源
你的依赖配置里,docx4j-JAXB-Internal是8.3.4版本,而其他核心转换组件(比如docx4j-export-fo)都是11.4.6版本。版本差异使得高版本组件试图调用低版本中不存在的方法,直接引发了NoSuchMethodError。另外,你同时引入了三个JAXB实现(Internal、ReferenceImpl、MOXy),这会导致依赖冲突,进一步加重问题。
解决方案步骤
1. 统一依赖版本并清理冲突的JAXB依赖
把所有docx4j组件的版本统一为11.4.6,并且只保留一个JAXB实现(避免冲突)。推荐使用docx4j-JAXB-ReferenceImpl,修正后的Maven依赖如下:
<dependency> <groupId>org.docx4j</groupId> <artifactId>docx4j-JAXB-ReferenceImpl</artifactId> <version>11.4.6</version> </dependency> <dependency> <groupId>org.docx4j</groupId> <artifactId>docx4j-export-fo</artifactId> <version>11.4.6</version> </dependency>
注意:移除
docx4j-JAXB-Internal和docx4j-JAXB-MOXy,如果需要使用MOXy作为JAXB实现,只保留docx4j-JAXB-MOXy即可。
2. 优化Kotlin代码的资源管理
你的代码手动调用flush()和close()存在风险——如果转换过程中抛出异常,流可能无法正确关闭。Kotlin的use块可以自动管理资源,确保流始终被正确处理:
class DocxToPdf { fun convert(inputFile: File, outputFile: File) { inputFile.inputStream().use { inputStream -> outputFile.outputStream().use { outputStream -> val wordMLPackage = WordprocessingMLPackage.load(inputStream) Docx4J.toPDF(wordMLPackage, outputStream) } } } }
这里直接用
File作为参数比FileInputStream更灵活,use块会自动处理流的打开和关闭,无需手动操作,代码也更简洁健壮。
3. 补充缺失的依赖(可选)
如果仍然遇到问题,检查是否缺少Apache FOP的依赖(docx4j-export-fo依赖它来生成PDF),可以显式添加以下依赖确保完整性:
<dependency> <groupId>org.apache.xmlgraphics</groupId> <artifactId>fop</artifactId> <version>2.9</version> </dependency>
为什么这样能解决问题
- 统一版本后,所有docx4j组件的API保持一致,不会出现方法找不到的情况。
- 清理多余的JAXB实现避免了类加载冲突,确保使用的JAXB上下文与docx4j版本完全匹配。
use块提升了代码的健壮性,彻底避免资源泄漏的可能。
内容的提问来源于stack exchange,提问作者Ricardo de Vries




