ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 使用IBM Rational Software Architect 在Java中处理XSD

使用IBM Rational Software Architect 在Java中处理XSD

原创 Linux操作系统 作者:myattitude 时间:2009-05-26 14:29:08 0 删除 编辑

引言

许多应用程序需要以一种或多种使用 XSD 指定的行业标准消息格式表示数据。XSD 通常是指定行业标准消息格式的理想方法,因为它跨平台和编程语言受到广泛支持(无论是本机支持还是通过库支持)。但是,即使拥有此支持,由于特定于应用程序的数据结构与 XSD 之间的特性不匹配,将存储在这些特定于应用程序的数据结构中的数据转换为符合 XSD 的消息(通常为 XML 消息)会带来挑战。


图 1. 在两种特定于应用程序的数据结构之间提供公共消息模型的行业标准 XSD(中心)
提供公共消息模型的行业标准 XSD

在实现基于 Java 的 Web 服务时,这些特性不匹配会导致很难使用基于 Java API for XML-based RPC (JAX-RPC)、Java API for XML Web Services (JAX-WS) 或同时基于这两者的工具包,自动化从特定于应用程序的数据结构到 XML 消息的映射。

由于 XSD 与编程语言无关,它具有许多在 Java 对象中不直接受到支持的特性。此类特性的示例包括 xsd:choicexsd:group 数据类型以及 xsd:restriction 属性。本文向您介绍如何创建消除这些数据类型的 Java 友好的 XSD。您将使用基于 XSL Transformation (XSLT) 的映射,从而将基于 Java 友好的(内部)XSD 的消息转换为全功能的(外部)XSD。对于本文中的特定示例,外部 XSD 为 Postsecondary Electronic Standards Council (PESC) 的 Common Record: CommonLine (CRC) 助学贷款消息标准。

本文中用于创建与 CRC 1.4 XSD 相对应的 Java 友好的 XSD 的技术可应用于任何太复杂而在基于 Java 的 Web 服务工具包中不直接受支持的 XSD。首先让我们看一下大致步骤:

  1. 使用 JAX-RPC 或 JAX-WS 为 XSD 接口生成服务实现(和测试客户端)。
  2. 如果需要,则创建外部 XSD 的 Java 友好的简化版本。
  3. 使用 Java 友好的 XSD 重新生成服务实现。
  4. 实现 JAX-RPC 或 JAX-WS 代码生成当前不支持的 XSD 约束。

系统要求

要按照本文所述进行操作,需要在系统上安装以下软件:

  • 带 IBM WebSphere® Application Server Feature Pack for Web Services 的 IBM® Rational® Software Architect V7.0.0.6
  • IBM WebSphere Integration Developer V6.1

Feature Pack for Web Services 是 Rational Software Architect V7 的一个可选包,您可以使用 IBM Installation Manager 对其进行下载和安装。安装该功能包之后,确保通过在 Rational Software Architect 中单击 Window > Preferences > General > Capabilities 启用 Web Services Developer 功能。


导入外部 XSD

您的第一个步骤是导入外部 XSD 并基于该 XSD 创建 Web 服务描述语言(Web Services Description Language,WSDL)接口:

  1. 在 Rational Software Architect V7 中创建一个 Java 项目(例如,CRCLib)。
  2. PESC 网站导入该 XSD。

    图 2. 构成 CRC 标准的 XSD
    构成 CRC 标准的 XSD

  3. 通过右键单击 CRCLib 项目并选择 New > Other > WSDL 创建新的 WSDL 接口。
  4. 在 com.ibm.jxsd.services 目录中创建名为 LoanProcessing.wsdl 的接口。
  5. 将操作名称更改为 process,将输入更改为 CommonRecordCommonlineReceipt,将输出更改为 CommonRecordCommonlineResponse

    图 3. 在 Rational Software Architect 中创建 WSDL 接口
    在 Rational Software Architect 中创建 WSDL 接口 

    创建 JAX-RPC 实现

    下一步,您将创建服务实现。实现技术的选择将决定您对内部 XSD 所做的更改。给定基于 WebSphere Application Server 的部署环境,总共存在两种技术选择:JAX-RPC 和 JAX-WS。JAX-WS 是一种较新的规范,比 JAX-RPC 支持更多的 XSD 构造,因此不需要单独的(内部)XSD。JAX-RPC 是一种较旧的规范,并且需要内部 XSD;但是由于它较旧,因此受到比 JAX-WS 更广泛的支持和采用。

    CRC 标准
    本文的示例中使用的 XSD 来自于 Common Record:CommonLine 标准。Common Record:CommonLine (CRC) 标准同时描述了助学贷款流程中的参与者用于进行消息交换的消息和流程:学生、学校、借款人和担保人。完整的 CRC 1.4 XSD 包括在七个文件中,可以在 Web上的地址 http://www.pesc.org/interior.php?page_id=162 处找到。

    本文介绍 JAX-RPC 和 JAX-WS 实现所需要的更改,首先从 JAX-RPC 开始:

    1. 右键单击 LoanProcessing.wsdl 文件并选择 Web Service > Generate Java bean Skeleton
    2. 使用 Generate Java bean Skeleton 向导,选择一个新的项目名称并确保 Web 服务运行时为 JAX-RPC
    3. 单击 Finish 生成代码。您应该看到一个窗口打开并显示警告。让我们检查一下其中一些警告,并了解为什么会发生这些警告。

    xsd:group

    无法在 Java 中通过 JAX-RPC 映射的 XSD 特性之一是 xsd:group 数据类型。它在 XSD 中的存在导致类似于清单 1 所示的 JAX-RPC 警告。


    清单 1. 由于 xsd:group 而产生的 JAX-RPC 警告
    WSWS3029W: Warning: The xml construct named 
    {urn:org:pesc:core:CoreMain:v1.4.0}OrganizationType cannot be 
    mapped to a java type.  The construct will be mapped to 
    javax.xml.soap.SOAPElement.
    

    由于 xsd:group 数据类型无法在 JAX-RPC 中进行明确的映射,因此一般将其映射到 Java 中的 SOAPElementSOAPElement 需要以编程方式映射到 xsd:group 才能正常工作(请参见清单 2 和 3)。


    清单 2. 包含 xsd:group 元素的 XSD
    
    ...
    
    
    
     
      
       ...
     
    
    


    清单 3. 为 xsd:group 元素生成的 JAX-RPC 代码
    ...
     private javax.xml.soap.SOAPElement[] organizationType; 
    ...
    

    替代方法

    以编程方式将生成的 SOAPElement 映射到 xsd:group 数据类型是一种脆弱的解决方案,并违反了尽可能避免直接修改所生成的代码的实践。您不能更改来自于标准的 XSD,因此可以创建一个内部 XSD,在其中将 xsd:group 替换为 xsd:complexType,如清单 4 所示。


    清单 4. 在其中将 xsd:group 元素替换为 xsd:complexType 的 XSD
    
    ...
    
    
    
     
      
       ...
     
    
    

    虽然 xsd:groupxsd:complexType 都是容器数据类型,但它们并不完全相同。组封装 allchoicesequence 元素,而 complexType 封装属性、嵌套元素和混合内容。因此您可能担心在转换到 xsd:complexType 时会失去 xsd:group 数据类型的某些表达功能。但是结果证明,xsd:choice 也不受 JAX-RPC 映射的支持,因此您无论如何都要在内部 XSD 中对此进行更改。xsd:sequencesxsd:complexType 中受支持(如清单 4 所示)。

    xsd:choice

    xsd:choice 是另一个不受 JAX-RPC 支持的 XSD 特性。针对 xsd:choice 的警告与清单 5 所示类似。


    清单 5. 由于 xsd:choice 而产生的 JAX-RPC 警告
    WSWS3029W: Warning: The xml construct named 
    {urn:org:pesc:core:CoreMain:v1.4.0}TestsType cannot be mapped to a 
    java type.  The construct will be mapped to 
    javax.xml.soap.SOAPElement.
    

    xsd:choice 数据类型描述了这样一个结构,其中只有一个子元素可以是活动的或者可供选择。Java 中不存在对应的结构,因此 JAX-RPC 同样将 xsd:choice 数据类型映射到通用 SOAPElement(请参见清单 6 和 7)。


    清单 6. 包含 xsd:choice 元素的 XSD
    
     
      ...
       
        
        
        
       
      ...
     
    
    


    清单 7. 为 xsd:choice 元素生成的 JAX-RPC 代码
    ...
     private javax.xml.soap.SOAPElement[] testType; 
    ...
    

    替代方法

    要使您的 XSD 变得 Java 友好,您可以从出现 xsd:choice 的位置将其完全删除,以便 JAX-RPC 能够产生映射。没有 xsd:choice 时,JAX-RPC 生成的代码将创建正确的类(请参见清单 8)。


    清单 8. 在其中将 xsd:group 元素替换为 xsd:complexType 的 XSD
    
    ...
    
    
    
     
      
       ...
     
    
    

    这可能让人担心 XSD 将允许消息有多个元素,从而与外部 XSD 冲突。这种数据结构约束的弱化要求根据需要强化应用程序逻辑中的约束。但是,由于传入数据来自于外部来源,并满足外部 XSD,而传出数据在传输前将根据外部 XSD 进行验证,因此不存在应用程序接受或传输无效数据的危险。如果需要根据 XSD 约束对传入数据或传出数据进行权威验证,可以考虑部署专用的网络边缘设备,例如 IBM WebSphere DataPower SOA Appliances 所提供的设备。

    Russell Butek 的文章“Web 服务技巧: 将多态性作为 xsd:choice 的备选方法”描述了对 xsd:choice 的另一种替代选择。

    将内部 XSD 映射到外部 XSD

    在完成从外部 XSD 到内部 XSD 的所有更改之后,您可以在 WebSphere Integration Developer V6.1 中创建一个中介模块,此模块将在 IBM WebSphere Enterprise Service Bus 或在 IBM WebSphere Process Server 中运行。在该中介模块中,一个 XSLT 映射在内部和外部 XSD 之间转换 XML 消息(请参见图 4)。

    创建中介流和 XSLT 映射超出了本文的范围,但是WebSphere Integration Developer 帮助文档的构建中介流部分对此进行了详细的描述。 此外,为了便于参考,下载部分作为项目交换文件提供了为本文创建的中介模块。

    请参见图 4 的大图


    图 4. 在 WebSphere Integration Developer 中将内部 XSD 映射到外部 XSD
    在 WebSphere Integration Developer 中将内部 XSD 映射到外部 XSD 

    创建 JAX-WS 实现

    在实际实现中,您将选择一种实现技术:JAX-RPC 或 JAX-WS。但是出于完整性的考虑,下面介绍了在使用 JAX-WS 时需要对内部 XSD 做出的更改:

    1. 在 CRCLib 项目中,右键单击 LoanProcessing.wsdl 文件,然后选择 Web Services > Generate Java bean skeleton

      图 5. 在 WSDL 基础上生成 Web 服务
      在 WSDL 基础上生成 Web 服务

    2. 在窗口中,将 Web 服务运行时更改为 IBM WebSphere JAX-WS。如果 JAX-WS 选项未列出,这意味着未安装 WebSphere Application Server Feature Pack for Web Services。

      图 6. 用于生成 JAX-WS Web 服务的选项
      用于生成 JAX-WS Web 服务的选项

    3. 确保在窗口中选择新的项目名称(例如 LoanPWS),然后单击 Next 以确保将 WSDL 复制到项目。
    4. 回到 Service Deployment Configuration 窗口,单击 OK 生成所有代码。如果服务器未运行,它将会启动。

    生成的 Java

    代码成功生成而无任何错误或警告。成功地为整个 XSD 生成了对应的类,因此不需要任何单独的内部 XSD。JAX-WS 实现将 xsd:group 数据类型(此数据类型没有对应的 Java 表示形式)转换为 xsd:complexType。这是您在为 JAX-RPC 实现的内部 XSD 中手动执行的相同转换;但是在 JAX-WS 实现中,该转换是隐式和自动的。

    xsd:choice

    JAX-WS 实现将 xsd:choice 数据类型表示为 Java 类的属性,并且做出隐式和自动的转换,同样,此转换与您使用内部 XSD 为 JAX-RPC 实现执行的转换相同。

    确保仅设置其中一个选择。例如,在清单 9 中,eSignatureCustodianType 中可以具有 LenderGuarantor 元素。


    清单 9. 包含 xsd:choice 元素的 XSD

    
     
      
       
        
         
         
        
       
      
      
       
        
         
         
        
       
      
     
    
    

    为此类型生成的 Java 代码如清单 10 所示。


    清单 10. 为 xsd:choice 元素生成的 JAX-WS 代码

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "eSignatureCustodianType", 
    namespace = "urn:org:pesc:core:CoreMain:v1.4.0", 
    propOrder = {
     "lender",
     "guarantor"
    })
    public class ESignatureCustodianType {
    
     @XmlElement(name = "Lender")
     protected ESignatureCustodianType.Lender lender;
     @XmlElement(name = "Guarantor")
     protected ESignatureCustodianType.Guarantor guarantor;
    

    请注意,LenderGuarantor 都存在 get 和 set 方法。您必须确保仅填充其中一个。

    不兼容性

    XSD 数据类型可以描述在 Java 没有等效表达式时的约束。因此,JAX-RPC 和 JAX-WS 都不能创建保留所有约束的对应 Java 类。让我们看看 XSD 约束和 JAX-WS 中生成的对应 Java 代码的一些示例。

    长度约束

    在清单 11 中的 XSD 中,confirmationID 是一个最小长度为 1 和最大长度为 20 的字符串。


    清单 11. 带长度约束的 XSD

    
     
       Confirmation ID supplied 
      from the counseling session
     
     
      
      
     
    
    

    生成的 Java 代码如清单 12 所示。


    清单 12. 为带长度约束的 XSD 生成的 Java 代码

    public class LoanCounselingType {
    
     @XmlElement(name = "ConfirmationID")
     protected String confirmationID;
     @XmlElement(name = "CompletionDate")
     protected XMLGregorianCalendar completionDate;
     @XmlElement(name = "CompletionTime")
     protected XMLGregorianCalendar completionTime;
    

    confirmationID 生成的 Java 代码只是一个不带任何约束的 Java 字符串。如果将该字符串设置为无效长度的值,该代码没有问题,但是生成的 XML 将无法通过验证。为了避免这一点,您必须显式地向代码添加字符串长度检查。

    必备约束

    另一个在 Java 中不受支持的 XSD 约束是必备 约束。例如,下面的 XSD 描述了一组必须从中选择其一的枚举值(也就是说,值为 Null 或不做出选择将是无效的)。


    清单 13. 带必备约束的 XSD

    
     
      Code indicating the preferred or 
      actual method of delivering the promissory note to 
      the borrower
     
     
      
      
      
      
     
     
    

    生成的 JAX-WS 代码如清单 14 所示。


    清单 14. 为带必备约束的 XSD 生成的 Java 代码

    public enum PromissoryNoteDeliveryCodeType {
     @XmlEnumValue("Paper")
     PAPER("Paper"),
     @XmlEnumValue("Email")
     EMAIL("Email"),
     @XmlEnumValue("Web")
     WEB("Web");
     private final String value;
    

    代码生成器正确地创建了 Java 枚举,但是不确保至少选择其中一个值。因此,强制执行此约束同样是您的责任。

    maxOccurs 约束

    您将在这里检查的最后一个不受支持的 XSD 约束是 maxOccurs。在该示例中(请参见清单 15)中,父元素 PellAwardResponseType 具有一个名为 FSACode 的子元素,此子元素应该出现零至三次。


    清单 15. 带 maxOccurs 约束的 XSD

    
     
      
       
       
       
      
     
    
    

    生成的 Java 代码(请参见清单 16)将 FSACode 表示为字符串列表。它没有将该列表的长度限制为少于四个项目。


    清单 16. 为带 maxOccurs 约束的 XSD 生成的 Java 代码

    public class PellAwardResponseType
     extends ResponseType
    {
     ….
     @XmlElement(name = "FSACode")
     protected List fsaCode;
    
    作者:Majeed Arni, 高级软件工程师, IBM
    Anthony Young-Garner, 解决方案开发人员, IBM

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14780914/viewspace-604215/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-07-07

  • 博文量
    172
  • 访问量
    330703