开发者

Omitting @XmlSeeAlso from XJC output

开发者 https://www.devze.com 2023-03-29 05:00 出处:网络
Currently I\'m busy on a project using XML messaging. I have one general schema, with abstract types and some reusable type definitions and elements. For each sort of message I\'m dealing with, there\

Currently I'm busy on a project using XML messaging. I have one general schema, with abstract types and some reusable type definitions and elements. For each sort of message I'm dealing with, there's a separate schema (with a different target namespace) that imports the genera开发者_StackOverflow社区l one. In other words, it's a two-level hierarchy. Pretty simple.

Each of these schemas is used for generating Java classes. Each schema corresponds to one package. The code generation is handled by the Maven JAXB 2.1 plugin. When I'm using the code, I create a separate JAXBContext for each message type. The JAXBContext is created using the package name of the general schema and that of the specific message type, so the context should only see those classes it has to deal with.

To my surprise I noticed that when I unmarshal an XML document to beans and then marshal those back to XML, there were namespace declarations for each and every message type (= schema target namespace). Wondering how JAXB got that info despite the context scope, I found out some @XmlSeeAlso annotations were placed on some abstract class definitions. This causes JAXB to seek information regarding classes outside of the target packages.

Is there any way to avoid generating the @XmlSeeAlso annotations? Looking around here, I found out this was new for JAXB 2.1. I could switch to an XJC plugin for 2.0, but I'm not certain if this would have unwanted side effects. Plus, I'd like to keep following new JAXB releases in the future. The unrequired namespace declarations are not a problem (the XML is still valid) but will be confusing once more message types are added. Also, this has made it clear my JAXB contexts loaded more classes than I thought and are basically duplicates of each other. I could go with one context encompassing all, but I've got an API of my own built around this separation.

Thanks for reading and any answers supplied.


Use separate compilation of parent schema and child schemas.

If you compile the parent schema separately (without including child schemas in the context), the @XmlSeeAlso annotation and the {@link ChildType} will only reference JAXB classes in that schema and its parents. This achieves a clear separation of parent/child schemas.

Using maven-jaxb2-plugin, this can be achieved by limiting included schemas. Say you have schemas A.xsd and B.xsd in folder src/xsd, where B.xsd imports A.xsd with different namespace. To generate just the parent (A.xsd), use the following configuration:

<plugin>
  <groupId>org.jvnet.jaxb2.maven2</groupId>
  <artifactId>maven-jaxb2-plugin</artifactId>
  <version>0.8.2</version>
  <executions>
    <execution>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <schemaDirectory>${project.basedir}/src/xsd</schemaDirectory>
        <schemaIncludes>
          <include>A.xsd</include>
        </schemaIncludes>
        <episode>true</episode>
      </configuration>
    </execution>
  </executions>
</plugin>

This will generate JAXB classes for A.xsd without any references to elements from child schema B.xsd.

Because of <episode>true</episode>, it will also generate a META-INF/sun-jaxb.episode file, which you can refer to when you generate the child schemas.

Alternatively, when you generate the child schemas (again, use separate compilation for each), you can just delete the parent packages if you do not want to go the episode way. You can use maven-clean-plugin or maven-antrun-plugin to delete extra parent packages for child generation. I had some trouble with episodes - an additional ObjectFactory class was generated for children - so I used this way to achieve the structure I wanted.

Another thing to watch out for is the JAXBElement<? extends ParentType> references in your generated classes. If you do a separate compilation, XJC will not know about possible substitution groups (if I am not mistaken..), and may generate just the ParentType reference. So if you need the JAXBElement reference, add the <jaxb:property generateElementProperty="true" /> property to your schema or bindings for that reference.


I have the same issue and I do not think there is an easy answer. I found the source of the com.sun.tools.xjc.generator.bean.BeanGenerator class which appears to be responsible for generating the java source code (jaxb-xjc-2.1.4.jar). The code, starting from line 496 looks like this:

     if(model.options.target.isLaterThan(SpecVersion.V2_1)) {
        // @XmlSeeAlso
        Iterator<CClassInfo> subclasses = cc.target.listSubclasses();
        if(subclasses.hasNext()) {
            XmlSeeAlsoWriter saw = cc.implClass.annotate2(XmlSeeAlsoWriter.class);
            while (subclasses.hasNext()) {
                CClassInfo s = subclasses.next();
                saw.value(getClazz(s).implRef);
            }
        }
    }

The XMLSeeAlso annotation appears to be hard-coded and NOT optional or configurable (at least with JAXB 2.1.4).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号