com.sun.tools.xjc.Plugin: Provider <plugin> not a subtype

强颜欢笑 提交于 2019-11-28 12:15:30

I have tried

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

and indeed that fails with Exception in thread "main" java.util.ServiceConfigurationError: com.sun.tools.xjc.Plugin: Provider com.sun.tools.xjc.addon.xew.XmlElementWrapperPlugin not a subtype, so the problem is clearly reproducible. I have debugged java.util.ServiceLoader and it turned out that plugins should be passed as argument to XJC (not to classpath of Java). Actually, all maven plugins (like jaxb2-maven-plugin or maven-jaxb2-plugin …) know about this feature and form XJC argments correctly. So the correct command line is:

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

Note that -classpath is argument for XJC. commons-xxx libs can go to system classpath as the packages they export are not screened, but jaxb2-basics-tools should be in XJC classpath. If you are interested in details:

This happens because XJC does classpath loader screening to be able to load higher versions of JAXB API in JRE that has lower build-in version of API. See XJCFacade.java line 69. That means that com.sun.tools.xjc.Plugin is loaded once by custom XJCFacade classloader while the same class is loaded by another (actually, parent) classloader again when Class.forName("com.sun.tools.xjc.addon.xew.XmlElementWrapperPlugin") is called, but now classes are not equal.

Actually you can workaround like this (solution found after source code inspection):

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

Note that I have removed jaxb-api-2.2.7.jar from Java classpath but you'd better put JAXB API into lib/endorsed as it may not work on different Java versions: works fine for Java 7, because it's JAXB API is close to 2.2.7, but may not work on Java 6 + JAXB API 2.2.11.

Kudos to dma_k, but a working gradle solution was never provided. After some experimentation, this is what worked for me:

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
Stefan K.

I wouldn't use the ant or maven task for gradle, but rather invoke the Java class directly, like I did this for org.apache.cxf.tools.wsdlto.WSDLToJava.

No build/release engineer or jaxb-xjc implementor should be forced to use the internal proprietary JAXB-JXC ClassLoader. The original design was so JDK 1.x users would not load the JAXB-2.2.0.jar ..since 2010 there have been no significant version changes to JAXB and the jaxb-xjc developers stopped maintaining this plugin for JDK 5,6,7,8. I sent an email to the Oracle gurus at CXF-Metro on 31 Jan. If we dont hear back from them lets petition Oracle to release the code to OpenSource so at least it will be maintained. Every implementor of this plugin has been tripped up by this ephemeral solution. No need to further punish future implementors with unmaintained code that suffers from a short-term hack. Also the -DClassLoaderBuilder.noHack option COMPLETELY bypasses Oracles own Security Manager..this is VERBOTEN in Banks and Financial Institutions... I'll post back when I hear back from CXF Metro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!