com.sun.tools.xjc.Plugin: поставщик <плагин> не подтип
У меня есть приложение CXF JAX-RS, создаваемое с Maven. Я работаю над преобразованием его в Gradle, но использую задачу Ant XJC.
Текущая сборка использует пару расширений, одно из которых является копией плагина "element wrapper", а другое - "jaxb-fluent-api".
Я попытался поместить файлы jar для этих двух плагинов в путь к классам xjc, но когда я запускаю задачу XJC, я получаю следующее:
java.util.ServiceConfigurationError: com.sun.tools.xjc.Plugin: поставщик dk.conspicio.jaxb.plugins.XmlElementWrapperPlugin не является подтипом
Класс XmlElementWrapperPlugin расширяет com.sun.tools.xjc.Plugin.
Есть идеи, что здесь происходит?
Если это имеет значение, моя конфигурация Maven для плагина xjc выглядит примерно так:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-xjc-plugin</artifactId>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>xsdtojava</goal>
</goals>
<configuration>
<extensions>
<extension>JAXBXMLElementWrapperPlugin:JAXBXMLElementWrapperPlugin:1.0.0</extension>
<extension>net.java.dev.jaxb2-commons:jaxb-fluent-api:2.1.8</extension>
</extensions>
<xsdOptions>
<xsdOption>
<xsd>${basedir}/src/main/resources/schema/serviceCallResults.xsd</xsd>
<packagename>com.att.sunlight.service.domain.serviceCallResults</packagename>
<extension>true</extension>
<extensionArgs>
<extensionArg>-Xxew</extensionArg>
<extensionArg>-summary ${basedir}/target/xew-summary.txt</extensionArg>
<extensionArg>-instantiate lazy</extensionArg>
<extensionArg>-Xfluent-api</extensionArg>
</extensionArgs>
</xsdOption>
</xsdOptions>
</configuration>
</execution>
</executions>
</plugin>
Вот мой "build.gradle", в котором выбраны только репозитории:
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'war'
group = 'SunlightDataService'
version = '1.2.4-SNAPSHOT'
sourceCompatibility = 1.6
targetCompatibility = 1.6
repositories {
...
}
configurations {
jaxb
}
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.7-b41'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.7-b41'
jaxb 'javax.xml.bind:jaxb-api:2.2.7'
jaxb "JAXBXMLElementWrapperPlugin:JAXBXMLElementWrapperPlugin:1.0.0"
jaxb "net.java.dev.jaxb2-commons:jaxb-fluent-api:2.1.8"
compile group: 'org.springframework', name: 'spring-beans', version:'3.2.8.RELEASE'
compile group: 'org.springframework', name: 'spring-webmvc-portlet', version:'3.2.8.RELEASE'
compile group: 'org.apache.cxf', name: 'cxf-rt-transports-http', version:'2.7.7'
compile group: 'log4j', name: 'log4j', version:'1.2.16'
compile group: 'org.springframework', name: 'spring-jdbc', version:'3.2.8.RELEASE'
compile group: 'org.springframework', name: 'spring-context', version:'3.2.8.RELEASE'
compile group: 'org.apache.cxf', name: 'cxf-rt-frontend-jaxrs', version:'2.7.7'
compile group: 'org.apache.cxf', name: 'cxf-rt-bindings-xml', version:'2.7.7'
compile group: 'org.apache.cxf', name: 'cxf-rt-databinding-jaxb', version:'2.7.7'
compile group: 'org.apache.cxf', name: 'cxf-rt-core', version:'2.7.7'
compile group: 'org.apache.cxf', name: 'cxf-api', version:'2.7.7'
compile group: 'org.apache.cxf', name: 'cxf-rt-rs-extension-providers', version:'2.7.7'
compile group: 'org.codehaus.jettison', name: 'jettison', version:'1.3.4'
compile group: 'org.perf4j', name: 'perf4j', version:'0.9.14'
compile group: 'cglib', name: 'cglib', version:'2.2.2'
compile group: 'org.aspectj', name: 'aspectjweaver', version:'1.6.12'
compile group: 'commons-collections', name: 'commons-collections', version:'3.2.1'
compile group: 'esGateKeeper', name: 'GLCookieDecryption', version:'1.0.0'
compile group: 'joda-time', name: 'joda-time', version:'2.3'
compile group: 'org.apache.jackrabbit', name: 'jackrabbit-core', version:'2.4.0'
compile group: 'org.apache.commons', name: 'commons-lang3', version:'3.1'
testCompile group: 'org.springframework', name: 'spring-test', version:'3.2.8.RELEASE'
testCompile group: 'oracle.jdbc', name: 'oracle.jdbc.OracleDriver', version:'1.0.0'
testCompile group: 'com.atomikos', name: 'transactions-jta', version:'3.7.0'
testCompile group: 'org.apache.cxf', name: 'cxf-rt-transports-http-jetty', version:'2.7.7'
testCompile group: 'com.atomikos', name: 'transactions-jdbc', version:'3.7.0'
testCompile group: 'org.mockito', name: 'mockito-all', version:'1.9.5'
testCompile group: 'junit', name: 'junit', version:'4.10'
testCompile group: 'org.assertj', name: 'assertj-core', version:'1.6.1'
providedCompile group: 'javax.transaction', name: 'jta', version:'1.1'
providedCompile group: 'javax.servlet.jsp', name: 'jsp-api', version:'2.1'
providedCompile group: 'javax.servlet', name: 'servlet-api', version:'2.5'
}
task processXSDs() << {
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask',
classpath: configurations.jaxb.asPath)
ant.xjc(destdir: 'tmp', package: "com.att.sunlight.service.domain.serviceCallResults", extension: true) {
schema(dir: "src/main/resources/schema", includes: "serviceCallResults.xsd")
arg(line: "-Xxew")
arg(line: "-summary target/xew-summary.txt")
arg(line: "-instantiate lazy")
arg(line: "-Xfluent-api")
}
}
compileJava.dependsOn processXSDs
Обновить:
Я определил, что это не проблема с расширением Element Wrapper. Если я удаляю этот jar-файл из classpath и перестраиваю, он сообщает о той же ошибке для плагина "Fluent API".
Я также решил, что это не совсем проблема Gradle. Я получаю тот же симптом с Ant "build.xml" и даже с простым сценарием оболочки, напрямую вызывающим Java-класс "XJCFacade". Фактически, я могу немного упростить этот сценарий, даже не указав никаких файлов схемы, что дает понять, что эта ошибка происходит еще до попытки обработки любых схем.
Ниже мой текущий сценарий:
#! /bin/bash
java -classpath "lib/commons-beanutils-1.7.0.jar;lib/commons-lang-2.2.jar;lib/commons-logging-1.1.1.jar;lib/istack-commons-runtime-2.16.jar;lib/jaxb2-basics-runtime-0.6.5.jar;lib/jaxb2-basics-tools-0.6.5.jar;lib/jaxb-api-2.2.7.jar;lib/jaxb-core-2.2.7.jar;lib/jaxb-fluent-api-2.1.8.jar;lib/jaxb-xew-plugin-1.4.jar;lib/jaxb-xjc-2.2.7.jar" com.sun.tools.xjc.XJCFacade -extension
Вы можете создать тот же тест, загрузив все эти артефакты в кэш Gradle или Maven и скопировав их в простую структуру папок.
Также обратите внимание, что я запускаю этот тест в основном на Windows 7, но я заархивировал этот проект и переместил его на свою CentOS VM, и он выдает мне ту же ошибку.
4 ответа
Я пытался
java -cp jaxb-api-2.2.7.jar;jaxb-core-2.2.7.jar;jaxb-xjc-2.2.7.jar;commons-logging-1.1.1.jar;commons-lang-2.2.jar;jaxb2-basics-tools-0.6.5.jar;jaxb-xew-plugin-1.3.jar com.sun.tools.xjc.XJCFacade -verbose -extension -d src xsd
и на самом деле это не с Exception in thread "main" java.util.ServiceConfigurationError: com.sun.tools.xjc.Plugin: Provider com.sun.tools.xjc.addon.xew.XmlElementWrapperPlugin not a subtype
Таким образом, проблема явно воспроизводима. Я отладил java.util.ServiceLoader
и оказалось, что плагины должны передаваться в качестве аргумента в XJC (не в путь к классам Java). На самом деле, все плагины Maven (как jaxb2-maven-plugin
или же maven-jaxb2-plugin
…) Знать об этой функции и правильно формировать XJC-фрагменты. Итак, правильная командная строка:
java -cp jaxb-api-2.2.7.jar;jaxb-core-2.2.7.jar;jaxb-xjc-2.2.7.jar;commons-lang-2.2.jar;commons-logging-1.1.1.jar com.sun.tools.xjc.XJCFacade -classpath jaxb-xew-plugin-1.3.jar;jaxb2-basics-tools-0.6.5.jar -verbose -extension -Xxew -d src xsd
Обратите внимание, что -classpath
это аргумент для XJC. commons-xxx
libs может перейти в системный classpath, поскольку экспортируемые ими пакеты не проверяются, но jaxb2-basics-tools
должен быть в XJC classpath. Если вы заинтересованы в деталях:
Это происходит потому, что XJC выполняет проверку загрузчика пути к классам, чтобы иметь возможность загружать более высокие версии JAXB API в JRE с более низкой встроенной версией API. См. XJCFacade.java строка 69. Это означает, что com.sun.tools.xjc.Plugin
загружается один раз по заказу XJCFacade
classloader, в то время как тот же самый класс загружается другим (фактически, родительским) загрузчиком классов снова, когда Class.forName("com.sun.tools.xjc.addon.xew.XmlElementWrapperPlugin")
называется, но теперь классы не равны.
На самом деле вы можете обойти это так (решение найдено после проверки исходного кода):
java -Dcom.sun.tools.xjc.XJCFacade.nohack=true -cp jaxb-core-2.2.7.jar;jaxb-xjc-2.2.7.jar;commons-lang-2.2.jar;commons-logging-1.1.1.jar;jaxb2-basics-tools-0.6.5.jar;jaxb-xew-plugin-1.3.jar com.sun.tools.xjc.XJCFacade -verbose -extension -Xxew -d src xsd
Обратите внимание, что я удалил jaxb-api-2.2.7.jar
из Java classpath, но вам лучше поместить JAXB API в lib/endorsed
поскольку он может не работать на разных версиях Java: отлично работает для Java 7, потому что его JAXB API близок к 2.2.7, но может не работать на Java 6 + JAXB API 2.2.11.
Престижность к dma_k, но рабочее решение gradle никогда не предоставлялось. После некоторых экспериментов вот что сработало для меня:
def xjcGeneratedSourcesDir = "$buildDir/generated-sources/xjc"
configurations {
jaxb
xjc
}
sourceSets {
main {
java.srcDir xjcGeneratedSourcesDir
}
}
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-core:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
xjc "com.github.jaxb-xew-plugin:jaxb-xew-plugin:1.4"
xjc "net.java.dev.jaxb2-commons:jaxb-fluent-api:2.1.8"
// etc.
}
task wsdl2java << {
file( xjcGeneratedSourcesDir ).mkdirs()
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask',
classpath: configurations.jaxb.asPath)
ant.xjc(destdir: xjcGeneratedSourcesDir,
package: "com.localhost.jaxb", extension: true) {
schema(dir: "src/main/resources/schema", includes: "*.xsd")
classpath(path: configurations.xjc.asPath)
arg(line: "-Xxew")
arg(line: "-Xxew:summary $buildDir/xew-summary.txt")
arg(line: "-Xxew:instantiate lazy")
arg(line: "-Xfluent-api")
}
}
compileJava.dependsOn wsdl2java
Я не буду использовать задачу ant или maven для gradle, а просто вызову Java-класс напрямую, как я сделал это дляorg.apache.cxf.tools.wsdlto.WSDLToJava
,
Ни один инженер по сборке / выпуску или разработчик jaxb-xjc не должны быть вынуждены использовать внутренний проприетарный JAXB-JXC ClassLoader. Первоначальный дизайн был таким, что пользователи JDK 1.x не загружали JAXB-2.2.0.jar . С 2010 года в JAXB не было никаких существенных изменений версии, и разработчики jaxb-xjc прекратили поддерживать этот плагин для JDK 5,6,7,8. Я отправил электронное письмо гуру Oracle в CXF-Metro 31 января. Если мы не получим от них ответа, разрешите Oracle обратиться с просьбой выпустить код в OpenSource, чтобы, по крайней мере, он был сохранен. Каждый разработчик этого плагина был сбит с толку этим эфемерным решением. Не нужно дополнительно наказывать будущих разработчиков неиспользуемым кодом, который страдает от кратковременного взлома. Кроме того, опция -DClassLoaderBuilder.noHack ПОЛНОСТЬЮ обходит собственного менеджера по безопасности Oracles.. Это ВЕРБЕНО в банках и финансовых учреждениях... Я отправлю ответ, когда получу ответ от CXF Metro