mojohaus / jaxb2-maven-plugin

JAXB2 Maven Plugin
https://www.mojohaus.org/jaxb2-maven-plugin/
Apache License 2.0
106 stars 77 forks source link

Schemagen fails when run against package with namespace prefixes already defined #52

Closed karlmdavis closed 6 years ago

karlmdavis commented 8 years ago

I've got a package like the following:

@XmlSchema(namespace = XmlNamespace.BB_MANIFEST, xmlns = {
        @XmlNs(prefix = "bbm", namespaceURI = XmlNamespace.BB_MANIFEST) }, elementFormDefault = XmlNsForm.QUALIFIED)
package gov.hhs.cms.bluebutton.datapipeline.rif.extract.s3;

This breaks schemagen. Initially, I was seeing errors like the following:

[ERROR] Failed to execute goal org.codehaus.mojo:jaxb2-maven-plugin:2.2:schemagen (schemagen) on project bluebutton-data-pipeline-rif-extract: Execution schemagen of goal org.codehaus.mojo:jaxb2-maven-plugin:2.2:schemagen failed. NullPointerException -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:jaxb2-maven-plugin:2.2:schemagen (schemagen) on project bluebutton-data-pipeline-rif-extract: Execution schemagen of goal org.codehaus.mojo:jaxb2-maven-plugin:2.2:schemagen failed.
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:224)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
        at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:158)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:483)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.PluginExecutionException: Execution schemagen of goal org.codehaus.mojo:jaxb2-maven-plugin:2.2:schemagen failed.
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:143)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208)
        ... 19 more
Caused by: java.lang.NullPointerException
        at org.codehaus.mojo.jaxb2.schemageneration.AbstractXsdGeneratorMojo.performExecution(AbstractXsdGeneratorMojo.java:492)
        at org.codehaus.mojo.jaxb2.AbstractJaxbMojo.execute(AbstractJaxbMojo.java:257)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132)
        ... 20 more

... but I figured out that those errors were just due to bad error handling code in the plugin. (That error handling problem has been fixed, per #32, but the fix hasn't been released yet.)

I had to debug the plugin in Eclipse to find the real problem. I was having trouble getting a stack trace from Eclipse, but org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver:211 is the real error that was being hidden:

            if (oldPrefixValue != null) {
                throw new IllegalStateException(
                        "Replaced prefix [" + oldPrefixValue + "] with [" + cacheKey + "] for URI [" + aNode.getNodeValue()
                                + "]");

As a workaround, this error goes away if I remove the xmlns property (the prefix binding) from my package's @XmlSchema annotation. I guess the plugin was written before JAXB added official support for prefix mapping?

lennartj commented 8 years ago

The general idea is that the plugin considers it a user error if a namespace prefix is mapped to two different namespace URIs. Translated to a XSD schema specification, two different prefixes for the same URI would translate to something like:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:prefix="http://www.jguru.se/some/uri" xmlns:prefix="http://www.jguru.se/some/other/uri" ... >

While we should care to ensure that we only emit that Exception when a namespace prefix/URI (i.e. key/value) is being changed, I believe it should be considered a user error. Within a JAXB compilation unit, namespace prefix/URI mappings should be stable.

lennartj commented 6 years ago

Closing as a user error.