我正在使用 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 存在一个大问题。
当 XJC 为 JDK 打包时,所有 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
中的“内部”XJC .
(这也是您应该同时打开 com.sun.tools.xjc.Options.findServices=true
和 com.sun.tools.internal.xjc.Options.findServices=true
来调试插件加载的原因。)
基本上,为“独立”XJC 开发的插件与“内部”XJC 不兼容,反之亦然。
据我所知,大多数 XJC 插件都是为“独立”XJC 开发的。
XJC 2.3 版本和 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 版本不兼容。
关于java - 使用 JAXB/XJC 插件时出现无法识别的参数 -XsomePlugin 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50669567/