javaschemagen

schemagen: How to share classes, but not their namespaces?


I have two top-level classes which share a third class by composition. Example:

@XmlRootElement
@XmlType(namespace = "http://example.com/foo")
public class Foo {
    public Shared shared;
}

@XmlRootElement
@XmlType(namespace = "http://example.com/bar")
public class Bar {
    public Shared shared;
}

public class Shared {
    public String string;
}

Each of these classes is assigned to a different package in a different compilation unit (module). Now when I use schemagen on each top level class, I would like the Shared class to have the same name space than the top level class. So the output for Foo should look like this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="foo" type="Foo"/>

  <xs:complexType name="Foo">
    <xs:sequence>
      <xs:element name="shared" type="Shared" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Shared">
    <xs:sequence>
      <xs:element name="string" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

However, it doesn't work like this. Instead the Shared class has the default namespace and so I get two schema files, one for the namespace of Foo and one for the namespace of Shared.

Is there a way to fix this without the obvious solution to duplicate the Shared class and thus, not sharing it anymore?


Solution

  • After investigating the issue and elaborating the options, I have decided to change the design and use one and only one namespace for all my classes. Here's the rationale:

    1. The relationship between a class and a namespace is naturally one to one. Even if I manually mock-up an XSD so that my instance document properly validates, the JAXB unmarshaller ignores elements which belong to a name space which doesn't match, so hacking the XSD doesn't help at all.

    2. I can easily reuse the same namespace over multiple packages and compilation units. The class path just needs to be set up correctly, which Maven will do for me when using the jaxb2-maven-plugin.

    3. I can easily associate all my classes with one namespace and still have different XSD files for each top-level element. The advantage is that each output XSD file contains only the classes (i.e. complex types) which are referenced from the included root element classes when running schemagen.

    After making this change, I get one XSD file per compilation unit. Each compilation unit contains exactly one root element (i.e. class). Each root element references only the complex types which are strongly reachable through the class representing the root element. This is exactly what I wanted.