java - 使用 JAXB/XJC 插件时出现无法识别的参数 -XsomePlugin 错误
问题描述
我正在使用 JAXB/XJC 编译 XML 模式,并且我想使用一些 XJC 插件来增强生成的代码。
我将插件包含到 XJC 类路径中并使用-XsomePlugin
.
但是我收到如下错误:
Caused by: com.sun.tools.xjc.BadCommandLineException: unrecognized parameter -XsomePlugin
at com.sun.tools.xjc.Options.parseArguments(Options.java:859)
at com.sun.tools.xjc.XJCBase._doXJC(XJCBase.java:804)
... 21 more
所以显然该插件没有被 XJC 拾取或未被激活。
可能是什么原因,我该如何调试这个错误?
解决方案
XJC 使用“服务加载器”机制发现和实例化插件。XJC 插件提供了META-INF\services\com.sun.tools.xjc.Plugin
列出插件类的 FQCN 的资源。
无法加载/实例化插件可能有不同的原因。
打开插件加载错误的日志记录
不幸的是,XJC 通常不会显示在插件实例化期间发生了哪些特定错误。您只会收到此unrecognized parameter -XsomePlugin
消息,仅此而已。
幸运的是,有一个“调试”开关可以使用以下系统属性之一激活:
com.sun.tools.xjc.Options.findServices=true
com.sun.tools.internal.xjc.Options.findServices=true
(我通常设置这两个属性,我将在下面解释原因。)
这将使 XJC 记录插件实例化期间发生的实际错误,例如:
[xjc] java.util.ServiceConfigurationError: com.sun.tools.xjc.Plugin: Provider org.jvnet.jaxb2_commons.plugin.tostring.ToStringPlugin could not be instantiated
[xjc] at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:581)
[xjc] at java.base/java.util.ServiceLoader.access$100(ServiceLoader.java:390)
[xjc] at java.base/java.util.ServiceLoader$ProviderImpl.newInstance(ServiceLoader.java:799)
[xjc] at java.base/java.util.ServiceLoader$ProviderImpl.get(ServiceLoader.java:721)
[xjc] at java.base/java.util.ServiceLoader$3.next(ServiceLoader.java:1389)
[xjc] at com.sun.tools.xjc.Options.findServices(Options.java:1009)
[xjc] at com.sun.tools.xjc.Options.getAllPlugins(Options.java:385)
[xjc] at com.sun.tools.xjc.Options.parseArgument(Options.java:724)
[xjc] at com.sun.tools.xjc.Options.parseArguments(Options.java:857)
....
[xjc] Caused by: java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader (instance of org/apache/tools/ant/AntClassLoader) of the current class, org/slf4j/LoggerFactory, and the class loader (instance of org/apache/tools/ant/loader/AntClassLoader5) for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
[xjc] at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:306)
[xjc] at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:276)
[xjc] at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:156)
[xjc] at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:132)
[xjc] at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:274)
[xjc] at org.jvnet.jaxb2_commons.plugin.AbstractPlugin.<init>(AbstractPlugin.java:28)
.....
如果您已激活这些系统属性,但仍未在日志中看到有关加载插件的任何错误消息,则最可能的原因是:
- 插件库未正确添加到 XJC 类路径;
- 插件库无效,即不提供
META-INF\services\com.sun.tools.xjc.Plugin
具有插件类的 FQCN 的资源。
内部 XJC
XJC有两种口味:
- “独立”XJC 作为
jaxb-xjc-<version>.jar
工件提供。在maven-jaxb2-plugin中使用(除其他外)。 - 与 JDK 一起打包的“内部”XJC。
xjc
这是从命令行调用时调用的内容。
不幸的是,“内部”XJC 存在一个大问题。
当为 JDK 打包 XJC 时,所有 XJC 包都从 重命名com.sun.tools.xjc.*
为 com.sun.tools.internal.xjc.*
。我想这背后有一些非技术原因,但我不会推测。
当com.sun.tools.xjc.*
包被重命名为 时com.sun.tools.internal.xjc.*
,这从本质上破坏了为“独立”XJC 开发的插件的兼容性:
- 为“独立”XJC 开发的 XJC 插件必须扩展
com.sun.tools.xjc.Plugin
. “内部”XJC 期望插件类扩展com.sun.tools.internal.xjc.Plugin
. - 对于“独立”的 XJC 插件,必须在
META-INF\services\com.sun.tools.xjc.Plugin
. 对于META-INF\services\com.sun.tools.internal.xjc.Plugin
.
(这也是您应该同时打开com.sun.tools.xjc.Options.findServices=true
和com.sun.tools.internal.xjc.Options.findServices=true
调试插件加载的原因。)
基本上,为“独立”XJC 开发的插件与“内部”XJC 不兼容,反之亦然。
据我所知,大多数 XJC 插件都是为“独立”XJC 开发的。
XJC 2.3 和 pre-2.3 的兼容性
另一个问题是 XJC 版本之间存在不兼容的更改。
因此,在 XJC 2.3 中,类Aspect
从包com.sun.tools.xjc.model
移到了包com.sun.tools.xjc.outline
。这意味着com.sun.tools.xjc.model.Aspect
在 2.3 之前的 XJC 版本中使用的插件将不适用于 2.3。可能还有其他例子。
这意味着 XJC 插件可能与您使用的 XJC 版本不兼容。
推荐阅读
- php - Laravel:如果 foreach 为空
- python-3.x - 发送 HEX 命令并回读到 rfid reader tcp
- c++ - 从多个函数写入文件并替换值 C++
- angular - 如何在 ionic 4 中禁用侧边菜单?
- python-3.x - 在 pandas 中识别两个不同大小的数据帧中的公共列值
- javascript - 保存/导出 Chrome 的 JavaScript 控制台输入历史
- php - 如何使用验证规则:通过仅比较 foreign_key 在数据上唯一
- javascript - 在 Netlify 上部署 React 网站时出现空白页面
- javascript - 捏合/展开触摸缩放 — 如何避免创建“缩放陷阱”?
- ios - 科尔多瓦 iOS;保存时查看更改