jaxb2-maven-plugin
jaxb2-maven-plugin copied to clipboard
Schemagen will fail if package-info.java contains xmlns-attributes with the same prefix as in transformSchema
Re-posting the same problem as mentioned in https://github.com/mojohaus/jaxb2-maven-plugin/issues/52, with a new description and motivation:
We specify explicit xmlns namespace prefixes in our package-info.java files, in order to get well-defined namespace-prefixes in the generated XML.
Example package-info.java:
@XmlSchema(namespace = "http://schemas.acme.com/student", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(namespaceURI = "http://schemas.acme.com", prefix = "base"),
@XmlNs(namespaceURI = "http://schemas.acme.com/dap", prefix = "dap"),
@XmlNs(namespaceURI = "http://schemas.acme.com/student", prefix = "st") })
package com.acme.student.interfaces;
We want the same well-defined namespaces in the XSD:s that are generated with the schemagen mojo, so we configure the mojo with:
<transformSchemas>
<transformSchema>
<uri>http://schemas.acme.com</uri>
<toPrefix>base</toPrefix>
<toFile>schemas.acme.com.xsd</toFile>
</transformSchema>
<transformSchema>
<uri>http://schemas.acme.com/dap</uri>
<toPrefix>dap</toPrefix>
<toFile>schemas.acme.com-dap.xsd</toFile>
</transformSchema>
<transformSchema>
<uri>http://schemas.acme.com/student</uri>
<toPrefix>st</toPrefix>
<toFile>schemas.acme.com-student.xsd</toFile>
</transformSchema>
<transformSchemas>
However, the mojo fails when the namespaces are specified in the package-info.java files, with the following error:
Caused by: java.lang.IllegalStateException: Replaced prefix [st] with [tns] for URI [http://schemas.acme.com/student]
at org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver$NamespaceAttributeNodeProcessor.process (SimpleNamespaceResolver.java:215)
at org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper.process (XsdGeneratorHelper.java:408)
at org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver.initialize (SimpleNamespaceResolver.java:154)
at org.codehaus.mojo.jaxb2.schemageneration.postprocessing.schemaenhancement.SimpleNamespaceResolver.<init> (SimpleNamespaceResolver.java:74)
at org.codehaus.mojo.jaxb2.schemageneration.XsdGeneratorHelper.getFileNameToResolverMap (XsdGeneratorHelper.java:130)
at org.codehaus.mojo.jaxb2.schemageneration.AbstractXsdGeneratorMojo.performExecution (AbstractXsdGeneratorMojo.java:462)
...
The problem seems to be related to the "tns" namespace prefix that is used by the mojo prior to the transform schema post-processing phase. As mentioned above we want to replace this with something unique and well-defined.
If we remove the xmlns-part in the package-info.java file we don't get predefined namespace prefixes in the generated XML, and if we remote the <toPrefix>-part of the <transformSchema>-tags we don't get the predefined prefixes in the schemagen generated XSD. Hence none of that is acceptable.
However, by a couple of small modifications to the mojo we can fix the problem:
SimpleNamespaceResolver.java#214
//If old prefix has changed, throw exception. The "tns" prefix may be overridden by a specific namespace in @XmlSchema(xmlns=...), and is therefore ignored here
if (oldPrefixValue != null && !oldPrefixValue.equals(cacheKey) && !cacheKey.equals("tns")) {
throw new IllegalStateException(
"Replaced prefix [" + oldPrefixValue + "] with [" + cacheKey + "] for URI [" + aNode.getNodeValue()
+ "]");
}
XsdGeneratorHelper.java#490
if (!newPrefix.equals(oldPrefix) && currentResolver.getNamespaceURI2PrefixMap().containsValue(newPrefix)) {
throw new MojoExecutionException(MISCONFIG + "Namespace prefix [" + newPrefix + "] is already in use."
+ " Cannot replace namespace prefix [" + oldPrefix + "] with [" + newPrefix + "] in file ["
+ currentResolver.getSourceFilename() + "].");
}
This fix does the trick for us, hopefully it can make it into an upcoming official version as well.
Tested with jaxb2-maven-plugin, version 2.5.0.
Not sure I agree with this conclusion, "user error." The plugin does not correctly handle integration with the package-info.java to set a unique prefix and namespace. You can set the namespace via package-info but not the prefix. The result is you are forced to use the dreaded NamespacePrefixMapper in your jaxb marshaller. Hopefully, umefjord's commit would fix this; if it did, it would be a nice addition to this plugin.