JAXB,我自己的领域模型和建议

标签 jaxb jax-ws cxf

我有一个自 2005 年以来增量构建的相当大的 POJO 域模型。我们还在同一时间范围内增量开发了 XSD。目前,我按以下方式使用 xmlbeans 生成要通过 HTTP 发送并作为 WebService 响应的一部分的 xml。

  1. 使用 xmlbeans 从 XSD 生成绑定(bind)代码
  2. 编写了大量映射器,用于填充我的域 POJO 中的绑定(bind)代码(反之亦然)
  3. 将其编码为 XML
  4. 对于网络服务,我们使用 Axis 1.4 which can use the Serialization/Desrialization factories generated by xmlbeans 。这允许我们在两个端点上重用相同的代码:基于 HTTP 的 XML 和 SOAP/HTTP

现在,我们希望开始使用 JAXB,因为它是成熟的、标准的、支持 Multi-Tenancy (至少是 Moxy 实现),并且不再作为 xmlbeans 的一部分进行太多工作。所以我的问题是

  1. 如何在不生成绑定(bind)代码的情况下使用 JAXB。即我不想再编写或维护映射代码(步骤 2)。我想知道是否可以使用 JAXB 直接解码到我的域 POJO?
  2. 如何将其与我的 WebService 集成?我的网络服务使用相同的架构,并且不想复制映射。
  3. 还有其他最佳实践建议吗?
  4. 有什么我应该注意的陷阱/经验教训吗?

最佳答案

注意:我是EclipseLink JAXB (MOXy) JAXB (JSR-222) 的领导者和成员专家组。

1 - How to use JAXB without generating the binding code. i.e. I doesn't want to write or maintain the mapping code (Step 2) anymore. I am wondering if I can somehow use the JAXB to unmarshal to my domain POJO directly?

使用自己的域对象的关键是基于路径的映射。如果没有这个,您的绑定(bind)框架使用的模型必须与 XML 文档非常相似。下面是我想提供的一个示例,其中一个简单的地址对象映射到 Google Geocoding API V2 的结果.

package blog.geocode;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="kml")
@XmlType(propOrder={"country", "state", "city", "street", "postalCode"})
public class Address {

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:Thoroughfare/ns:ThoroughfareName/text()")
    private String street;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:LocalityName/text()")
    private String city;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:AdministrativeAreaName/text()")
    private String state;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:CountryNameCode/text()")
    private String country;

    @XmlPath("Response/Placemark/ns:AddressDetails/ns:Country/ns:AdministrativeArea/ns:SubAdministrativeArea/ns:Locality/ns:PostalCode/ns:PostalCodeNumber/text()")
    private String postalCode;

}

下面是一个示例链接,其中相同的对象模型映射到 Google 和 Yahoo 天气服务:


2 - How to integrate this with my WebService? My webservice uses the same schema and doesnt want to replicate the mappings.

如果 Axis 支持多个 JAXB 提供程序,那么您应该能够利用 MOXy,而无需进行太多配置。可能只需在与域模型相同的包中添加 jaxb.properties 文件即可。


3 - Any other best practice suggestions?

如果您想避免将任何编译时依赖项添加到域模型中,那么您可能需要考虑将元数据表示为 XML。


更新

以下是对您通过评论提出的问题的解答:

One restriction I know with the webservice API's is that they work against the "factories generated by the xjc." In which case I believe I can no longer use the XPath mapping. Please correct me if I am wrong. Also, If I use annotations, should I still need to use xjc?

我不确定 CXF,但标准 JAX-WS 实现允许您从自己的域模型开始,或通过 XJC 生成域模型。下面是当您从 Java 对象开始时在 JAX-WS 环境中使用 MOXy 的几个示例:


I assume this is another option other than using XPath and is also the only option if I need to support multi-tenancy.

外部映射文档并不是 XPath 的替代品,它只是指定元数据的另一种方式。如果某些人不想在类上引入任何 MOXy 依赖项(这些类将用于对象到 XML 或对象到 JSON 的转换),那么他们更喜欢这种方法。对于 Multi-Tenancy ,我经常注释所有共享属性,然后为每个租户提供一个映射文档来映射扩展。


Also, are there any performance implications if I go the XPath route or if i chose metadata in XML?

使用基于路径的映射不会产生任何性能影响。当 JAXBContext 初始化时,这一切都会得到优化。当引导外部绑定(bind)文档时,JAXBContext 创建速度会稍慢,因为需要完成更多工作,但由于 JAXB/MOXy 是异常(exception)配置,因此这些文档往往很小。使用外部映射文档对 Marshaller/Unmarshaller 没有影响。

关于JAXB,我自己的领域模型和建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11745465/

相关文章:

maven - com.sun.tools.xjc.Plugin : Provider <plugin> not a subtype

java - JAXB/Jersey - JSONObject 作为 XmlElement

java - JAXB 编码和多态性

java - 如何调用带参数的webservice方法?

spring - 使用 spring 加载带有 jersey/jax-ws 的 jetty 时,ServletContext 为 null

spring - 使用 JAXB + Spring RESTful Web 服务防止 XXE(外部实体处理)攻击

java - maven:如何添加编译阶段后生成的资源

java - Spring-ws VS Apache cxf VS Apache Axis2 VS Metro

java - 如何使用 CXF 获取发件人公钥?

CXF wsdl2java 不为成员生成 Javadoc