I have 2 service XSD files AService.xsd and BService.xsd each with different targetNamespace. Both of these use a common XSD called common.xsd. I use the JAXB Maven plugin to generate classes. Here's how,
<execution>
<id>generate-package</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<extension>true</extension>
<schemaIncludes>
<include>schema/Aservice.xsd</include>
开发者_如何学Go <include>schema/Bservice.xsd</include>
</schemaIncludes>
<bindingIncludes>
<include>schema/*.xjb</include>
</bindingIncludes>
<generatePackage>com.schema</generatePackage>
<generateDirectory>src/main/java</generateDirectory>
</configuration>
</execution>
When i try to run this i get the following error. ValidationType
is defined in common.xsd
org.xml.sax.SAXParseException: A class/interface with the same name "com.schema.ValidationType" is already in use. Use a class customization to resolve this conflict.
..........
org.xml.sax.SAXParseException: (Relevant to above error) another "ValidationType" is generated from here.
......
com.sun.istack.SAXParseException2: Two declarations cause a collision in the ObjectFactory class.
If i run the 2 service xsds in 2 different executions generating into 2 different packages, i get the same ValidationType
class in 2 different packages.
Any ideas on how to make JAXB recognize shared schemas?
You are facing a so-called "chameleon schema" which is considered to be a bad practice. Unfortunately, there is no good solution due to the nature of JAXB. JAXB annotation bind bean properties to XML elements and attributes in specific namespaces (determined in the schema compile time). So once your schema is compiled, there is no official good way to change namespaces of elements and attributes your properties are bound to.
However, this is exactly what you want to achieve with "chameleon" schemas. Classes derived from "common.xsd" should somehow magically map to namespace A if used in A classes and to namespace B if used in B classes. I can imagine this magic, but never seen in in real life.
Since you essentially want A/common and B/common to be the "same thing", one of the ways to resolve it is to generate A and B (both with common) in two executions and to make common classes implement a certain "common" interface. Then your software could process A/common and B/common in the same faschion regardless of the fact that these are actually classes from the different packages.
UPDATE:
From the comment I see that you don't have a chameleon schema, but just a normal importing. It is easy then, just compile common, A and B separately. See the Separate schema compilation for maven-jaxb2-plugin.
I customized the packages as described here. So common.xsd
goes in com.common.schema
and is shared by AService.xsd
and BService.xsd
which are both in different packages themselves, since they are in different namespaces.
The generatePackage
is removed from the maven configuration and looks like this,
<execution>
<id>generate-package</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<extension>true</extension>
<schemaIncludes>
<include>schema/Aservice.xsd</include>
<include>schema/Bservice.xsd</include>
</schemaIncludes>
<bindingIncludes>
<include>schema/*.xjb</include>
</bindingIncludes>
<generateDirectory>src/main/java</generateDirectory>
</configuration>
</execution>
精彩评论