从 XJC 输出中省略 @XmlSeeAlso

发布于 2024-11-30 07:10:47 字数 777 浏览 1 评论 0 原文

目前我正忙于一个使用 XML 消息传递的项目。我有一个通用模式,其中包含抽象类型和一些可重用的类型定义和元素。对于我正在处理的每种消息,都有一个单独的模式(具有不同的目标命名空间)来导入通用模式。换句话说,它是一个两级层次结构。很简单。

这些模式中的每一个都用于生成 Java 类。每个模式对应一个包。代码生成由 Maven JAXB 2.1 插件处理。当我使用代码时,我为每种消息类型创建一个单独的 JAXBContextJAXBContext 是使用通用模式的包名称和特定消息类型的包名称创建的,因此上下文应该只看到它必须处理的那些类。

令我惊讶的是,我注意到当我将 XML 文档解组到 beans,然后将它们编组回 XML 时,每个消息类型(= 模式目标名称空间)都有名称空间声明。想知道 JAXB 如何在上下文范围内获取该信息,我发现一些 @XmlSeeAlso 注释被放置在一些抽象类定义上。这会导致 JAXB 寻找有关目标包之外的类的信息。

有什么方法可以避免生成 @XmlSeeAlso 注释吗?环顾四周,我发现这是 JAXB 2.1 的新功能。我可以切换到 2.0 的 XJC 插件,但我不确定这是否会产生不需要的副作用。另外,我希望将来继续关注新的 JAXB 版本。不需要的命名空间声明不是问题(XML 仍然有效),但一旦添加更多消息类型就会造成混乱。另外,这清楚地表明我的 JAXB 上下文加载的类比我想象的要多,并且基本上是彼此重复的。我可以使用一个包含所有内容的上下文,但我已经围绕这种分离构建了自己的 API。

感谢您的阅读和提供的任何答案。

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 general 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晨曦慕雪 2024-12-07 07:10:47

使用父模式和子模式的单独编译。

如果单独编译父架构(不在上下文中包含子架构),则 @XmlSeeAlso 注释和 {@link ChildType} 将仅引用该架构中的 JAXB 类和它的父母。这实现了父/子模式的清晰分离。

使用maven-jaxb2-plugin,这可以通过限制包含的模式来实现。假设您在文件夹 src/xsd 中有架构 A.xsdB.xsd,其中 B.xsd 导入A.xsd 具有不同的命名空间。要仅生成父级 (​​A.xsd),请使用以下配置:

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

这将为 A.xsd 生成 JAXB 类,而不引用子架构中的元素 B.xsd

因为true,它还会生成一个META-INF/sun-jaxb.episode文件,您可以在< a href="http://weblogs.java.net/blog/kohsuke/archive/2006/09/separate_compil.html" rel="nofollow">生成子模式。

或者,当您生成子模式时(同样,对每个模式使用单独的编译),如果您不想采用这种方式,则可以删除父包。您可以使用 maven-clean-plugin 或 maven-antrun-plugin 删除子代的额外父包。我在episodes方面遇到了一些麻烦 - 为孩子们生成了一个额外的 ObjectFactory 类 - 所以我使用这种方式来实现我想要的结构。

另一件需要注意的事情是 JAXBElement 引用。如果您进行单独的编译,XJC 将不知道可能的替换组(如果我没有记错的话......),并且可能只生成 ParentType 引用。因此,如果您需要 JAXBElement 引用,请将 属性添加到该引用的架构或绑定中。

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.

宁愿没拥抱 2024-12-07 07:10:47

我有同样的问题,我认为没有一个简单的答案。我找到了 com.sun.tools.xjc.generator.bean.BeanGenerator 类的源代码,该类似乎负责生成 java 源代码(jaxb-xjc-2.1.4.jar)。从第 496 行开始的代码如下所示:

     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);
            }
        }
    }

XMLSeeAlso 注释似乎是硬编码的,并且不是可选的或可配置的(至少对于 JAXB 2.1.4 而言)。

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文