Непризнанный параметр -XsomePlugin ошибка при использовании JAXB / XJC-плагинов

lexicore спросил: 10 мая 2018 в 04:37 в: java

Я компилирую XML-схему с использованием JAXB / XJC, и я хочу использовать некоторый плагин 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 или не активирован.

В чем может быть причина и как я могу отладить эту ошибку?

1 ответ

lexicore ответил: 10 мая 2018 в 05:45

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 FQCNs классов плагинов.

Есть два варианта XJC:

  • "Автономный" XJC доступен как артефакт jaxb-xjc-<version>.jar. Используется (среди прочих) в maven-jaxb2-plugin.
  • "Внутренний" XJC, упакованный с JDK. Это то, что вызывается, когда вы вызываете 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. Для "внутреннего" XJC в 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 существуют несовместимые изменения.

Таким образом, в XJC 2.3 класс Aspect был перенесен из пакета com.sun.tools.xjc.model в пакет com.sun.tools.xjc.outline. Это означает, что плагины, которые использовали com.sun.tools.xjc.model.Aspect в версиях XJC раньше 2.3, не будут работать с 2.3. Возможно, есть и другие примеры.

Это означает, что плагин XJC может быть просто несовместим с используемой версией XJC.