Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAXB: Generating classes for two XSDs which share a common XSD

Tags:

java

jaxb

xsd

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>
            <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?

like image 767
Aravindan R Avatar asked Jun 08 '11 22:06

Aravindan R


1 Answers

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.

like image 191
lexicore Avatar answered Nov 06 '22 04:11

lexicore