IBMChinaSkip to main content
搜索帮助
      IBM 主页   |   产品与服务   |   支持与下载   |   个性化服务

IBM : developerWorks 中国网站 : XML & Web services : 所有的文章
developerWorks 中国网站
Web Services for J2EE,版本 1.0英文原文

草案版本 0.91 — 2002 年 8 月 19 日

本版本:
http://www.ibm.com/developerworks/library/ws-jsr109-proposed/(以 PDF 格式提供的文档)
作者:
Jim Knutson,IBM <knutson@us.ibm.com>
Heather Kreger,IBM <kreger@us.ibm.com>

摘要

JSR109,即 Web Services for J2EE 定义了在 J2EE 1.3 或 J2EE 1.4 应用程序服务器中如何支持 Web 服务。具体地说,Web Services for J2EE 定义了客户机模型、部署模型和运行时模型,从而使 Web 服务客户机和实现可以从一个 J2EE 供应商实现移植到另一个 J2EE 供应商实现。Web Services for J2EE 基于 JAX-RPC(JSR101)进行构建,以提供客户机编程模型。该客户机模型允许 Web 服务客户机(Java 的或非 Java 的,在 J2EE 之中或在 J2EE 之外)访问部署在支持 JSR109 的 J2EE 应用程序服务器中的 Web 服务。它还允许 J2EE 组件通过使用 J2EE 编程模型调用 Web 服务(Java 的或非 Java 的,在 J2EE 之中或在 J2EE 之外)。WebServices for J2EE 部署模型定义了 WSDL 文档的处理方法和 WSDL 文档的服务和 XML 信息模型到 J2EE 组件的映射,包括 EJB 容器中的无状态会话 Bean 和 Servlet 容器中的 Servlet 和 JAX-RPC 端点。它还定义了对 JAX-RPC 处理程序的部署和运行时支持。Web Services for J2EE 还通过定义 J2EE 应用程序服务器应如何使 WSDL 文档可以通过 URL 获得定义了对服务发布的支持。为您的 Web 服务支持与 J2EE 应用程序服务器一起使用 JSR109 能确保您 Web 服务实现和客户机的可移植性。

本文档的状态

提议的最终草案

本文档是 JSR 109 的公开最终草案版本。它处于 JSR 规范在 Java 社区过程(Java Community Process)中的倒数第二个阶段。这表明 specification lead 和专家组认为该草案已经完成。对提议的最终草案的修订根据在创建参考实现(Reference Implementation)和技术兼容性工具(Technology Compatibility Kit,TCK)时出现的问题进行。本文档不是 JSR 109 规范的最终发行版。当本文档、参考实现和技术兼容性工具都完成时,本规范才会成为最终发行版。

目录

1. 前言
    1.1. 目标读者
    1.2. 致谢
    1.3. 规范结构
    1.4. 文档约定
2. 目标
    2.1. 客户机模型目标
    2.2. 服务开发目标
    2.3. 服务部署目标
    2.4. 服务发布目标
    2.5. Web 服务注册中心目标
3. 概述
    3.1. Web 服务体系结构概述
    3.2. Web 服务
    3.3. Web Services for J2EE 概述
        3.3.1. Web 服务组件
        3.3.2. Web 服务容器
    3.4. 平台角色
    3.5. 可移植性
    3.6. 标准服务
        3.6.1. JAX-RPC
    3.7. 互操作性
    3.8. 作用域
        3.8.1. 作用域
        3.8.2. 作用域之外
    3.9. Web 服务客户机视图
    3.10. Web 服务服务器视图
4. 客户机编程模型
    4.1. 概念
    4.2. 规范
        4.2.1. 服务查找
        4.2.2. 服务接口
        4.2.3. 端口存根和动态代理
        4.2.4. JAX_RPC 属性
        4.2.5. JAX-RPC 定制序列化程序/反序列化程序
        4.2.6. 打包
5. 服务器编程模型
    5.1. 目标
    5.2. 概念
    5.3. 端口组件模型规范
        5.3.1. 服务端点接口
        5.3.2. 服务实现 Bean
        5.3.3. 服务实现 Bean 生命周期
        5.3.4. JAX-RPC 定制序列化程序/反序列化程序
    5.4. 打包
        5.4.1. EJB 模块打包
        5.4.2. Web 应用程序模块打包
        5.4.3. EAR 文件中的装配
    5.5. 事务
    5.6. 容器提供者职责
6. 处理程序
    6.1. 概念
    6.2. 规范
        6.2.1. 适用情况
        6.2.2. 编程模型
        6.2.3. 开发者职责
        6.2.4. 容器提供者职责
    6.3. 打包
    6.4. 对象交互图
        6.4.1. 客户机 Web 服务方法访问
        6.4.2. EJB Web 服务方法调用
7. 部署描述符
    7.1. Web 服务部署描述符
        7.1.1. 概述
        7.1.2. 开发者职责
        7.1.3. 装配者职责
        7.1.4. 部署者职责
        7.1.5. Web 服务部署描述符 DTD
    7.2. Web 服务客户机部署描述符
        7.2.1. 概述
        7.2.2. 开发者职责
        7.2.3. 装配者职责
        7.2.4. 部署者职责
        7.2.5. webservicesclient.xml DTD
    7.3. JAX-RPC 映射部署描述符
        7.3.1. 概述
        7.3.2. 开发者职责
        7.3.3. 装配者职责
        7.3.4. 部署者职责
        7.3.5. JAX-RPC 映射 DTD
8. 部署
    8.1. 概述
    8.2. 容器提供者要求
        8.2.1. 部署构件
        8.2.2. 生成 Web 服务实现类
        8.2.3. 生成部署的 WSDL
        8.2.4. 发布部署的 WSDL
        8.2.5. 服务和生成的服务接口实现
        8.2.6. 静态存根生成
        8.2.7. 类型映射
        8.2.8. 映射要求
        8.2.9. 部署失败的情况
    8.3. 部署者职责
9. 安全性
    9.1. 概念
        9.1.1. 认证
        9.1.2. 授权
        9.1.3. 完整性和机密性
        9.1.4. 审计
        9.1.5. 不可抵赖性
    9.2. 目标
        9.2.1. 假设
    9.3. 规范
        9.3.1. 认证
        9.3.2. 授权
        9.3.3. 完整性和机密性
10. 附录
    10.1. 附录 A. 与其它 Java 标准的关系
    10.2. 附录 B. 参考资料
    10.3. 附录 C. 版本历史
        10.3.1. 附录 C.1. 版本 0.8
        10.3.2. 附录 C.2. 版本 0.7
        10.3.3. 附录 C.3. 版本 0.6
        10.3.4. 附录 C.4. 版本 0.5
        10.3.5. 附录 C.5. 版本 0.4 专家组草案


1. 前言

本规范定义了 Web Services for J2EE 体系结构。这个服务体系结构利用 J2EE 组件体系结构提供了一种客户机和服务器编程模式(可在应用程序服务器之间移植,并可在服务器间进行互操作),从而提供了一种可伸缩的安全环境,但仍然为 J2EE 开发者所熟知。

1.1. 目标读者

此规范旨在由以下读者使用:

  • 为遵循此规范的 Web 服务实现支持的 J2EE 供应商

  • 将部署到 J2EE 应用程序服务器的 Web 服务实现的开发者

  • 将部署到 J2EE 应用程序服务器的 Web 服务客户机的开发者

  • 访问部署到 J2EE 应用程序服务器的 Web 服务的 Web 服务客户机的开发者

此规范假定其读者熟悉 J2EE 平台和规范。它还假定读者熟悉 Web 服务,尤其是 [JAX-RPC] 规范和 WSDL 文档。

1.2. 致谢

此规范的原始思想建立在 IBM 成员 Donald F. Ferguson 的设想之上。它经过了业界范围内的专家小组的修正。专家小组的成员包括来自以下公司的积极的代表:IBM、Sun、Oracle、BEA、Sonic Software、SAP、HP、Silverstream 和 IONA。我们要感谢这些公司以及 JSR 109 专家小组的其它成员:EDS、Macromedia、Interwoven、Rational Software、Developmentor、interKeel、Borland、Cisco Systems、ATG、WebGain、Sybase、Motorola 和 WebMethods。

JSR 109 专家小组必须与其它 JSR 专家小组达成一致,从而为 Web Service for J2EE 定义一个一致的编程模型。我们特别要感谢 Rahul Sharma 和 JSR 101(JAX-RPC)专家小组、Farukh Najmi 和 JSR 093(JAX-R)专家小组,还有 Linda G. DeMichiel 和 JSR 153(EJB 2.1)专家小组。

1.3. 规范结构

此规范的下面两章内容概括了 J2EE 环境中的 Web 服务支持的需求及概念性体系结构。J2EE 中的 Web 服务的每个主要的集成点,如客户机模型、服务器模型、部署模型、WSDL 绑定以及安全,都有自己的章节。其中每一章都由两个主题构成:概念和规范。概念部分将讨论如何使用 Web 服务、相关问题、注意事项以及支持的情况。规范部分具有标准的形式,定义了该规范的实现者必须支持什么。

1.4. 文档约定

为了一致起见,此规范将沿用由 [EJB] 规范所使用的文档约定。

此规范中的说明性信息将用非固定字体表示。

包含描述性信息的段落(如描述典型应用的注释,或文本内容需要与说明性规范区分开来的注释)将使用这种表示强调的字体。

代码示例将使用这种固定字体。

本文当中的关键词“必须(MUST)”、“绝不可以(MUST NOT)”、“需要的(REQUIRED)”、“将(SHALL)”、“将不(SHALL NOT)”、“应该(SHOULD)”、“不应该(SHOULD NOT)”、“推荐(RECOMMENDED)”、“可以(MAY)”及“可选的(OPTIONAL)”的解释应依照 RFC 2119 中的描述。

2. 目标

这一部分列出了此规范的高级目标。

  • 建立在不断发展的 Web 服务业界标准(特别是 WSDL 1.1 和 SOAP 1.1)的基础之上。

  • 利用已有的 J2EE 1.3 技术。

  • 确保程序员能够实现和打包正确部署到遵循 J2EE 1.3 和本规范的应用程序服务器上的 Web 服务。

  • 确保遵循本规范的供应商实现之间可互操作,也就是说,在一个供应商的实现上的 Web 服务必须能够与在另一个供应商实现上执行的 Web 服务进行交互。

  • 定义一个支持 J2EE 中 Web 服务所需的最小集合,该集合的元素包括新的概念、接口、文件格式等等。

  • 清晰并简洁地定义 J2EE 应用程序服务器供应商在 J2EE 1.3 之上为遵循本规范需要提供的功能。

  • 定义本规范所需的角色、这些角色所实现的功能以及它们与 J2EE 平台角色的对应关系。定义 Web Services for J2EE 产品提供者为支持这些角色而必须提供的功能。

  • 支持一个用于定义新的 Web 服务并将其部署到 J2EE 应用程序服务器的简单的模型。

本规范与 J2EE 1.4 之间的关系在 10.1. 附录 A. 与其它 Java 标准的关系中有所定义。

2.1. 客户机模型目标

客户机编程模型应该与 JAX-RPC 所定义的客户机编程模型一致并兼容。

客户机编程模型的其它目标是要确保:

  • 程序员可以实现可能驻留在 J2EE 容器(例如使用 Web 服务的 EJB)遵循本规范的 Web 服务客户机应用程序,或者 J2EE 客户机容器可以调用在 Web Services for J2EE 容器中运行的 Web 服务。

  • 遵循本规范的客户机应用程序能够通过 HTTP 1.1 或 HTTPS SOAP 绑定调用任何基于 SOAP 1.1 的 Web 服务。

  • 使用其它客户机环境(如 Java 2 标准版环境)的程序员能够调用在 Web Services for J2EE 容器中运行的 Web 服务。使用 Java 之外的语言的程序员必须能够实现遵循 SOAP 1.1 的应用程序(此类应用程序可以使用遵循本规范的 Web 服务)。支持第 4 章 客户机编程模型中描述的客户机开发情况。

  • 客户机开发者必须能够不必清楚服务实现是如何完成的。

  • JSR 172 定义的 Java 2 微型版客户机应该能够使用 WSDL 和 JAX-RPC 运行时中发布的传输标准与 Web Services for J2EE 应用程序进行互操作。

2.2. 服务开发目标

服务开发模型定义了如何开发 Web 服务实现并将其部署到已有的 J2EE 容器中,包括下面几个特定的目标:

  • 如何实现 Web 服务在 Web 服务客户机看来应该是透明的。客户机应该不需了解 Web 服务是否被部署到 J2EE 或非 J2EE 环境中。

  • 由于 Web 服务实现必须被部署到 J2EE 容器中,所以实现服务的类必须遵循某个定义的需求,以确保它不会有损应用程序服务器的完整性。

  • JAX-RPC 定义了三类服务器端运行时,即基于 J2SE 的 JAX-RPC 运行时、基于 Servlet 容器的 JAX-RPC 运行时以及基于 J2EE 容器的 JAX-RPC 运行时。本规范定义了基于 J2EE 容器(Web 和 EJB)的运行时,因为它与 [JAX-RPC] 规范所定义的基于 Servlet 容器的模型一致。

  • 支持将 SOAP 1.1 请求映射和分派到 J2EE 无状态会话 Bean 上的方法。

  • 支持将 SOAP 1.1 请求映射和分派到 Web 容器中的 JAX-RPC 服务端点类上的方法。

2.3. 服务部署目标

  • Web 服务部署是声明性的。我们通过将 J2EE 1.3 模型扩展到支持部署描述符合 EAR 文件格式实现这一点。不过,这些变化都是最小的。

  • 已有的 J2EE 1.3 环境上能够支持 Web 服务部署。

  • 部署需要服务能够由 WSDL 表示。部署还需要 WSDL 文件。Web 服务部署必须支持:

    • 希望将 Web 服务部署为部署的中心的人

    • 希望将已有的、部署过的 J2EE 组件作为 Web 服务公开的人

2.4. 服务发布目标

  • 服务部署可以将 WSDL 发布到合适的服务注册中心、资源库(如果 Web 服务需要)、文件或 URL。

  • 如果 Web 服务需要由部署工具发布,执行发布所需的所有数据都必须在部署软件包中提供,或在部署过程中提供。

  • 如果执行了任何到 UDDI 的发布,还必须提供 WSDL 的 URL。

2.5. Web 服务注册中心目标

Web 服务注册中心 API 以及编程模型不在本规范的讨论范围之内。Web 服务实现、Web 服务客户机或 Web 服务部署工具可以使用包括 JAX-R 在内的任何注册中心 API。JAX-R 并不直接支持 WSDL 发布。不过它的确支持与 UDDI 目录的交互。UDDI.org 规定了如何将用 WSDL 描述的服务发布到 UDDI 目录。

本规范定义了部署工具的服务发布职责。

本规范没有定义在开发或部署服务实现期间的服务定义发现(查找要实现的 WSDL)。

本规范没有定义开发、部署或服务客户机运行时期间的服务发现。

3. 概述

3.1. Web 服务体系结构概述

Web 服务是一种面向服务的体系结构,它能够创建服务的抽象定义、提供服务的具体实现、发布并查找服务、实现服务实例选择,并实现可互操作服务的使用。一般来讲,Web 服务实现以及客户机的使用可以按多种方式区分。客户机和服务器实现可以按编程模式区分。具体的实现可以按逻辑和传输区分。

图 1. 面向服务的体系结构

面向服务的体系结构

服务提供者使用 Web 服务描述语言(Web Services Description Language,WSDL)来定义抽象的服务描述。然后,抽象的服务描述将用 WSDL 生成具体的服务描述,从而创建出具体的服务。接下来,具体的服务描述可以被发布到类似统一描述、发现和集成(Universal Description,Discovery and Integration,UDDI)这样的注册中心。服务请求者可以使用注册中心来找到服务描述,并根据服务描述选择和使用服务的具体实现。

抽象服务描述在 WSDL 文档中被定义为端口类型(PortType)。具体的服务实例是由端口类型、传输和编码绑定以及作为 WSDL 端口的地址共同定义的。多组端口聚集成一个 WSDL 服务。

3.2. Web 服务

对于 Web 服务还没有被广泛接受的定义。由于撰写此规范的需要,我们将 Web 服务定义为具有以下特征的组件:

  • 服务实现将实现能够由 WSDL 描述的接口的方法。方法将通过使用无状态会话 EJB 或 JAX-RPC Web 组件来实现。

  • Web 服务的接口在部署期间可能会被发布到一个或多个 Web 服务注册中心。

  • 只使用由本规范描述的功能的 Web 服务实现可以被部署到任何遵循 Web Services for J2EE 的应用程序服务器中。

  • 服务实例(称为端口(Port))由容器创建和管理。

  • 运行时服务需求(如安全性属性)与服务实现是分开来的。您可以在组装或部署期间使用工具来定义这些需求。

  • 容器将充当对服务进行访问的媒介。

JAX-RPC 定义了从 WSDL 文档到 Java 的编程模型映射,该映射提供了一个工厂(服务)用来选择客户机希望使用哪个聚集的端口。请参阅图 2 的逻辑图表。一般来讲,传输、编码和端口的地址在客户机看来都是可见的。客户机只需在服务器端点接口(Service Endpoint Interface)上按照 JAX-RPC 定义的方式(也就是端口类型)调用方法来访问服务即可。请参阅第 4 章 客户机编程模型了解更多细节。

图 2. 客户机视图

客户机视图

3.3. Web Services for J2EE 概述

Web Services for J2EE 规范定义了所需的体系结构关系,如图 3 所示。它是一种逻辑关系,对容器提供者结构化容器和过程没有任何需求。添加到 J2EE 平台的内容包括依赖于由 Web 和 EJB 容器提供的容器功能的端口组件,还有 SOAP/HTTP 传输。

图 3. J2EE 体系结构示意图

J2EE 体系结构示意图

Web Services for J2EE 需要端口能够从客户机、Web 和 EJB 容器引用。本规范不需要端口能够从 applet 容器进行访问。

本规范给那些由 JAX-RPC 定义的、用来实现 Web 服务容器添加了额外的构件:基于角色的开发方法学、可移植的打包和 J2EE 容器服务对 Web 服务的体系结构。这些将在后面的章节中描述。

3.3.1. Web 服务组件

本规范定义了两种实现在 J2EE 环境中运行的 Web 服务的方式,但并不把 Web 服务实现局限为仅仅这两种方式。第一种方法是基于容器的 JAX-RPC 编程模式的扩展,它将 Web 服务定义为在 Web 容器中运行的 Java 类。第二种方法将使用 EJB 容器中的无状态会话 EJB 的受限实现。还可能有其它的服务实现情况,但它们并不在本规范的定义之列。

3.3.2. Web 服务容器

容器提供了服务实现的生命周期管理、方法调用的并发管理以及安全性服务。容器提供了专门在 J2EE 环境中支持 Web 服务的服务。本规范不需要实现新的容器。您可以使用已有的 J2EE 容器,而且我们的确希望您使用已有的容器来托管 Web 服务。Web 服务实例生命周期和并发管理依赖于服务实现在哪个容器中运行。Web 容器中的 JAX-RPC 服务端点实现遵循标准的 servlet 生命周期和并发需求,而 EJB 容器中的 EJB 实现遵循标准的 EJB 生命周期和并发需求。

3.4. 平台角色

本规范定义了已有的 J2EE 平台角色的职责。本规范没有定义新的角色。对于本规范中使用的 Web Services for J2EE 来说有两个特定的角色,不过它们可以被映射到已有的 J2EE 平台角色上。Web Services for J2EE 产品提供者角色可以被映射到 J2EE 产品提供者角色上,Web 服务容器提供者角色可以被映射到 J2EE 规范中的容器提供者角色上。

一般来讲,开发者角色负责服务定义、实现以及 J2EE 模块中的打包。装配者角色负责将模块装配成应用程序,部署者角色负责发布部署后的服务并将客户机引用解析为服务。您可以在后面的章节中找到更多有关角色职责的细节描述。

3.5. 可移植性

标准的打包格式、声明性的部署模型以及标准的运行时服务为使用 Web 服务开发的应用程序提供了可移植性。标准的 J2EE 模块中所包含的特定于 Web 服务的部署描述符定义了针对这种模块的 Web 服务应用。您可以在后面的章节中找到关于 Web 服务部署描述符的更多细节描述。根据本规范,为了能够部署打包后的应用程序,您需要支持 Web Services for J2EE 的部署工具。

Web 服务容器提供者可以在牺牲一定的应用程序可移植性的前提下,为其它服务实现以及其它传输和编码绑定提供支持。

3.6. 标准服务

J2EE 平台定义了 J2EE 提供者必须提供的一组标准服务。Web Services for J2EE 规范确定了另一组所需的运行时服务。

3.6.1. JAX-RPC

JAX-RPC 提供了运行时服务,以便向 XML SOAP 消息编入 Java 数据和对象,以及从 XML SOAP 消息中编出 Java 数据和对象。另外,JAX-RPC 定义了服务端点接口(Service Endpoint Interface)和服务(Service)类从 WSDL 到 Java 的映射。

3.7. 互操作性

本规范定义了在 J2EE(TM)之上实现本规范的产品的互操作性需求,从而扩展 J2EE 平台的互操作性需求。互操作性需求依赖于本规范所依据的已有标准的互操作性。

本规范建立在以下 JSR 和规范的不断发展基础之上:

  • JSR 101,基于 Java(TM)API for XML 的 RPC(JAX-RPC)

  • J2EE 1.3

  • [EJB]

  • Servlet 2.3

3.8. 作用域

3.8.1. 作用域

  • 本规范的作用域仅限于在业界中被广泛制定和接受的 Web 服务标准。这些标准包括:

    • SOAP 1.1 以及带附件的 SOAP

    • WSDL 1.1

    • UDDI 1.0

  • 本规范仅限于定义 HTTP 1.1 或 HTTPS 协议上的 SOAP 以及 Web 服务通信 API(供应商可以随意支持更多的传输)。

  • 这些标准应该会继续改变和发展。这个 JSR 将来的版本将适应和解决这些标准将来的版本的问题。在本规范中,所有对 SOAP、WSDL、和 UDDI 的引用都假定为上面定义的版本。

3.8.2. 作用域之外

  • HTTP 上的 SOAP 最缺乏的就是基本可靠消息语义。除了这一不足之外,本 JSR 在其作用域内还没有考虑到消息可靠性(Message Reliability)或消息完整性(Message Integrity)。其它的 JSR,如 JAX-M 和 JMS 的演变和合并产物,还有 W3C 中的活动以及其它标准实体,将定义这些功能。

  • XML 数据的持久性。

  • 工作流和数据流模型。

  • 任意的 XML 转换。

  • 与本规范不一致的 Web 服务客户机的客户机编程模型。

3.9. Web 服务客户机视图

Web 服务客户机视图与 Enterprise JavaBean 的客户机视图非常相似。Web 服务的客户机可以是另一个 Web 服务、一个 J2EE 组件(包括 J2EE 应用程序客户机),或任意的 Java 应用程序。非 Java 应用程序或非 Web Services for J2EE 应用程序也可以充当 Web 服务客户机,但这种应用程序的客户机视图不在本规范的讨论之列。

Web 服务客户机视图可以是远程的,它提供了本地-远程(local-remote)的透明性。

端口(Port)提供者和容器共同提供了 Web 服务客户机视图。它包括以下两种接口:

  • 服务接口

  • 服务端点接口

JAX-RPC 处理程序接口被认为是容器 SPI,因此不是客户机视图的一部分。

图 4. Web 服务客户机视图

Web 服务客户机视图

服务接口(Service Interface)定义了客户机可以用来访问 Web 服务的端口的方法。客户机并不创建或删除端口。它使用服务接口来获取对端口的访问权。服务接口由 [JAX-RPC] 规范定义,但其行为由 Web 服务提供者所提供的 WSDL 文档来定义。容器的部署工具提供服务接口或 JAX-RPC 生成的服务接口的方法的实现。

客户机通过使用 JNDI API 来查找服务接口。这在第 4 章 客户机编程模型中有进一步的解释。Web 服务是由客户机通过使用服务端点接口来访问的。服务端点接口由服务提供者指定。部署工具和容器运行时提供服务器端类,它将向 Web 服务实现分派一个 SOAP 请求,后者将实现服务端点接口的方法。服务端点接口将扩展 java.rmi.Remote 接口,并完全由 [JAX-RPC] 规范所定义。

端口在客户机视图中没有任何标识,它可以被认为是无状态对象。

3.10. Web 服务服务器视图

第 5 章 服务器编程模型定义了服务器编程模型的细节问题。这一部分定义了服务提供者的一般需求。

服务提供者定义了 WSDL 端口类型、WSDL 绑定,以及 Web 服务的服务端点接口。端口类型和服务端点接口必须遵循 JAX-RPC 中的规则,才能进行从 WSDL 到 Java 以及从 Java 到 WSDL 的映射。

服务提供者在 WSDL 文档中定义了 WSDL 服务和端口聚集。

服务提供者用下面两种方式之一实现 Web 服务的业务逻辑:

  1. 无状态会话 Bean:服务提供者通过实现无状态会话 EJB 来实现 Web 服务业务逻辑。EJB 的远程接口方法说明必须与服务端点接口的方法说明一致,还必须包含服务端点接口的所有方法。

  2. Java 类:服务提供者根据基于 JAX-RPC Servlet 的服务实现模型定义的需求来实现 Web 服务业务逻辑。

Web 服务生命周期管理与服务实现方法有关。

服务提供者实现特定于所使用的服务实现方法的容器回调方法。请参阅 [JAX-RPC] 规范和 Enterprise JavaBean 规范以了解关于容器回调方法的详细内容。

容器管理 Web 服务所需的运行时服务,如安全性服务。Web 服务不会在全局事务上下文中执行。如果客户机用事务上下文访问端口,那么在端口被访问前上下文就会被暂挂。

服务提供者必须避免妨碍容器操作的编程习惯。这些限制是由 J2EE 1.3、Servlet 2.3 和 [EJB] 规范定义的。

打包 J2EE 模块中的 Web 服务与服务实现方法有关,但遵循 J2EE 对 EJB-JAR 文件或 WAR 文件的需求。它包含服务端点接口的 Java 类文件以及 Web 服务的 WSDL 文档。另外,它包含一个 XML 部署描述符,用来定义 Web 服务端口和它们的结构。打包需求在第 5.4 节 打包中描述。

4. 客户机编程模型

本章描述了 Web Services for J2EE 的客户机编程模型。一般来说,客户机编程模型在 [JAX-RPC] 规范中有详细的描述。本规范讨论了 J2EE 环境中 JAX-RPC 客户机编程模型的使用。

本规范和 [JAX-RPC] 规范之间的区别将用这形式指出。

4.1. 概念

Web 服务客户机不局限在本规范所定义的客户机,然而本规范并没有特别强调非 Web Services for J2EE 客户机的客户机编程模型。一般来说,Web 服务的 WSDL 定义为非 Web Services for J2EE 客户机的构建和运行提供了足够的信息,但并没有定义它的编程模型。本章的其它部分讨论了 Web Services for J2EE 客户机的编程模型。它并不假定客户机调用的 Web 服务实现是由 Web Services for J2EE 运行时还是某个外部运行时托管的。

客户机使用 Web Services for J2EE 运行时来访问并调用 Web 服务的方法。客户机可以是以下任意一种:J2EE 应用程序客户机、Web 组件、EJB 组件和另外的 Web 服务。

Web 服务的客户机视图是代表客户机执行业务逻辑一组方法。客户机无法区分方法是本地执行还是远程执行的,也不能确定服务是如何实现的。最后,客户机必须假定 Web 服务的方法在多次 Web 服务方法调用中不具有持久的状态。客户机可以认为 Web 服务实现是无状态的。

按照 [JAX-RPC] 规范中所定义,客户机使用服务端点接口来访问 Web 服务。对 Web 服务实现的引用决不应传递到另一个对象上。客户机决不应直接访问 Web 服务实现。这样做将跳过可能会打开安全漏洞或导致反常行为的容器的请求处理。

按照 [JAX-RPC] 所定义,客户机使用 JNDI 查找来访问实现服务接口的服务(Service)对象。服务对象是由客户机用来获取实现服务端点接口的存根(stub)或代理的一个工厂。存根是 Web 服务实例的客户机表示。

按照 JAX-RPC 所定义,服务接口可以是普通的 javax.xml.rpc.Service 接口,也可以是继承了 javax.xml.rpc.Service 的生成的服务接口(Generated Service Interface)。除非另行指定,本文档中接下来对服务接口的引用指的是一般接口或生成的接口。

客户机不能控制服务器上 Web 服务实现的生命周期。客户机并不创建或销毁 Web 服务实例(也就是我们所说的端口)。客户机只访问端口。端口的生命周期或者 Web 服务实现的实例是由托管 Web 服务的运行时管理的。端口没有标识。这就意味着,客户机不能将端口与其它端口相比较来确定它们是否相同或相符,客户机也不能访问特定的端口实例。如果在 Web 服务访问的过程中发生了崩溃或者重新启动,客户机无法确定服务器是否崩溃或者重新启动。

客户机开发者从服务端点接口和服务接口开始。开发者如何获得这些不在我们讨论之列,但我们要讨论 Web 服务提供者如何提供它们,或者如何使用工具从 Web 服务提供者提供的 WSDL 定义生成它们。这些工具根据 JAX-RPC 规则操作,以进行 WSDL 到 Java 的映射。客户机开发者不需要在开发期间生成存根,我们也不鼓励他们这样做。客户机应该使用接口,而不是存根。存根将在开发期间生成,特定于客户机运行所处的供应商运行时。

Web 服务的每个客户机 JNDI 查找都是通过一个逻辑名称进行的。客户机开发者选择客户机代码中要使用的逻辑名称,并将它在 Web 服务客户机部署描述符中随所需的服务接口一起声明。客户机应该使用接口,而不是存根。

服务接口方法可以分为两类:存根/代理和 DII。存根/代理方法提供了两种对端口进行访问的方法,一种是特定于服务(客户机需要 WSDL 信息)的,另一种是与服务无关的(不需 WSDL 信息)。DII 方法在客户机需要与 Web 服务进行动态的、不基于存根的通信时使用。

客户机可以使用服务接口的存根/代理方法来获取端口存根或动态代理。特定于 WSDL 的方法可以在客户机开发者能够得到服务的完整 WSDL 定义时使用。与 WSDL 无关的方法必须在客户机开发者只有部分 WSDL 定义(只包含端口类型和绑定)的情况下使用。

4.2. 规范

4.2.1. 服务查找

客户机开发者需要为 Web 服务定义一个逻辑的 JNDI 名称,这被称为服务引用。该名称在客户机的部署描述符中指定。我们推荐在一个 JNDI 名称空间的服务子上下文中对所有服务引用逻辑名称进行组织,但这不是必需的。容器必须使用服务引用的逻辑名称在客户机环境上下文 java:comp/env 中绑定服务接口实现。在下面的示例中,客户机部署描述符中给出的逻辑服务名为 service/AddressBookService

容器充当代表客户机的媒介,用来确保能够通过 JNDI 查找的方式得到服务接口。更明确的是,容器必须确保所需的服务接口的实现必须按照 Web 服务客户机部署描述符中的服务引用所规定的方式绑定到客户机所选择的 JNDI 名称空间中的一个位置。下面的代码片段可以更好地说明这一点:

     InitialContext ic = new InitialContext ();
     Service abf = (Service)ic.lookup(
          "java:comp/env/service/AddressBookService");
			

在上面的示例中,容器必须确保一般的服务接口实现 javax.xml.rpc.Service 在 JNDI 名称空间中被绑定到开发者指定的位置。类似代码片段被用于访问实现生成的服务接口(如 AddressBookService)的对象。

     InitialContext ic = new InitialContext ();
     AddressBookService abf = (AddressBookService)ic.lookup(
          "java:comp/env/service/AddressBookService"); 
			

J2EE 产品提供者需要在 Web、EJB 和应用程序客户机容器中提供服务查找支持。

4.2.2. 服务接口

服务接口被客户机用来获取端口的存根或动态代理,或者DII Call 对象。容器提供者需要支持服务接口的所有方法(除了第 4.2.2.7 节和第 4.2.2.8 节中描述的 getHandlerRegistry() 和 getTypeMappingRegistry() 方法之外)。

客户机开发者必须在客户机部署描述符中说明应用程序使用的服务接口类型。

4.2.2.1 存根/代理访问

客户机可以使用下面的服务接口方法来获取 Web 服务的静态存根或动态代理:

     java.rmi.Remote getPort(QName portName, Class serviceEndpointInterface) throws ServiceException;
     java.rmi.Remote getPort(java.lang.Class serviceEndpointInterface) throws ServiceException;
				

客户机还可以使用生成的服务接口的其它方法来获取 Web 服务的静态存根或动态代理。

按照第 4.2.3 节 端口存根和动态代理中所描述,容器必须为这些方法提供至少一个静态存根或动态代理。容器必须确保存根或动态代理在返回到客户机之前被完全配置为由客户机使用。存根或动态代理由 getPort 还是 get<port name> 方法返回的部署时选择不在本规范的讨论之列。容器提供者可以自行提供其中一个或两者。

容器提供者必须提供 getPort(java.lang.Class serviceEndpointInterface) 方法的端口解析。这在解析多个使用同一绑定的 WSDL 端口或开发期间端口未知的情况下很有用。客户机必须在客户机部署描述符中说明它对服务端点接口的容器端口解析的依赖性。如果客户机部署描述符中没有说明解析接口端口参数的依赖性,容器可能会提供缺省的解析功能或抛出 ServiceException。

4.2.2.2 动态端口访问

客户机可以使用下面几种由客户机环境的 JNDI 查找找到的服务接口的 DII 方法来获取 Call 对象:

     Call createCall() throws ServiceException;
     Call createCall(QName portName) throws ServiceException;
     Call createCall(QName portName, String operationName) throws ServiceException;
     Call createCall(QName portName, QName operationName) throws ServiceException;
     Call[] getCalls(QName portName) throws ServiceException;
				

DII Call 对象不一定能够根据用来获取它的方法被预先配置。请参阅 [JAX-RPC] 规范以了解详细内容。

4.2.2.3 ServiceFactory

Web Services for J2EE 产品中不支持 JAX-RPC ServiceFactory 类。客户机必须按照第 4.2.1 节 服务查找中描述的方式使用 JNDI 查找来获取服务接口。

4.2.2.4 有完整 WSDL 的服务方法使用

如果客户机部署描述符中给出了完整的 WSDL 描述以及 JAX-RPC 映射文件,那么客户机开发者就可以使用服务接口的所有方法(除了第 4.2.2.7 节和第 4.2.2.8 节中描述的情况之外)。WSDL 中可能没有端口地址属性,也可能是虚值。

4.2.2.5 有部分 WSDL 的服务方法使用

如果客户机部署描述符中给出了部分 WSDL 定义,那么客户机开发者就可以使用下面服务接口方法。

Call createCall() throws ServiceException;
java.rmi.Remote getPort(java.lang.Class serviceEndpointInterface) throws ServiceException;
java.net.URL getWSDLDocumentLocation()
				

这里定义了一个不完整的 WSDL 定义,作为完全指定的 WSDL 文档,它不包括服务或端口元素。开发者所指定的 JAX-RPC 映射文件在这种情况下将不包括 service-interface-mapping

如果服务接口的其它方法被调用,而开发者指定了部分的 WSDL 定义,那么容器就必须抛出 java.lang.UnsupportedOperationException

4.2.2.6 没有 WSDL 的服务方法使用

如果客户机部署描述符中没有指定 WSDL 定义,那么客户机开发者就可以使用下面的服务接口方法:

     Call createCall() throws ServiceException;
				

如果部署描述符中没有指定 wsdl-file,那么就决不能指定 jaxrpc-mapping-file

如果服务接口的其它方法被调用,而开发者没有指定 WSDL 定义,那么容器就必须抛出 java.lang.UnsupportedOperationException

4.2.2.7 处理程序

组件不应使用 getHandlerRegistry() 方法。容器提供者必须从服务接口的 getHandlerRegistry() 方法抛出 java.lang.UnsupportedOperationException。处理程序支持在第 6 章 处理程序中描述。

4.2.2.8 类型映射

组件不应使用 getTypeMappingRegistry() 方法。容器提供者必须从服务接口的 getTypeMappingRegistry() 方法抛出 java.lang.UnsupportedOperationException

4.2.3. 端口存根和动态代理

4.2.3.1 标识

端口存根和动态代理是客户机的 Web 服务表示。与存根或代理进行通信的端口在客户机视图中没有标识。equals() 方法不能用于比较两个存根或代理实例以确定它们是否代表同一个端口。存根的 equals()hash()toString() 方法的结果是未指定的。客户机无法确保端口存根、动态代理或调用在多次调用中会访问某个特定的端口实例或者同一个端口实例。

4.2.3.2 类型强制转型

尽管我们认为存根和动态类是远程(Remote)对象,但客户机并不需要使用 PortableRemoteObject.narrow(...)。然而,我们鼓励客户机使用 PortableRemoteObject.narrow(...) 来防止与其它远程对象的客户机使用发生混淆。

4.2.4. JAX_RPC 属性

J2EE 容器环境改变了 JAX-RPC 中定义的支持存根/代理属性所需的条件。

4.2.4.1 可选的属性

容器提供者不需要支持下面 javax.xml.rpc.Stubjavax.xml.rpc.Call 接口上的属性。如果 setProperty() 方法是通过使用下面的属性调用的,而且存根实现不支持属性,那么存根就必须抛出 java.lang.UnsupportedOperationException 异常。

USERNAME_PROPERTY 以及 PASSWORD_PROPERTY — 客户机管理的凭证传播属性。

容器提供者不需要支持存根实现上的 USERNAME_PROPERTY 和 PASSWORD_PROPERTY 属性。容器提供者负责获取凭证信息并根据给定请求的认证需求将其传送到服务器。举例来说,当提交一条 HTTP 请求以访问 Web 服务,而服务器被配置为需要 HTTP Basic 认证时,那么容器就必须获取用户标识和密码,并将 HTTP 授权(Authorization)头添加到 HTTP 请求。在 HTTP 请求需要客户机证书的情况下,容器负责用共用的 SSL 建立 HTTPS 连接,方法是让底层 SSL 层能够访问客户机证书。

J2EE 1.3 规范的第 9.2 节描述了客户机能够用来以编程方式通过实现 javax.security.auth.callback.CallbackHandler 接口向容器提供认证信息的机制。

SESSION_MAINTAIN_PROPERTY — 会话管理配置。

容器提供者不需要支持存根实现上的 SESSION_MAINTAIN_PROPERTY 属性。参与 HTTP 会话的容器管理和配置是特定于容器实现以及最终用户需求的。容器一般会为最终用户提供一种方法来选择是否希望参与 HTTP 会话,但对定义这一点没有标准要求。

参与 HTTP 会话特定于 JAX-RPC 服务端点模型,并不一定适合实现 Web 服务的会话 EJB 模型。如果客户机调用了需要参与 HTTP 会话的 Web 服务,而客户机被配置为不参与 HTTP 会话,那么它就会接收到错误。

4.2.4.2 所需的属性

ENDPOINT_ADDRESS_PROPERTY — 动态端点地址分配。

容器提供者需要支持 ENDPOINT_ADDRESS_PROPERTY,从而使组件能够动态地将存根/代理重定向至不同的 URI。

4.2.5. JAX-RPC 定制序列化程序/反序列化程序

JAX-RPC 定制序列化程序/反序列化程序的使用不在规范的这个版本的讨论之列。JAX-RPC 定制序列化程序/反序列化程序不能在 Web Services for J2EE 提供者之间移植,因此也不属于可移植部署单元的一部分。我们希望在 JAX-RPC 的将来版本解决该问题之前,提供商将为此问题提供专门的解决方案。

4.2.6. 打包

开发者要负责通过容纳或引用的方式,对 WSDL 文件、服务端点接口类、生成的服务接口类(如果使用了该类)、它们相关的类、JAX-RPC 映射文件以及 J2EE 模块中的 Web 服务客户机部署描述符进行打包。模块中 Web 服务客户机部署描述符的位置特定于模块。WSDL 文件的位置相对于模块的根,而且一般与模块的部署描述符并列。JAX-RPC 映射文件位于模块根结构的相对位置,而且一般与 WSDL 文件位于同一位置。开发者决不能打包生成的存根。

5. 服务器编程模型

本章定义了 Web Services for J2EE 的服务器编程模型。WSDL 文档定义了 Web 服务的互操作性,其中包括传输和有线格式需求的规范。一般来讲,WSDL 对客户机或服务器的编程模型没有什么需求。Web Services for J2EE 定义了两种实现 Web 服务的方法。它需要基于 JAX-RPC Servlet 容器的 Java 类编程模型来实现在 Web 容器中运行的 Web 服务,还需要无状态会话 EJB 编程模型来实现在 EJB 容器中运行的 Web 服务。这两种实现方法提供了定义端口组件,从而将可移植应用程序引入 Web 服务编程范型的方法。本规范还要求开发者能够从简单做起,慢慢发展成为能够使用更复杂的服务质量。下面几节定义了端口组件的要求。

5.1. 目标

端口组件旨在达到以下目标:

  • 提供可移植的 Web 服务编程模型

  • 提供一种服务器编程模型,该模型将维护一致的客户机视图。客户机绝不需要了解服务是如何实现的。

  • 提供从简单开始发展到更复杂的运行时服务需求的途径

  • 利用已有 J2EE 容器的功能

  • 利用熟悉的编程模型

5.2. 概念

端口组件(有时称为端口)定义了 Web 服务的服务器视图。每个端口都充当 WSDL 端口地址定义的一个位置。端口组件充当 WSDL 端口类型定义的操作请求。每个端口组件都有一个服务端点接口和一个服务实现 Bean。服务端点接口是 WSDL 端口类型的 Java 映射和与 WSDL 端口相关联的绑定。服务实现 Bean 根据端口部署所在的容器可能会有所不同,但一般来讲,它是实现服务端点接口定义的方法的 Java 类。WSDL 端口只在地址上有区别,被映射为单独的端口组件,每个都带有可能是唯一的但也许是共享的服务实现 Bean。图 5 在下面说明了这一点。

图 5. 容器

容器

端口的生命周期与容器有关,而且完全由容器控制,但大体上与容器本身的生命周期相同。端口在 WSDL 端口地址接收到的第一个请求可以使用之前由容器创建并初始化。端口在容器认为必要的时候被容器销毁,比如在容器关闭的时候销毁。

端口的实现和它运行所在的容器是紧密相关的。JAX-RPC 服务实现 Bean 总是在 Web 容器中运行。EJB 服务实现类总是在 EJB 容器中运行。

端口组件将服务实现 Bean 与 WSDL 端口关联。一般来讲,端口组件将服务需求定义委托给 J2EE 组件的部署描述符。第 6.3 节 打包第 7.3 节 JAX-RPC 映射部署描述符中将进一步讨论这个问题。容器为 WSDL 端口地址提供侦听器,并提供一种将请求分派到服务实现的方法。容器还向用于引用分布式对象和资源的物理映射提供运行时服务,如安全性约束和逻辑。

5.3. 端口组件模型规范

端口组件定义了将 Web 服务变为可移植服务器应用程序的编程模型构件。端口组件与 WSDL 端口的关联提供了互操作性。编程模型构件包括:

WSDL 文档 — 尽管不是严格意义上的编程模型构件,WSDL 文档还是提供了能够发布到第三方的 Web 服务标准描述。WSDL 文档和服务端点接口根据 JAX-RPC WSDL 和 Java 之间的映射规则相关联。OUT 以及 IN/OUT 参数的支持对 EJB 容器来说是可选的。
服务端点接口(Service Endpoint Interface,SEI)— 这个接口定义了由服务实现 Bean 实现的方法。是否支持 Holder 参数对 EJB 容器来说是可选的。
服务实现 Bean — 服务实现 Bean 是一种提供 Web 服务业务逻辑的 Java 类。此外,它还定义容器的端口组件契约,这使得业务逻辑可以与容器服务交互。它实现与 SEI 相同的方法和签名,但不是实现 SEI 本身所需要的。
安全角色引用 — 端口可能在部署描述符中说明逻辑角色名称。这些逻辑角色名称在各个模块之间由装配者统一,并在部署时映射到物理角色,使服务提供实例级的安全性检查。

开发者在 Web 服务部署描述符中声明端口组件。部署描述符包括描述端口类型和 Web 服务绑定的 WSDL 文档。部署者和部署工具将处理从端口到容器的映射。

5.3.1. 服务端点接口

服务端点接口(Service Endpoint Interface,SEI)必须遵循 WSDL 和 Java 互映射的 JAX-RPC 规则。根据这些规则,SEI 与 WSDL 端口类型以及 WSDL 绑定有关。SEI 是部署工具和并行客户机开发需要使用的。端口组件开发者负责提供带有所定义的最少端口类型和绑定的 WSDL 文档以及 SEI,并负责保持两者之间的同步。

JAX-RPC 将 Holder 定义为不能序列化的类,它不能由 Enterprise JavaBean 的远程接口实现。因此,在 EJB 容器中部署的端口组件并不需要支持为了参数而使用 Holder 的 SEI。

5.3.2. 服务实现 Bean

有两种方法可以实现服务实现 Bean。按照 [JAX-RPC] 规范的第 10 章所定义,其中包括无状态会话 EJB 和 JAX-RPC 服务端点。这两种编程模型在第 5.3.2.1 节和第 5.3.2.2 节中有完整的定义。

容器可以使用任何 bean 实例为请求提供服务。

5.3.2.1 EJB 编程模型

无状态会话 Bean,如 [EJB] 规范的第 7.8 到 7.10 节中所定义,可以用来实现将在 EJB 容器中部署的 Web 服务。

无状态会话 Bean 不必担心多线程访问。EJB 容器需要通过服务实现 Bean 的任意实例来对请求流进行序列化。

这里将部分重复对创建服务实现 Bean 作为无状态会话 EJB 的要求。

  • 服务实现 Bean 必须有缺省的公开构造函数

  • 服务实现 Bean 可以实现服务端点接口,但并非必须如此。bean 必须实现 SEI 所有的方法说明。服务实现 Bean 方法不需要抛出 javax.rmi.RemoteException。bean 的业务方法必须是公开的,而且绝不能是最终或静态的。它可以实现除 SEI 所定义的方法之外的其它方法。

  • 服务实现 Bean 必须是无状态对象。服务实现 Bean 绝不能在各方法调用之间保存特定于客户机的状态,不管是在 bean 实例的数据成员中还是在实例外部都不可以。

  • 类必须是公开的,绝不能是最终的,也绝不能是抽象的。

  • 类绝不能定义 finalize() 方法。

  • 目前,它必须实现不接受参数的 ejbCreate()ejbRemove() 方法。这是 EJB 容器的要求,不过一般可以用空的实现来排除。

5.3.2.1.1 所需的会话 Bean 接口

目前,无状态会话 Bean 必须直接或间接地实现 javax.ejb.SessionBean 接口。

该接口使容器能够在其状态中通知服务实现 Bean 即将发生的错误。Enterprise JavaBean 规范 2.0 的第 7.5.1 节中定义了该接口的全部需要。

5.3.2.1.2 允许的对容器服务的访问

[EJB] 规范的第 7.8.2 节定义了允许的容器服务访问要求。

5.3.2.1.3 公开已有的 EJB

已有的 Enterprise JavaBean 如果符合下面的要求,就可以作为服务实现 Bean 使用:

  • EJB bean 类的业务方法必须满足第 5.3.1 节 服务端点接口中定义的服务实现 Bean 的要求。

  • 服务端点接口方法必须是 EJB 的远程接口方法的一个子集,而且 SEI 必须符合 Java 到 WSDL 映射的 [JAX-RPC] 规范中描述的要求。

  • SEI 方法的事务属性绝不能包括强制属性。

开发者必须按照第 5.4 节 打包中描述的方式打包 Web 服务,而且必须指定从 Web 服务部署描述符中的端口到已有 EJB 的 ejb-link

5.3.2.2 Web 容器编程模型

[JAX-RPC] 规范中使用的 JAX-RPC 服务端点一词有点令人迷惑,因为服务实现 Bean 都需要使用 JAX-RPC 运行时。然而,在这种情况下它指的是用来创建在 Web 容器中运行的 Web 服务的 [JAX-RPC] 规范中定义的编程模型。我们在这里重复这个要求,并加以澄清。对 JAX-RPC 定义的编程模型的改变是在 J2EE 容器管理的环境中运行所需要的。

JAX-RPC 服务端点可以是单线程,也可以是多线程的。我们在这里说明并发性要求是作为编程模型的一部分。如果组件需要单线程访问,JAX-RPC 服务端点就必须实现 javax.servlet.SingleThreadModel。容器必须将实现 SingleThreadModel 接口的服务实现 Bean 的方法请求序列化。

服务实现 Bean 必须遵循 [JAX-RPC] 规范中概述的服务开发者要求,除非另行指出,否则以下面列出的为准。

  • 服务实现 Bean 必须有一个缺省的公开构造函数。

  • 服务实现 Bean 可以实现服务端点接口,但并非必须如此。bean 必须实现 SEI 的所有方法说明。bean 的业务方法必须是公开的(public),并且绝不可以是最终(final)的或静态(static)的。它可以实现除 SEI 所定义的方法之外的其它方法。

  • 服务实现必须是无状态对象。服务实现 Bean 绝不能在各方法调用之间保存特定于客户机的状态,不管是在 bean 实例的数据成员中还是在实例外部都不可以。容器可以使用任何 bean 实例作为请求。

  • 类必须是公开的,绝不能是最终的,也绝不能是抽象的。

  • 类绝不能定义 finalize() 方法。

5.3.2.2.1 可选的 ServiceLifecycle 接口

Web 容器的服务实现 Bean 可以实现 java.xml.rpc.server.ServiceLifeCycle 接口:

     package javax.xml.rpc.server;
     public interface ServiceLifecycle {
     void init(Object context) throws ServiceException;
     void destroy();
     }
					

ServiceLifeCycle 接口使容器能够通知服务实现 Bean 即将发生的自身状态的改变。bean 可以使用通知来准备转换的中间状态。如果 bean 实现 ServiceLifeCycle 接口,容器就需要按照下面描述的方式调用 init 和 destroy 方法。

容器在开始将请求分派到 bean 的 SEI 方法之前,必须调用 init 方法。容器所提供的 init 方法参数值由 [JAX-RPC] 规范描述。bean 可以使用容器通知来使其中间状态准备好接收请求。

容器必须让 bean 知道它将通过调用 destroy 方法从容器的工作集中删除 bean 实例的意图。容器在请求正由 bean 实例处理时可能不会调用 destroy 方法。容器在 destroy 方法被调用后可能不会将其它请求分派到 bean 的 SEI 方法。

5.3.2.2.2 允许的对容器服务的访问

容器根据服务实现 Bean 的生命周期状态提供特定服务。下表描述了可以在 bean 的各种方法中访问的服务。如果 bean 试图访问不允许访问的容器服务,就会抛出 java.lang.IllegalStateException

表 1:允许的对容器服务的访问
Bean 方法允许的容器支持
构造函数
initjava:comp/env 的 JNDI 查找
destroy
SEI 的业务方法
ServletEndpointContext 方法
资源管理器
enterprise bean

5.3.3. 服务实现 Bean 生命周期

服务实现 Bean 的生命周期由容器控制,如图 6 所示。容器调用的方法与容器/bean 有关,但一般来说是非常相似的。图 6 说明了 Web 容器中的生命周期。EJB 容器生命周期的描述可以在 [EJB] 规范的第 7.8.1 节中找到。

图 6. Web 容器中的服务实现 Bean 生命周期

Web 容器中的服务实现 Bean 生命周期

容器向 WSDL 端口所定义的请求提供服务。它通过为 WSDL 端口地址创建侦听器、接受请求并将请求分派到服务实现 Bean 上实现这一点。在能够服务于请求之前,容器必须实例化一个服务实现 Bean 并使之准备好接受方法请求。

容器准备 bean 实例的方法是:首先调用服务实现 Bean 类上的 newInstance 来创建实例。容器然后调用与容器有关的服务实现 Bean 上的生命周期方法。对 Web 容器来说,如果服务实现 Bean 类实现 ServiceLifecycle 接口,它就调用实例上的 init 方法。对 EJB 容器来说,它将调用 setSessionContextejbCreate 方法。

服务实现 Bean 实例没有标识。

容器可以对服务实现 Bean 的方法就绪(method ready)的实例进行池化,并将方法请求分派到处于方法就绪状态的任何实例上。

容器通过调用实例上特定于容器/bean 的生命周期方法来通知服务实现 Bean 实例它将被从方法就绪状态删除。对于 Web 容器来说将调用 destroy 方法。对于 EJB 容器来说将调用 ejbRemove 方法。

5.3.4. JAX-RPC 定制序列化程序/反序列化程序

JAX-RPC 定制序列化程序/反序列化程序的使用不在规范的这个版本的讨论之列。JAX-RPC 定制序列化程序/反序列化程序不能在 Web Services for J2EE 提供者之间移植,因此也不属于可移植部署单元的一部分。我们希望在 JAX-RPC 的将来版本解决该问题之前,提供商将为此问题提供专门的解决方案。

5.4. 打包

端口组件可以被打包为 WAR 文件或者 EJB JAR 文件。打包成 WAR 文件的端口组件必须使用服务实现 Bean 的 JAX-RPC 服务端点。打包成 EJB-JAR 文件的端口组件必须使用服务实现 Bean 的无状态会话 Bean。

开发者要负责通过容器或引用的方式,对 WSDL 文件、服务端点接口类、生成的服务实现类(如果使用了该类)、它们相关的类、JAX-RPC 映射文件以及 J2EE 模块中的 Web 服务客户机部署描述符进行打包。模块中 Web 服务客户机部署描述符的位置与特定模块有关。WSDL 文件位于模块根结构的相对位置,而且一般与模块的部署描述符位于同一位置。映射(Mapping)文件位于模块根结构的相对位置,而且一般与模块的部署描述符位于同一位置。

5.4.1. EJB 模块打包

无状态会话 EJB 服务实现 Bean 打包成包含类文件和 WSDL 文件的 EJB-JAR。打包规则遵循那些由 Enterprise JavaBean 规范定义的规则。另外,Web 服务部署描述符在 EJB-JAR 文件中的位置是 META-INF/webservices.xml

5.4.2. Web 应用程序模块打包

JAX-RPC 服务端点打包在包含类文件和 WSDL 文件的 WAR 文件中。WAR 文件的打包规则是由 Servlet 规范定义的。Web 服务部署描述符在 WAR 中位于 WEB-INF/webservices.xml。

5.4.3. EAR 文件中的装配

将包含端口组件的模块装配成 EAR 文件遵循 J2EE 规范定义的要求。

5.5. 事务

服务实现 Bean 的方法在特定于容器的事务上下文中运行。Web 容器在未指定的事务上下文中运行方法。EJB 容器在 EJB 部署描述符的 container-transaction 元素所定义的事务上下文中运行方法。

5.6. 容器提供者职责

除了上面所述的容器要求,容器提供者还必须提供 JAX-RPC 运行时。

如上所述,容器提供者要负责支持处理符合 JAX-RPC 的请求并支持调用端口。应用程序服务器必须支持对这些端口的部署。本规范规定了所有基于 XML 协议的 Web 服务绑定的 JAX-RPC Java 与 WSDL 之间和 Java 与 XML 之间的序列化框架。对于 JAX-RPC 入站消息来说,容器将充当 JAX-RPC 服务器端运行时。它负责:

  • 侦听公共端口或者 Web 服务实现的 URI(在部署后,在服务的 WSDL 中所定义),以获得 SOAP/HTTP 绑定。

  • 根据服务绑定解析入站消息。

  • 根据服务部署数据将消息映射到实现类和方法。

  • 根据 [JAX-RPC] 规范从 SOAP 信封创建合适的 Java 对象。

  • 用正确的 Java 参数调用服务实现 Bean 处理程序和实例方法。

  • 如果形式为请求-响应,那么就捕捉对调用的响应。

  • 根据 [JAX-RPC] 规范将 Java 响应对象映射到 SOAP 消息。

  • 创建适合传输的消息信封。

  • 将消息发送到源发请求的 Web 服务客户机。

6. 处理程序

本章定义了 Web Services for J2EE 的处理程序编程模型。处理程序定义了应用程序用以访问请求的原始 SOAP 消息的方法。这种访问在客户机和服务器上都有提供。处理程序不是 WSDL 规范的一部分,因此并不在其讨论范围之内。请参阅第 6.3 节 打包以了解部署描述符中的处理程序的说明。[JAX-RPC] 规范在第 12 章定义了处理程序 API。该规范定义了 J2EE 环境中的处理程序应用。

6.1. 概念

处理程序会让人联想到 Servlet 过滤程序,因为它是一种能够在 Web 服务组件处理请求之前检查并可能修改请求的业务逻辑。它还可以在组件处理请求之后,检查并可能修改响应。在请求被发送到远程主机之前和客户机收到响应之后,处理程序还可以在客户机上运行。

JAX-RPC 处理程序只特定于 SOAP 请求,不能被其它非 SOAP Web 服务使用。处理程序可以被独立传送。举例来说,JAX-RPC 定义的处理程序除了可以用于 SOAP/HTTP 之外,如果提供了 JMS 协议绑定,还可以用于 SOAP/JMS。非 SOAP 编码的处理程序还没有被定义。

处理程序是特定于服务的,因此与服务接口的特定 Port 组件或端口相关联。这种关联在第 7.1节 Web 服务部署描述符第 7.2 节 Web服务客户机部署描述符中分别描述。它们以一种称为 HandlerChain 的有序方式进行,这种方式由部署描述符定义。

您可以在几种情况下考虑使用处理程序。其中包括特定于应用程序的 SOAP 头处理、日志纪录和高速缓存。还可能使用一种有限的加密形势。对特定于应用程序的 SOAP 头处理来说,客户机和服务器必须在不需要说明语义需求的 WSDL 定义的帮助下在头处理语义上达成一致,这非常重要。加密仅限于文档/文字绑定,其中 SOAP 消息部分将映射到 SOAPElement。在种情况下,只要对值的加密不会改变 SOAPElement 的结构,SOAPElement 中的值就可以被加密。

本规范不支持 [JAX-RPC] 规范中描述的某些处理程序情况。举例来说,审计就无法被完全支持,因为没有办法让处理程序获取 Principal。安全股票报价示例就无法按规定支持,因为对主体加密将使容器不能决定请求应该被定向到哪个 Port 组件,也就不能决定哪个处理程序应该对主体加密。

处理程序总是在应用程序逻辑的执行上下文中运行。在客户机端,存根/代理控制处理程序执行。客户机端处理程序在存根/代理组织消息后运行,不过要在容器服务和传输绑定发生之前运行。服务器端处理程序在容器服务(包括方法级别授权)运行之后运行,但要在分解 SOAP 消息并将 SOAP 消息分派到端点之前运行。处理程序可以访问 java:comp/env 上下文,以访问与处理程序关联的 Port 组件定义的资源和环境条目。

处理程序受 J2EE 受管环境的约束。处理程序不能将请求重新定位到不同的组件上。处理程序不能改变 WSDL 操作,也不能改变消息部件类型和部件数。在服务器上,处理程序只能与使用 MessageContext 的组件的业务逻辑通信。在客户机上,处理程序无法与客户机的业务逻辑通信。处理程序没有标准的方法能够访问与请求关联的安全标识,因此处理程序不能可移植地根据安全标识执行处理。

处理程序的生命周期由容器控制。

处理程序与服务器上的 Port 组件相关联,因此在 Web 和 EJB 容器两者中运行。本规范将 EJB 容器中的处理程序支持定义为可选的是因为所需的 EJB 容器发生了变化,而它是实现处理程序支持所必需的。希望将来的 J2EE 规范能够将 EJB 处理程序支持定义为必需的。

6.2. 规范

这一节将定义在 Web Services for J2E 中运行的 JAX-RPC 处理程序的要求。[JAX-RPC] 规范的第 12 章定义了编程模型需要。本规范与 [JAX-RPC]规范之间的区别将在专门的段落中指出。

6.2.1. 适用情况

处理程序必须能够支持以下几种情况:

第 1 种情况:处理程序必须能够转换 SOAP 头。一个例子是用处理程序添加特定于应用程序的信息(如 customerID)的 SOAP 头。

第 2 种情况:处理程序必须能够只转换主体的部件。这可能包括改变 SOAP 主体中的部件值。这种情况的例子是对某些参数值的加密。

第 3 种情况:处理程序必须能够只读取消息,而不对消息进行添加、转换或修改。常用的情况有日志纪录、测量和记帐。

6.2.2. 编程模型

Web Services for J2EE 提供者需要提供下面的 javax.xml.rpc.handler 包的接口和类。

  • Handler

  • HandlerRegistry

  • MessageContext

  • GenericHandler

  • HandlerInfo

不需要提供 HandlerChain 接口。HandlerChain 的功能以特定于容器的方式提供。它不被应用程序代码使用。容器提供者不需要使用 HandlerChain 接口来实现链功能。

HandlerInfosetHandlerConfig()getHandlerConfig() 方法不影响容器的处理程序请求处理。

Web Services for J2EE 提供者需要提供 HandlerRegistry 的实现。该功能是特定于容器的。

Web Services for J2EE 提供者需要提供 MessageContext 的实现。

Web Services for J2EE 提供者需要提供 javax.xml.rpc.handler.soap 包的所有接口。提供者还必须提供 SOAPMessageContext 接口的实现。

按照第 5.3.2.1 节 EJB 容器编程模型第 5.3.2.2 节 Web 容器编程模型中所定义,Port 组件的编程模型可以是单线程的,也可以是多线程的。JAX-RPC 处理程序的并发性必须符合与其关联的业务逻辑的并发性。根据访问 Port 的不同业务逻辑,客户机处理程序可能需要支持多线程执行。

处理程序必须使用装入应用程序代码所使用的相同的类装入器来装入。类装入规则遵循为处理程序运行所在的容器定义的规则。

6.2.2.1 处理程序生命周期

处理程序的生命周期由容器控制,图 7 中说明了它。

图 7. 处理程序生命周期

处理程序生命周期

处理程序接口的 initdestroy 方法允许容器通知应用程序实例它的状态即将改变。处理程序可以使用这个通知来为它的内部状态过渡作准备。容器需要调用 initdestroy 方法,如下所述。

容器必须先调用 init 方法,然后才能够开始将请求分派给处理程序的 handleRequest()handleResponse()handleFault() 方法。处理程序可以使用容器通知来准备好它的内部状态,以接收请求。

容器必须通知处理程序它想调用 destroy 方法来从容器的工作集中删除该处理程序实例。在请求正在被处理程序实例处理时,容器绝对不可以调 destroy 方法。在调用了 destroy 方法之后,容器绝对不可以再分派额外的请求给处理程序接口的方法。

正如 JAX-RPC 所定义的,从处理程序的任何方法抛出的 RuntimeException(不是 SOAPFaultException)都会导致 destroy 方法被调用并且过渡到“Does Not Exist”状态。

池化处理程序实例是允许的,但不是必须的。如果处理程序实例被池化,那么用端口组件池化它们。这是因为处理程序可以跨方法调用(这些方法调用特定于端口组件)保持特定于非客户机的状态。举例来说,处理程序可能会用特定于端口组件的环境变量值来初始化内部数据成员。当单个处理程序类型与多个端口组件关联时,这些值可能会不一致。端口组件的处理程序的任何处于方法就绪状态的池化后的实例都可以用来为 handleRequest()handleResponse()handleFault() 方法服务。不要求同一个处理程序实例同时为任何给定请求的 handleRequest()handleResponse()handleFault() 方法调用服务。

6.2.2.2 安全性

与一个端口组件关联的多个处理程序在授权之后,服务实现 bean 的业务逻辑方法被分派出去之前运行。对于 JAX-RPC 服务端点,处理程序在容器执行完与定义端口组件的 servlet 元素相关联的安全性约束检查之后运行。对于基于 EJB 的服务实现,处理程序在发生了方法级的授权之后运行。

处理器绝对不可以以任何会导致先前执行过的授权检查以不同方式执行的方式更改消息。Handler.handleRequest() 绝对不可以更改操作名、消息中部件的数量或者消息部件的类型。如果处理程序做了这样的事,那么容器就必须将 java.rmi.MarshalExceptionjava.rmi.UnmarshalException 抛给客户机。尽管主要不是由于安全性原因,但 Handler.handleResponse() 方法绝对不可以更改消息中的部件数量或消息的部件类型。如果处理程序做了这样的事,那么容器就必须将 MarshalExceptionUnmarshalException 抛给客户机。由于客户机可能不期望得到响应(即可能是一个单向调用),所以容器应该记录这些错误的发生情况。

如果授权仅仅基于 MessageContext 和组件的环境变量值,那么处理程序可能会执行编程式授权检查。处理程序既不能执行基于角色的编程式授权检查,也不能访问与请求相关联的 Principal。

处理程序的 Java 2 安全性权限与运行该处理程序的容器所定义的权限相同。应用程序客户机、Web 和 EJB 容器可能具有不同的权限。如果提供者允许按每应用程序对权限进行定义,那么授予处理程序的权限由授予应用程序代码(该处理程序与这些代码包装在一起)的权限定义。请参阅 J2EE 1.3 规范的 J2EE.6.2.3 一节了解更多详情。

6.2.2.3 事务

处理程序在未特别指定的事务上下文中运行。

处理程序通常和与事务有关的 Servlet 过滤器满足相同的要求。处理程序绝对不可以使用 javax.transaction.UserTransaction 接口给事务划定界限。处理程序必须以本地事务模式使用事务资源,但不应该在任何对象的用来打包 MessageContext 的方法中使用事务资源。

6.2.3. 开发者职责

不要求开发者实现处理程序。处理程序是编写与处理 Web 服务请求有关的业务逻辑的另一种手段。一个开发者可以实现零个或多个与 Port 组件和/或服务引用相关联的处理程序。如果一个开发者实现了一个处理程序,则它们都必须满足本节所概述的要求。

处理程序作为无状态实例实现。在处理(handle)方法的多个调用之间,处理程序不在它的实例变量中维护任何与消息处理(特定于客户机的)有关的状态。

处理程序类必须实现 java.xml.rpc.handler.Handler 接口。

Handler.handleXXX() 方法可以使用“java:comp/env”上下文的 JNDI 查找,并且可以通过执行 JNDI 查找访问部署描述符中定义的 env-entry-names,这样便可以访问组件的环境实体。详情请参阅 [EJB] 规范的第 20 章。如果从任何其它处理程序方法访问环境并且环境不可用,那么容器就会抛出 java.lang.IllegalStateException。此外,处理程序可以使用 HandlerInfo.getHandlerConfig() 方法来访问处理程序的 init-params,init-params 在部署描述符中定义。

Handler.init() 方法必须保持 HandlerInfo.getHeaders() 所定义的信息。

处理程序实现必须实现 getHeaders() 方法以返回 HandlerInfo.getHeaders() 方法的结果。处理程序声明它将处理的头(即那些由 Handler.getHeaders() 方法返回的东西)必须在服务的 WSDL 定义中进行定义。

处理程序实现应该测试传递到处理程序的在 handle<action>() 方法中传递到处理程序的 MessageContext 的类型。尽管本规范只要求支持 SOAP 消息,并且容器在这种情况下将传递 SOAPMessageContext,但有些提供者可能会提供一些使其它消息类型和 MessageContext 类型可以被使用的扩展。处理程序实现应该为接受并忽略它不理解的消息类型做好准备。

处理程序实现必须使用 MessageContext 来把信息传递到同一条处理程序链中的其它处理程序实现,对于 JAX-RPC 服务端点的情况,则传递到服务实现 Bean。不要求容器使用同一个线程来调用每一个处理程序或调用 Service Implementation Bean。

处理程序可以访问完整的 SOAP 消息,并且如果 handle<action>() 方法传递了 SOAPMessageContext,则处理程序也可以处理 SOAP 头块和主体。

SOAPMessageContext 处理程序可以添加或删除 SOAP 消息的头。如果 SOAP 消息的头未被映射到参数上,或者如果 SOAP 消息的头被映射到了参数上,而所作的修改没有更改参数的值类型,那么 SOAPMessageContext 处理程序就会修改 SOAP 消息的头。如果所作的修改没有更改值类型,那么处理程序就会修改消息的部件值。

处理程序可以以本地事务模式访问事务资源。

定义特定于应用程序的头的处理程序应该在这些头所关联的组件的 WSDL 文档中声明头模式,但并不是必须这样做。

6.2.4. 容器提供者职责

处理程序链根据 [JAX-RPC] 规范的第 12.2.2 节进行处理。缺省的处理顺序为处理程序在部署描述符中定义的顺序,并符合 [JAX-RPC] 规范的第 12.1.4 节中的处理顺序。

要求容器提供 HandlerInfo 实例中的 java.util.Map 对象的实例。HandlerInfo.getHeaders() 方法必须返回部署描述符中定义的 soap-headers 的设置。Map 对象必须提供对处理程序的各个 init-param 名称/值对的访问,这些名称/值对在部署描述符中被声明为 java.lang.String 值。容器必须为每一个处理程序实例提供唯一的 HandlerInfo 实例和映射配置(Map config)实例。必须为部署描述符中声明的每一个端口组件提供一个唯一的处理程序实例。

容器必须在端口组件的环境的上下文中调用 init() 方法。容器必须确保端口组件的 env-entrys 被设置为供 init 方法访问。

容器必须提供请求类型独有的 MessageContext 类型。例如,在处理 SOAP 请求时,容器必须给处理程序链中的处理程序的 handle<action>() 方法提供一个 SOAPMessageContext。这个 SOAPMessageContext 必须包含完整的 SOAP 消息。

容器必须跨所有处理程序实例和在单个请求和响应或在特定节点上进行的故障处理期间被调用的目标端点共享同一个 MessageContext 实例。

容器在调用处理程序链的 handle<action>() 方法之前必须设置端口组件的执行环境。各个处理程序在同一个执行环境下作为端口组件的业务方法运行。需要这样做处理程序才能够访问端口组件的 java:comp/env 上下文。

不要求容器提供者支持在 EJB 容器中运行的端口组件的处理程序。人们期望当本规范被包含到 J2EE 1.4 中时,会要求这一点。

6.3. 打包

要求开发者,通过容纳或引用,将处理程序类及其依赖类和引用这些处理程序类的部署描述符信息一起打包到模块中。开发者负责在部署描述符中定义处理程序类链信息。

6.4. 对象交互图

本节包含处理程序进行处理过程的对象交互图。一般来说,交互图是图解性的。

6.4.1. 客户机 Web 服务方法访问

图 8. 客户机方法调用处理程序对象交互图

客户机方法调用处理程序对象交互图

7. 部署描述符

本章描述各种用于 Web Services for J2EE 的部署描述符以及负责定义部署描述符中的信息的角色。

7.1. Web 服务部署描述符

这一节定义 webservices.xml 文件的内容、模块内的位置、角色和职责以及格式。

7.1.1. 概述

webservices.xml 部署描述符文件定义了将部署到启用了 Web Services for J2EE 的容器中的 Web 服务集合。webservices.xml 部署描述符文件的打包在第 5.4.1 节 EJB 模块打包第 5.4.2 节 Web 应用程序模块打包中定义。按照第 3.2 节 Web 服务中所描述,Web 服务是由 WSDL 文档所定义的。部署描述符定义了 WSDL 端口与端口组件之间的关系。端口组件在第 5 章 服务器编程模型中定义。

7.1.2. 开发者职责

开发者不但要负责 Web 服务的实现,还要负责声明其部署特征。部署特征在特定于模块的部署描述符以及 webservices.xml 部署描述符两者中定义。使用无状态会话 bean 的服务实现必须使用 session 元素在 ejb-jar.xml 部署描述符中定义。使用 JAX-RPC 服务端点的服务实现必须使用 servlet-class 元素在 web.xml 部署描述符中定义。请参阅 [EJB] 和 Servlet 2.3 规范以了解其它关于开发者对定义部署描述符的要求的详细内容。开发者还需要提供在 webservices.xml 部署描述符文件中定义端口组件的结构信息。开发者负责提供描述将部署的 Web 服务的 WSDL 文档集合、表示 Web 服务的 Java 类以及在两者之间建立关系的映射。

开发者负责在 webservices.xml 部署描述符中提供下面的信息:

  • 端口的名称。开发者必须使用端口-组件-名称(port-component-name)元素为端口指定逻辑名称。这个名称与 WSDL 端口名称没有任何关系。这个名称在模块中的所有端口组件名称中必须是唯一的。

  • 端口的 bean 类。开发者使用部署描述符的 service-impl-bean 元素声明 Web 服务的实现。这个元素中声明的 bean 指的必须是实现端口的服务端点接口的方法。这个元素使您可以选择实现。对于 JAX-RPC 服务端点来说,servlet-link 元素将 port-component 关联到 Web.xml 中 servlet-class 元素定义的 JAX-RPC 服务端点类。对于无状态会话 bean 实现来说,ejb-link 元素将 port-component 关联到 ejb-jar.xml 中的一个 session 元素。ejb-link 元素所指的可能不是另一个模块中定义的 session 元素。

  • 端口的服务端点接口。开发者必须在 service-endpoint-interface 中指定服务端点接口的完全限定类名。您可以在第 5.3.1 节 服务端点接口中找到服务端点接口要求。

  • 端口的 WSDL 定义。wsdl-file 元素指定一组 Web 服务的 WSDL 描述的位置。它位于模块根结构的相对位置,而且必须由开发者指定。

  • 端口的 QName。除了指定 WSDL 文档之外,开发者还必须在 wsdl-port 元素中为部署描述符中定义的每个端口指定 WSDL 端口 QName。

  • JAX-RPC 映射。开发者必须使用 jaxrpc-mapping-file 元素指定 WSDL 定义与接口之间的相关性。第 7.3. 节 JAX-RPC 映射部署描述符中讨论了在 jaxrpc-mapping-file 中指定信息的要求。对于和一个 wsdl-file 关联的所有接口必须使用同一个映射文件。

  • 处理程序。开发者可以选择使用 handler 元素指定与 port-component 关联的处理程序。

请注意,如果 WSDL 在端口中指定了地址语句,它的 URI 地址就会被忽略。这个地址是在部署期间在部署的 WSDL 中生成并被取代的。

还是请参阅第 7.2.2 节 开发者职责中定义的开发者要求。

7.1.3. 装配者职责

Web Services for J2EE 的装配者的职责是在 [EJB]、Servlet 2.3 和 J2EE 1.3 规范定义的装配者职责上进行了扩展。装配者通过组成多个模块、分析模块间的依赖性并生成 EAR 文件,从而创建一个可部署的构件。

装配者可以修改下面由开发者在 webservices.xml 部署描述符文件中指定的任何信息:

  • 描述字段。装配者可以修改已有的或创建新的 description 元素。

  • 处理程序。装配者可以改变已有 param-value 元素的值、可以改变或添加 init-param 元素、可以改变或添加 soap-header 元素或添加 soap-role 元素,也可以添加新的处理程序元素(handler elements)。

还请参阅第 7.1.3 节 装配者职责中定义的装配者职责。

7.1.4. 部署者职责

部署者的职责是由 J2EE 1.3、[EJB] 以及 Servlet 2.3 规范所定义的。

另外,部署者必须分析下面的信息:

  • 发布后的 WSDL 定义在什么位置。部署者必须用正确的端口地址属性值发布每个 webservice-description wsdl-file 以访问服务。

  • 部署后的服务的端口地址属性值。

7.1.5. Web 服务部署描述符 DTD

下面是 Web 服务部署描述符的 DTD:

<!-- Last updated: 08/21/2002 11:30
All Web service deployment descriptors must use the following delcaration:
<!DOCTYPE webservices PUBLIC "-//IBM Corporation, Inc.//DTD J2EE Web services 1.0//EN"
 "http://www.ibm.com/standards/xml/webservices/j2ee/j2ee_Web_services_1_0.dtd">
-->

<!--
The webservices element is the root element for the Web services
deployment descriptor.  It specifies the set of Web service descriptions
that are to be deployed into the J2EE Application Server and the 
dependencies they have on container resources and services.

Used in: webservices.xml
-->
<!ELEMENT webservices (description?, display-name?, small-icon?, 
	large-icon?, webservice-description+) >

<!--
The description element is used by the module producer to provide
text describing the parent element.

The description element should include any information that the
module producer wants to provide to the consumer of the module 
(i.e. to the Deployer). Typically, the tools used by the module 
consumer will display the description when processing the parent 
element that contains the description.

Used in: port-component, webservice-description, webservices
-->
<!ELEMENT description (#PCDATA)>

<!--
The display-name element contains a short name that is intended to be
displayed by tools. The display name need not be unique.

Used in: port-component, webservice-description and webservices

Example:
	<display-name>Employee Self Service</display-name>
-->
<!ELEMENT display-name (#PCDATA)>

<!--
The ejb-link element is used in the service-impl-bean element
to specify that a Service Implementation Bean is defined as a Web
Service Endpoint.

The value of the ejb-link element must be the ejb-name of an enterprise
bean in the same ejb-jar file.

Used in: service-impl-bean

Examples:
	<ejb-link>EmployeeRecord</ejb-link>
	<ejb-link>../products/product.jar#ProductEJB</ejb-link>
-->
<!ELEMENT ejb-link (#PCDATA)>

<!--
Declares the handler for a port-component. Handlers can access the
init-param name/value pairs using the HandlerInfo interface.

Used in: port-component
-->
<!ELEMENT handler (description?, display-name?, small-icon?, 
	large-icon?, handler-name, handler-class, init-param*, 
	soap-header*, soap-role*)>

<!--
Defines the name of the handler. The name must be unique within the
module.
-->
<!ELEMENT handler-name (#PCDATA)>

<!--
Defines a fully qualified class name for the handler implementation.
-->
<!ELEMENT handler-class (#PCDATA)>

<!--
The init-param element contains a name/value pair as an
initialization param of the servlet
Used in: filter, servlet
-->
<!ELEMENT init-param (param-name, param-value, 
	description?)>

<!--
The jaxrpc-mapping-file element contains the name of a file that
describes the JAX-RPC mapping between the Java interaces used by
the application and the WSDL description in the wsdl-file.  The 
file name is a relative path within the module.

Used in: webservice-description
-->
<!ELEMENT jaxrpc-mapping-file (#PCDATA)>

<!--
The localpart element indicates the local part of a QNAME.

Used in: soap-header, wsdl-port
-->
<!ELEMENT localpart (#PCDATA)>

<!--
The namespaceURI element indicates a URI.

Used in: soap-header, wsdl-port
-->
<!ELEMENT namespaceURI (#PCDATA)>

<!--
The param-name element contains the name of a parameter. Each
parameter name must be unique in the Web application.
Used in: context-param, init-param
-->
<!ELEMENT param-name (#PCDATA)>

<!--
The param-value element contains the value of a parameter.
Used in: context-param, init-param
-->
<!ELEMENT param-value (#PCDATA)>

<!--
The large-icon element contains the name of a file containing a large
(32 x 32) icon image. The file name is relative path within the
ejb-jar file.

The image must be either in the JPEG or GIF format.
The icon can be used by tools.

Example:
	<large-icon>employee-service-icon32x32.jpg</large-icon>
-->
<!ELEMENT large-icon (#PCDATA)>

<!--
The port-component element associates a WSDL port with a Web service
interface and implementation.  It defines the name of
the port as a component, optional description, optional display 
name, optional iconic representations, WSDL port QName, Service 
Endpoint Interface, Service Implementation Bean.

Used in: webservices
-->
<!ELEMENT port-component (description?, display-name?, small-icon?, 
	large-icon?, port-component-name, wsdl-port, 
	service-endpoint-interface, service-impl-bean, handler*)>

<!--
The port-component-name element specifies a port component's name. 
This name is assigned by the module producer to name the service 
implementation bean inthe module's deployment descriptor. The name 
must be unique among the port component names defined in the same 
module.

Used in: port-component

Example:
	<port-component-name>EmployeeService</port-component-name>
-->
<!ELEMENT port-component-name (#PCDATA)>

<!--
The service-endpoint-interface element contains the fully-qualified 
name of the port component's Service Endpoint Interface.

Used in: port-component

Example:
	<remote>com.wombat.empl.EmployeeService</remote>
-->
<!ELEMENT service-endpoint-interface (#PCDATA)>

<!--
The service-impl-bean element defines the Web service implementation.
A service implementation can be an EJB bean class or JAX-RPC Web 
component.  Existing EJB implementations are exposed as a Web service
using an ejb-link.

Used in: port-component
-->
<!ELEMENT service-impl-bean (ejb-link | servlet-link)>

<!--
The servlet-link element is used in the service-impl-bean element
to specify that a Service Implementation Bean is defined as a 
JAX-RPC Service Endpoint.

The value of the servlet-link element must be the servlet-name of 
a JAX-RPC Service Endpoint in the same WAR file.

Used in: service-impl-bean

Example:
	<servlet-link>StockQuoteService</servlet-link>
-->
<!ELEMENT servlet-link (#PCDATA)>

<!--
The small-icon element contains the name of a file containing a small
(16 x 16) icon image. The file name is relative path within the
ejb-jar file.

The image must be either in the JPEG or GIF format.
The icon can be used by tools.

Example:
	<small-icon>employee-service-icon16x16.jpg</small-icon>
-->
<!ELEMENT small-icon (#PCDATA)>

<!--
Defines the QName of a SOAP header that will be processed by the
handler.
-->
<!ELEMENT soap-header (namespaceURI, localpart)>

<!--
The soap-role element contains a SOAP actor definition that the
Handler will play as a role.
-->
<!ELEMENT soap-role (#PCDATA)>

<!--
The webservice-description element defines a WSDL document file 
and the set of Port components associated with the WSDL ports 
defined in the WSDL document.  There may be multiple 
webservice-descriptions defined within a module.

All WSDL file ports must have a corresponding port-component element
defined.

Used in: webservices
-->
<!ELEMENT webservice-description (description?, display-name?, 
	small-icon?, large-icon?, webservice-description-name, wsdl-file, 
	jaxrpc-mapping-file, port-component+)>

<!--
The webservice-description-name identifies the collection of 
port-components associated with a WSDL file and JAX-RPC mapping. The
name must be unique within the deployment descriptor.

Used in: webservice-description
-->
<!ELEMENT webservice-description-name (#PCDATA)>

<!--
The wsdl-file element contains the name of a WSDL file in the module.
The file name is a relative path within the module.
-->
<!ELEMENT wsdl-file (#PCDATA)>

<!--
Defines the name space and local name part of the WSDL port QName.
-->
<!ELEMENT wsdl-port (namespaceURI, localpart)>

<!--
The ID mechanism is to allow tools that produce additional deployment
information (i.e., information beyond the standard EJB deployment
descriptor information) to store the non-standard information in a
separate file, and easily refer from these tools-specific files to the
information in the standard deployment descriptor.
The EJB architecture does not allow the tools to add the non-standard
information into the EJB deployment descriptor.
-->
<!ATTLIST description id ID #IMPLIED>
<!ATTLIST display-name id ID #IMPLIED>
<!ATTLIST ejb-link id ID #IMPLIED>
<!ATTLIST handler id ID #IMPLIED>
<!ATTLIST handler-class id ID #IMPLIED>
<!ATTLIST handler-name id ID #IMPLIED>
<!ATTLIST init-param id ID #IMPLIED>
<!ATTLIST jaxrpc-mapping-file id ID #IMPLIED>
<!ATTLIST large-icon id ID #IMPLIED>
<!ATTLIST localpart id ID #IMPLIED>
<!ATTLIST namespaceURI id ID #IMPLIED>
<!ATTLIST param-name id ID #IMPLIED>
<!ATTLIST param-value id ID #IMPLIED>
<!ATTLIST port-component id ID #IMPLIED>
<!ATTLIST port-component-name id ID #IMPLIED>
<!ATTLIST service-endpoint-interface id ID #IMPLIED>
<!ATTLIST service-impl-bean id ID #IMPLIED>
<!ATTLIST servlet-link id ID #IMPLIED>
<!ATTLIST small-icon id ID #IMPLIED>
<!ATTLIST soap-header id ID #IMPLIED>
<!ATTLIST soap-role id ID #IMPLIED>
<!ATTLIST webservices id ID #IMPLIED>
<!ATTLIST webservice-description id ID #IMPLIED>
<!ATTLIST webservice-description-name id ID #IMPLIED>
<!ATTLIST wsdl-file id ID #IMPLIED>
<!ATTLIST wsdl-port id ID #IMPLIED>
			

7.2. Web 服务客户机部署描述符

这一节定义 webservicesclient.xml 文件的功能、模块内的位置、角色和职责以及格式。

7.2.1. 概述

webservicesclient.xml 部署描述符包含服务引用条目。这些条目声明 Web、EJB 或应用程序客户机容器中 J2EE 组件所使用的对 Web 服务的引用。如果 Web 服务客户机为 J2EE 组件,那么它就使用 Web 服务的逻辑名称(称为服务引用)来查找服务。任何使用 Web 服务引用的组件都必须在 webservicesclient.xml 部署描述符文件中声明 Web 服务引用的相关性。webservicesclient.xml 文件与模块的部署描述符打包在同一个目录下。至于 WAR 模块,它打包在 WEB-INF 目录中。而 EJB JAR 和应用程序客户机模块则打包在 META-INF 目录下。

7.2.2. 开发者职责

开发者要负责为模块内的组件希望引用的每个 Web 服务定义一个 service-ref。它包括下面的信息:

  • 服务引用名。它为客户机源代码中使用的引用定义了逻辑名称。我们推荐让名称以 service/ 开头,但不是必需的。

  • 服务类型:service-interface 元素定义了 JNDI 查找返回的 JAX-RPC 服务接口类的完全限定名。

  • 端口。开发者使用 port-component-ref 元素为容器受管的端口解析声明要求。port-component-ref 元素将被容器解析为 WSDL 端口。请参阅第 4 章 客户机编程模型,那里有一个关于容器受管端口访问的讨论。

  • 作用域。如果 EJB-JAR 中定义了服务引用,那么 service-ref 元素就必须在 component-scoped-refs 元素中定义,这样 service-ref 才能够与特定的 EJB 关联。与 EJB 的关联是由 component-name 元素定义的。

开发者指定下面的信息:

  • WSDL 定义。wsdl-file 元素服务的 WSDL 描述的位置。它位于模块根结构的相对位置。WSDL 描述可能是部分的 WSDL,但必须至少包括 portType 和 binding 元素。开发者所提供的 WSDL 描述可以被视为必须由装配/部署过程保留的模板。换句话说,WSDL 描述包含应用程序与端口类型、绑定和 QName 的相关性的声明。如果应用程序依赖于端口 QName(例如使用 Service.getPort(QName,Class) 方法),WSDL 文档就必须被完全指定,包括服务和端口元素。如果使用了第 4 .2.2.4 节或第 4.2.2.5 节中声明的任何服务方法,开发者就必须指定 wsdl-file

  • 服务端口。如果指定的 wsdl-file 有不止一个 service 元素,开发者就必须指定 service-qname

  • JAX-RPC 映射。开发者通过使用 jaxrpc-mapping-file 元素指定 WSDL 定义到接口的关系。它位于模块根结构的相对位置。对于和一个 wsdl-file 关联的所有接口必须使用同一个映射文件。如果指定了 wsdl-file,那么开发者必须指定 jaxrpc-mapping-file

  • 处理程序。开发者可以选择使用 handler 元素指定与 service-ref 关联的处理程序。

7.2.3. 装配者职责

除了 J2EE 1.3 规范中定义的职责之外,装配者还可以定义下面的信息:

  • 服务引用的绑定。 装配者可以使用 port-component-link 元素将 Web 服务引用链接到 J2EE 应用程序单元中的组件。

装配者可以修改下面由开发者在 webservicesclient.xml 部署描述符中指定的任何信息:

  • 描述字段。 装配者可以修改已有的或创建新的 description 元素。

  • 处理程序。装配者可以改变已有 param-value 元素的值、可以添加新的 init-param 元素、可以改变或添加 soap-header 元素、可以改变或添加 soap-role 元素,也可以添加新的 handler 元素。

  • WSDL 定义。装配者可以用一个新的 WSDL(它将找回丢失的服务和端口元素或丢失的端口地址属性)来代替已有的 WSDL 定义。装配者可以更新端口地址属性。

7.2.4. 部署者职责

除了担负 J2EE 部署者平台角色的普通任务之外,部署者还必须提供部署时绑定信息来为每个 service-ref 解析 WSDL 文档。

7.2.5. webservicesclient.xml DTD

webservicesclient.xml 部署描述符的 DTD:

<!-- Last updated: 08/21/2002 11:30
All Web service client deployment descriptors must use the following 
declaration:

<!DOCTYPE webservicesclient PUBLIC 
"-//IBM Corporation, Inc.//DTD J2EE Web services client 1.0//EN" 
"http://www.ibm.com/standards/xml/webservices/j2ee/j2ee_Web_services_client_1_0.dtd">
-->

<!--
The webservicesclient element is the top level element for service
references.
-->
<!ELEMENT webservicesclient (service-ref+|component-scoped-refs+)>

<!--
The component-name element defines a link to a component name such
as the ejb-name in the module deployment descriptor.  It's value
must exist in the module level deployment descriptor.

Used in: component-scoped-refs
-->
<!ELEMENT component-name (#PCDATA)>

<!--
The component-scoped-refs element defines service references that
are scoped to a particular component of a module.  Not all modules
support component scoping.

Used in: webservicesclient
-->
<!ELEMENT component-scoped-refs (component-name, service-ref+)>

<!--
The description element gives the deployer a textual description 
of the Web service. 

Used in: service-ref
-->
<!ELEMENT description (#PCDATA)>

<!--
The display-name element contains a short name that is intended to be
displayed by tools. The display name need not be unique.

Used in: port-component and webservices

Example:
	<display-name>Employee Self Service</display-name>
-->
<!ELEMENT display-name (#PCDATA)>

<!--
Declares the handler for a port-component. Handlers can access the
init-param name/value pairs using the HandlerInfo interface. If 
port-name is not specified, the handler is assumed to be associated
with all ports of the service.

Used in: service-ref
-->
<!ELEMENT handler (description?, display-name?, small-icon?, 
	large-icon?, handler-name, handler-class, init-param*, 
	soap-header*, soap-role*, port-name*)>

<!--
Defines a fully qualified class name for the handler implementation.
-->
<!ELEMENT handler-class (#PCDATA)>

<!--
Defines the name of the handler. The name must be unique within the
module.
-->
<!ELEMENT handler-name (#PCDATA)>

<!--
The init-param element contains a name/value pair as an
initialization param of the handler.

Used in: handler
-->
<!ELEMENT init-param (param-name, param-value, 
	description?)>

<!--
The jaxrpc-mapping-file element contains the name of a file that
describes the JAX-RPC mapping between the Java interaces used by
the application and the WSDL description in the wsdl-file.  The 
file name is a relative path within the module file.

Used in: webservice-description
-->
<!ELEMENT jaxrpc-mapping-file (#PCDATA)>

<!--
The large-icon element contains the name of a file containing a large
(32 x 32) icon image. The file name is relative path within the
module file.

The image must be either in the JPEG or GIF format.
The icon can be used by tools.

Example:
	<large-icon>employee-service-icon32x32.jpg</large-icon>
-->
<!ELEMENT large-icon (#PCDATA)>

<!--
The localpart element indicates the local part of a QNAME.

Used in: service-qname, soap-header
-->
<!ELEMENT localpart (#PCDATA)>

<!--
The namespaceURI element indicates a URI.

Used in: service-qname, soap-header
-->
<!ELEMENT namespaceURI (#PCDATA)>

<!--
The param-name element contains the name of a parameter. Each
parameter name must be unique in the Web application.

Used in: context-param, init-param
-->
<!ELEMENT param-name (#PCDATA)>

<!--
The param-value element contains the value of a parameter.

Used in: context-param, init-param
-->
<!ELEMENT param-value (#PCDATA)>

<!--
The port-component-link element links a port-component-ref to a 
specific port-component required to be made available by a service 
reference.

The value of a port-component-link must be the port-component-name
of a port-component in the same module or another module in the same
application unit. The syntax for specification follows the syntax
defined for ejb-link in the EJB 2.0 specification.

Used in: port-component-ref
-->
<!ELEMENT port-component-link (#PCDATA)>

<!--
The port-component-ref element declares a client dependency
on the container for resolving a Service Endpoint Interface
to a WSDL port. It optionally associates the Service Endpoint
Interface with a particular port-component. This is only used
by the container for a Service.getPort(Class) method call.

Used in: service-ref
-->
<!ELEMENT port-component-ref (service-endpoint-interface, 
	port-component-link?)>

<!--
The port-name element defines the WSDL port-name that a handler
should be associated with.
-->
<!ELEMENT port-name (#PCDATA)>

<!--
The service-endpoint-interface element defines a fully qualified
Java class that represents the Service Endpoint Interface of a
WSDL port.

Used in: service-ref
-->
<!ELEMENT service-endpoint-interface (#PCDATA)>

<!--
The service-interface element declares the fully qualified class 
name of the JAX-RPC Service interface the client depends on. 
In most cases the value will be javax.xml.rpc.Service.  A JAX-RPC
generated Service Interface class may also be specified.

Used in: services-ref
-->
<!ELEMENT service-interface (#PCDATA)>

<!-- The service-qname element declares the specific WSDL service
element that is being refered to.  It is not specified if no
wsdl-file is declared.

Used in service-ref
-->
<!ELEMENT service-qname (namespaceURI, localpart)>

<!-- The service-ref element declares a reference to a Web
service. It contains optional description, display name and
icons, a declaration of the required Service interface,
an optional WSDL document location, an optional set
of JAX-RPC mappings, an optional QName for the service element,
an optional set of Service Endpoint Interfaces to be resolved 
by the container to a WSDL port, and an optional set of handlers.

Used in: webservicesclient.xml 
-->
<!ELEMENT service-ref (description?, display-name?, small-icon?,
	large-icon?, service-ref-name, 	service-interface, wsdl-file?, 
	jaxrpc-mapping-file?, service-qname?, port-component-ref*, 
	handler*)>
	
<!--
The service-ref-name element declares logical name that the
components in the module use to look up the Web service. It 
is recommended that all service reference names start with 
"service/".

Used in: services-ref
-->
<!ELEMENT service-ref-name (#PCDATA)>

<!--
The small-icon element contains the name of a file containing a small
(16 x 16) icon image. The file name is relative path within the
module file.

The image must be either in the JPEG or GIF format.
The icon can be used by tools.

Example:
	<small-icon>employee-service-icon16x16.jpg</small-icon>
-->
<!ELEMENT small-icon (#PCDATA)>

<!--
Defines the QName of a SOAP header that will be processed by the
handler.
-->
<!ELEMENT soap-header (namespaceURI, localpart)>

<!--
The soap-role element contains a SOAP actor definition that the
Handler will play as a role.
-->
<!ELEMENT soap-role (#PCDATA)>

<!--
The wsdl-file element contains the URI location of a WSDL file. The
location is relative to the root of the module.

Used in: service-ref
-->
<!ELEMENT wsdl-file (#PCDATA)>

<!ATTLIST component-name id ID #IMPLIED>
<!ATTLIST component-scoped-refs id ID #IMPLIED>
<!ATTLIST description id ID #IMPLIED>
<!ATTLIST display-name id ID #IMPLIED>
<!ATTLIST handler id ID #IMPLIED>
<!ATTLIST handler-class id ID #IMPLIED>
<!ATTLIST handler-name id ID #IMPLIED>
<!ATTLIST init-param id ID #IMPLIED>
<!ATTLIST jaxrpc-mapping-file id ID #IMPLIED>
<!ATTLIST large-icon id ID #IMPLIED>
<!ATTLIST localpart id ID #IMPLIED>
<!ATTLIST namespaceURI id ID #IMPLIED>
<!ATTLIST param-name id ID #IMPLIED>
<!ATTLIST param-value id ID #IMPLIED>
<!ATTLIST port-component-link id ID #IMPLIED>
<!ATTLIST port-component-ref id ID #IMPLIED>
<!ATTLIST port-name id ID #IMPLIED>
<!ATTLIST service-endpoint-interface id ID #IMPLIED>
<!ATTLIST service-interface id ID #IMPLIED>
<!ATTLIST service-qname id ID #IMPLIED>
<!ATTLIST service-ref id ID #IMPLIED>
<!ATTLIST service-ref-name id ID #IMPLIED>
<!ATTLIST small-icon id ID #IMPLIED>
<!ATTLIST soap-header id ID #IMPLIED>
<!ATTLIST soap-role id ID #IMPLIED>
<!ATTLIST webservicesclient id ID #IMPLIED>
<!ATTLIST wsdl-file id ID #IMPLIED>
			

7.3. JAX-RPC 映射部署描述符

7.3.1. 概述

JAX-RPC 映射部署描述符没有标准的文件名。模块中的 WSDL 文档和映射文件具有一一对应关系。JAX-RPC 映射部署描述符包含在 Java 接口和 WSDL 定义之间建立映射关系的信息。部署工具使用该信息,结合 WSDL 文件生成部署的服务和服务引用的存根和 TIE。

7.3.2. 开发者职责

开发者在 WSDL 和/或 Java 接口被创建的同时创建映射文件。如果满足了下面的条件,开发者就可以仅指定打包映射。

  • WSDL 文件必须包含正好一个 service 元素。

  • service 元素必须定义正好一个端口。

  • service 名称、binding 名称、portType 名称以及所有根 WSDL 类型(例如 complexTypesimpleType 等)名称都必须是唯一的。

  • port's binding 必须是 style="rpc" 的 soap 1.1 绑定;它的所有操作都必须指定 use="encoded", encodingStyle="<the SOAP 1.1 encoding>" 作为输入、输出和错误消息,而且要么省略部件属性,要么包括部件属性,总之要让输入和输出消息的所有部件都映射到 soap 主体。而且,绑定中不能指定任何 soap 头或头错误。

  • 每个 operation 都必须:

    • 有遵循 Java 方法名称约定的唯一名称(在它所属的端口类型上下文中)。

    • 正好有一条输入消息。

    • 最多有一条输出消息。

    • 有零条或多条 fault 消息。

    • 要么没有 parameterOrder 属性,要么该属性的值为输入消息中所有部件的完整清单,顺序为输入消息中出现的顺序。

  • 错误必须被映射到异常上,使得它:

    • 直接或间接地从 java.lang.Exception 继承,但决不能从 RuntimeException 继承,也不能从 RemoteException 继承。

    • 最多有一个单独属性名为“message”,类型为 java.lang.String,带有对应的单个 String 参数的构造函数。

    • 必须是 SOAP 编码的。

  • 每条输入消息都必须有零或多个部件。

  • 每条输入消息都必须有零或一个部分。如果有,部件的名称必须有别于输入消息中的任何部件。

  • 每个部件必须是下面这种形式:

    <part name="..." type="T"/>

  • 每种类型 T 都必须是下面的有效类型之一:

    • [JAX-RPC] 规范的第 4.2.1 节的表 4-1 中所定义的简单类型。

    • 使用 sequence 组合器的复杂类型:

                <xsd:complexType name="T">
                   <xsd:sequence>
                          <xsd:element name="..." type="Tprime"/>
                   </xsd:sequence>
                </xsd:complexType>
      					

      或使用 all 组合器的复杂类型:

                <xsd:complexType name="T">
                   <xsd:all>
                          <xsd:element name="..." type="Tprime"/>
                   </xsd:all>
                </xsd:complexType>
      					

      不管哪种情况,元素声明都可以出现一次或多次,而且每个 Tprime 类型都必须有效。所有的元素名被映射为 JavaBean 属性,element 名遵循标准 JavaBean 属性命名约定,第一个字母小写,而 complexType 名遵循 Java 标准类名称约定,第一个字母大写。

    • 遵循这种形式的一个 SOAP 数组:

                <xsd:complexType name="...">
                   <xsd:restriction base="soapenc:Array"/>
                          <xsd:attribute ref="soapenc:arrayType"
                                 wsdl:arrayType="Tprime[]"/>
                   </xsd:restriction>
                </xsd:complexType>
      					

      其中 Tprime 为有效类型,而且不是 SOAP 数组类型。

如果条件不满足,那么就必须指定完整的映射。对于每个根 WSDL 类型必须有一个 java-xml-type-mapping。必须为每个 WSDL 错误创建一个 exception-mapping。对于在具有开发者所使用的生成的服务接口的 WSDL 文件中的每个 service 元素,都必须有一个 service-interface-mapping。WSDL 文件中的端口类型和绑定的每个结合都必须有一个 service-endpoint-interface-mapping。WSDL 中定义的每个名称空间都必须有一个 package-mapping

不管 WSDL 内容是什么,Web Services for J2EE 提供者都可以通过使用标准的 JAX-RPC WSDL 到 Java 的映射规则来解析映射,从而支持部件映射规范(例如不为每种方法提供 method-param-parts-mapping)。如果映射是指定的,它们优先于映射规则。这种部分映射是特定于供应商的,因此不能够被移植。

开发者必须定义 webservices.xml 或 webservicesclient.xml 部署描述符的 jaxrpc-mapping-file 元素,作为映射文件的位置。

开发者必须把映射文件和 WSDL 文件一起打包在模块中。

7.3.3. 装配者职责

装配者决不能改变 JAX-RPC 映射文件。

7.3.4. 部署者职责

部署者使用部署工具来部署模块中包含的服务和服务引用。部署工具必须使用 JAX-RPC 映射文件来为服务和服务引用生成存根和 TIE。

7.3.5. JAX-RPC 映射 DTD

<!-- Last updated: 08/21/2002 11:30
All Web service deployment descriptors must use the following delcaration:
<!DOCTYPE java-wsdl-mapping PUBLIC 
"-//IBM Corporation, Inc.//DTD J2EE JAX-RPC mapping 1.0//EN"
 "http://www.ibm.com/standards/xml/webservices/j2ee/j2ee_jaxrpc_mapping_1_0.dtd">
-->

<!--
The element describes the Java mapping to a known WSDL document.

It contains the mapping between package names and XML namespaces, 
WSDL root types and Java artifacts, and the set of mappings for 
services.

-->
<!ELEMENT java-wsdl-mapping (package-mapping+,
	java-xml-type-mapping*, exception-mapping*,
	(service-interface-mapping?,
	service-endpoint-interface-mapping+)*)>

<!-- 
The class-type element is the fully qualified class name of
a Java class.

Used in: java-xml-type-mapping
-->
<!ELEMENT class-type (#PCDATA)>

<!--
The constructor-parameter-order element defines the order
that complexType element values are applied to a Java 
exception constructor. Element names are specified for each
parameter of the constructor, including element names of
inherited types if necessary.

Used in: exception-mapping
-->
<!ELEMENT constructor-parameter-order (element-name+)>

<!--
The data-member element is a boolean indicator that a Java
variable is a public data member and not a JavaBeans property.

Used in: variable-mapping
-->
<!ELEMENT data-member EMPTY>

<!--
The element-name element defines the name of a complexType
element name attribute value.

Used in: constructor-parameter-order
-->
<!ELEMENT element-name (#PCDATA)>

<!--
The exception-mapping element defines the mapping between the
service specific exception types and the wsdl faults.

This element should be interpreted with respect to the
mapping between a method and an operation which provides the
mapping context.

Used in: service-endpoint-method-mapping
-->
<!ELEMENT exception-mapping (exception-type, wsdl-message,
	constructor-parameter-order?)>

<!--
The exception-type element defines Java type of the exception. 
It may be a service specific exception.

It must be a fully qualified class name.

Used in: exception-mapping
-->
<!ELEMENT exception-type (#PCDATA)>

<!--
The java-method-name element defines the name of a Java method within
an interface.

Used in: service-endpoint-method-mapping
-->
<!ELEMENT java-method-name (#PCDATA)>

<!--
The java-port-name element is the string to use as the port name in
Java.  It is used in generating the Generated Service Interface method
get<java-port-name>.

Used in: port-mapping
-->
<!ELEMENT java-port-name (#PCDATA)>

<!--
The java-variable-name defines the name of a public data member or 
JavaBeans property within a Java class. 

Used in: variable-mapping
-->
<!ELEMENT java-variable-name (#PCDATA)>

<!-- 
The java-xml-type-mapping element contains a class-type that is the 
fully qualified name of the Java class, QName of the XML root type, 
the WSDL type scope the QName applies to and the set of variable 
mappings for each public variable within the Java class.

Used in: java-wsdl-mapping
-->
<!ELEMENT java-xml-type-mapping (class-type, root-type-qname, 
	qname-scope, variable-mapping*)>

<!--
The localpart element indicates the local part of a QNAME.

Used in: wsdl-binding, wsdl-message, wsdl-port-type, 
		wsdl-service-name
-->
<!ELEMENT localpart (#PCDATA)>

<!--
The method-param-parts-mapping element defines the mapping between a
Java method parameters and a wsdl-message.

Used in: service-endpoint-method-mapping
-->
<!ELEMENT method-param-parts-mapping (param-position, param-type,
	wsdl-message-mapping)>

<!--
The method-return-value  element defines a fully qualified class name
or void type for the method's return value type.

Used in: wsdl-return-value-mapping
-->
<!ELEMENT method-return-value (#PCDATA)>

<!--
The namespaceURI element indicates a URI.

Used in: package-mapping, wsdl-binding, wsdl-message, wsdl-port-type, 
		wsdl-service-name
-->
<!ELEMENT namespaceURI (#PCDATA)>

<!--
The package-mapping indicates the mapping between java-package-name 
and XML namespace in the WSDL document.

Used in: java-wsdl-mapping
-->
<!ELEMENT package-mapping (package-type, namespaceURI)>

<!--
The package-type indicates the Java package name. It must be a fully 
qualified name.

Used in: package-mapping
-->
<!ELEMENT package-type (#PCDATA)>

<!--
The parameter-mode  element defines the mode of the parameter.
It can have only three values, IN, OUT, INOUT.

Used in: wsdl-message-mapping, wsdl-return-value-mapping
-->
<!ELEMENT parameter-mode (#PCDATA)>

<!--
The param-position element defines the position of a parameter within 
a Java method.  It must be an integer starting from 0.

Used in: method-param-parts-mapping
-->
<!ELEMENT param-position (#PCDATA)>

<!--
The param-type element defines the Java type of a parameter within a 
Java method. It must be defined by a fully qualified name of a class.

Used in: method-param-parts-mapping
-->
<!ELEMENT param-type (#PCDATA)>

<!--
The port-mapping defines the mapping of the WSDL port name attribute
to the Java name used to generate the Generated Service Interface 
method get<java-name>.

Used in: service-interface-mapping
-->
<!ELEMENT port-mapping (port-name, java-port-name)>

<!--
The port-name is the attribute value of a name attribute of a WSDL
port element.

Used in: port-mapping
-->
<!ELEMENT port-name (#PCDATA)>

<!--
The qname-scope elements scopes the reference of a QName to the WSDL
element type it applies to. The value of qname-scope may be 
simpleType, complexType, or element.

Used in: java-xml-type-mapping
-->
<!ELEMENT qname-scope (#PCDATA)>

<!--
The root-type-qname identifies the WSDL QName of an XML type.

Used in: java-xml-type-mapping
-->
<!ELEMENT root-type-qname (namespaceURI, localpart)>

<!--
The service-endpoint-interface element defines the Java type for the 
endpoint interface. The name must be a fully qualified class name.

Used in: service-endpoint-interface-mapping
-->
<!ELEMENT service-endpoint-interface (#PCDATA)>

<!--
The service-endpoint-interface-mapping defines a tuple
to specify Service Endpoint Interfaces to
WSDL port types and WSDL bindings.


An interface may be mapped to a port-type and binding multiple
times. This happens rarely.

Used in: java-wsdl-mapping
-->
<!ELEMENT service-endpoint-interface-mapping (
	service-endpoint-interface, wsdl-port-type, wsdl-binding, 
	service-endpoint-method-mapping*)>

<!--
The service-endpoint-method-mapping element defines the mapping of
Java methods to operations (which are not uniquely qualified by
qnames).

The wsdl-operation should be interpreted with respect to the portType
and binding in which this definition is embedded within. See the 
definitions for service-endpoint-interface-mapping and 
service-interface-mapping to acquire the proper context.

Used in: service-endpoint-interface-mapping
-->
<!ELEMENT service-endpoint-method-mapping (java-method-name,
          wsdl-operation, method-param-parts-mapping*,
          wsdl-return-value-mapping)>

<!--
The service-interface element defines the Java type for the service.
For static services, it is javax.xml.rpc.Service interface. For 
generated service, it would be the generated interface name.

The name must be a fully qualified class name.

Used in: service-interface-mapping
-->
<!ELEMENT service-interface (#PCDATA)>

<!--
The service-interface-mapping element defines how a Java type for 
the service interface maps to a WSDL service.

Used in: java-wsdl-mapping
-->
<!ELEMENT service-interface-mapping  (service-interface, 
	wsdl-service-name, port-mapping*)>

<!--
The soap-header element is a boolean element indicating that
a parameter is mapped to a SOAP header.

Used in: wsdl-message-mapping
-->
<!ELEMENT soap-header EMPTY>

<!--
The variable-mapping element defines the correlation between a 
Java class data member or JavaBeans property to an XML element
name of an XML root type. If the data-member element is present,
the Java variable name is a public data member.  If data-member
is not present, the Java variable name is a JavaBeans property.

Used in: java-xml-type-mapping
-->
<!ELEMENT variable-mapping (java-variable-name, data-member?,
	xml-element-name)>

<!--
The wsdl-binding element defines the wsdl binding
by a QNAME which uniquely identifies  the binding.

Used in: service-endpoint-interface-mapping
-->
<!ELEMENT wsdl-binding (namespaceURI, localpart)>

<!--
The wsdl-message  element defines a WSDL message by a QNAME.

Used in: wsdl-message-mapping, wsdl-return-value-mapping
-->
<!ELEMENT wsdl-message (namespaceURI, localpart)>

<!--
The wsdl-message-mapping element defines the mapping to a specific 
message and its part. Together they define uniquely the mapping for 
a specific parameter. Parts within a message context are uniquely 
identified with their names.

The parameter-mode is defined by the mapping to indicate whether 
the mapping will be IN, OUT, or INOUT..  The presence of the soap-header
element indicates that the parameter is mapped to a soap header only.
When absent, it means that the wsdl-message is mapped to a Java
parameter. The soap headers are interpreted in the order they are
provided in the mapping.

Used in: method-param-parts-mapping
-->
<!ELEMENT wsdl-message-mapping (wsdl-message, wsdl-message-part-name,
	parameter-mode, soap-header?)>

<!--
The wsdl-message-part-name  element defines a WSDL message part. It 
should always be interpreter with respect to a wsdl-message element.

Used in: wsdl-message-mapping, wsdl-return-value-mapping
-->
<!ELEMENT wsdl-message-part-name (#PCDATA)>

<!--
The wsdl-operation element defines an operation within a WSDL document.
It must be interpreted with respect to a port type.

Used in: service-endpoint-method-mapping
-->
<!ELEMENT wsdl-operation (#PCDATA)>

<!--
The wsdl-port-type element defines the wsdl port type
by a QNAME which uniquely identifies  the port type.

Used in: service-endpoint-interface-mapping
-->
<!ELEMENT wsdl-port-type (namespaceURI, localpart)>

<!--
The wsdl-return-value-mapping  element defines the mapping for the
method's return value. It defines the mapping to a specific message 
and its part.  Together they define uniquely the mapping for a 
specific parameter. Parts within a message context are uniquely 
identified with their names.

Used in: service-endpoint-method-mapping
-->
<!ELEMENT wsdl-return-value-mapping (method-return-value, wsdl-message,
	wsdl-message-part-name)>

<!--
The wsdl-service-name element defines the wsdl service name
by a QNAME which uniquely identifies  the service.

Used in: service-interface-mapping
-->
<!ELEMENT wsdl-service-name (namespaceURI, localpart)>

<!--
The xml-element-name element defines name attribute value of a WSDL
element within a root type.

Used in: variable-mapping
-->
<!ELEMENT xml-element-name (#PCDATA)>

<!--
The ID mechanism is to allow tools that produce additional deployment
information (i.e., information beyond the standard EJB deployment
descriptor information) to store the non-standard information in a
separate file, and easily refer from these tools-specific files to the
information in the standard deployment descriptor.
The EJB architecture does not allow the tools to add the non-standard
information into the EJB deployment descriptor.
-->
<!ATTLIST class-type id ID #IMPLIED>
<!ATTLIST data-member id ID #IMPLIED>
<!ATTLIST exception-mapping id ID #IMPLIED>
<!ATTLIST exception-type id ID #IMPLIED>
<!ATTLIST java-method-name id ID #IMPLIED>
<!ATTLIST java-port-name id ID #IMPLIED>
<!ATTLIST java-variable-name id ID #IMPLIED>
<!ATTLIST java-wsdl-mapping id ID #IMPLIED>
<!ATTLIST java-xml-type-mapping id ID #IMPLIED>
<!ATTLIST localpart id ID #IMPLIED>
<!ATTLIST method-param-parts-mapping id ID #IMPLIED>
<!ATTLIST method-return-value id ID #IMPLIED>
<!ATTLIST namespaceURI id ID #IMPLIED>
<!ATTLIST package-mapping id ID #IMPLIED>
<!ATTLIST package-type id ID #IMPLIED>
<!ATTLIST parameter-mode id ID #IMPLIED>
<!ATTLIST param-position id ID #IMPLIED>
<!ATTLIST param-type id ID #IMPLIED>
<!ATTLIST port-mapping id ID #IMPLIED>
<!ATTLIST port-name id ID #IMPLIED>
<!ATTLIST qname-scope id ID #IMPLIED>
<!ATTLIST root-type-qname id ID #IMPLIED>
<!ATTLIST service-endpoint-interface id ID #IMPLIED>
<!ATTLIST service-endpoint-interface-mapping id ID #IMPLIED>
<!ATTLIST service-endpoint-method-mapping id ID #IMPLIED>
<!ATTLIST service-interface id ID #IMPLIED>
<!ATTLIST service-interface-mapping id ID #IMPLIED>
<!ATTLIST soap-header id ID #IMPLIED>
<!ATTLIST variable-mapping id ID #IMPLIED>
<!ATTLIST wsdl-binding id ID #IMPLIED>
<!ATTLIST wsdl-message id ID #IMPLIED>
<!ATTLIST wsdl-message-mapping id ID #IMPLIED>
<!ATTLIST wsdl-message-part-name id ID #IMPLIED>
<!ATTLIST wsdl-operation id ID #IMPLIED>
<!ATTLIST wsdl-port-type id ID #IMPLIED>
<!ATTLIST wsdl-return-value-mapping id ID #IMPLIED>
<!ATTLIST wsdl-service-name id ID #IMPLIED>
<!ATTLIST xml-element-name id ID #IMPLIED>
			

8. 部署

本章定义了部署过程要求和职责。部署任务是由 J2EE 部署者平台角色使用通常由 Web Services for J2EE 产品提供者提供的工具处理。这包括特定于容器的 Web 服务类和 Web 服务引用类的生成、为每个端口的配置服务器 SOAP 请求侦听器、Web 服务的发布和定位,还有 J2EE 规范定义的一般职责。

8.1. 概述

本节描述了 Web Services for J2EE 的一个说明性部署过程。过程本身是不需要的,但是部署必须满足某些需要,本章后面部分将详细描述这些内容。这个过程假定部署有一般有两个阶段。第一阶段将 Web 服务映射到标准的 J2EE 构件,第二阶段是标准的 J2EE 部署过程。

部署从启用服务的应用程序或模块入手。开发者使用部署工具来开始部署过程。一般来说,部署工具将验证内容是否为正确装配的部署构件、并从部属程序收集绑定信息、部署模块中定义的组件和 Web 服务、发布代表被部署 Web 服务的 WSDL 文档、部署任何使用 Web 服务客户机、配置服务器并启动应用程序。

部署工具开始部署过程时首先要检查可部署的构件并通过查找包含在模块中的 webservices.xml 部署描述符文件来确定哪个模块是启用 Web 服务的。服务的部署在服务引用的解析之前发生。这样是为了使部署能够在对它们的服务引用被处理之前更新 WSDL 端口地址。

执行构件打包的验证是为了确保:

  • Web 服务部署描述符中定义的每个 WSDL 中的每个端口都有对应的端口-组件(port-component)元素。

  • 如果服务实现 Bean 为 EJB,那么由 SEI 定义的方法的事务属性就不包括强制性。

  • 如果服务实现 Bean 为 EJB,那么 SEI 方法就被远程完全包含。

  • JAX-RPC 服务组件只被打包到 WAR 文件中。

  • 无状态会话 bean Web 服务只被打包到 EJB-JAR 文件中。

  • WSDL 端口所使用的 WSDL 绑定由 Web Services for J2EE 运行时支持。如果不被任何端口使用,那么不支持的绑定可以在 WSDL 中声明。

每个端口-组件的部署都依赖于所使用的服务实现和容器。JAX-RPC 服务端点的部署需要与会话 bean 服务的部署不同的处理方法。

如果实现为 JAX-RPC 服务端点,那么将生成一个 servlet 以处理解析传入的 SOAP 请求并将其分派至 JAX-RPC 服务组件的实例上的过程。生成的 servlet 类依赖于 JAX-RPC 服务端点的线程使用模型。Web.xml 部署描述符将被更新,从而用生成的 servlet 类代替 JAX-RPC 服务端点类。端口组件的 WSDL 端口地址为 Web 应用程序 context-root 和 servlet url-pattern 两者合并的结果。如果实现为无状态会话 bean,那么部署工具就有很多选择可以使用。一般来讲,部署工具生成 servlet 来处理解析传入的 SOAP 请求的过程,并创建一个远程无状态会话 EJB 对象,然后将请求分派到无状态会话 EJB。SEI 的方法由远程接口描述,部署工具能够生成一个分派到 EJB 的远程接口的 servlet。请求如何被分派到服务实现 Bean 依赖于部署者提供的部署工具和部署时绑定信息。

部署工具必须部署和发布 Web 服务部署描述符中描述的所有 WSDL 文档的所有端口。部署工具为每个部署的 port-component 更新或生成 WSDL 端口。更新后的 WSDL 文档接下来被发布到部署者决定的位置。它可能和发布到一个包含所部署服务的模块中的文件、代表服务器部署的服务的 URL 位置、一个 UDDI 或 ebXML 注册中心或同时发布到这些地方一样简单。这是下一步解析对 Web 服务的引用所需的。

对 Web 服务客户机部署描述符中描述的每个服务引用来说,部署工具都确保客户机代码能够访问 Web 服务。部署工具检查客户机部署描述符中提供的信息(服务接口类、服务端点接口类以及客户机希望访问的 WSDL 端口)以及 JAX-RPC 映射信息。一般来说,过程包括提供部署描述符服务引用中声明的 JAX-RPC 服务接口类的实现、为所有 service-endpoint-interface 声明生成存根(如果支持生成的存根,而且部署者决定使用它们),还有将服务类实现绑定到 JNDI 名称空间。具体情况取决于服务是否被声明为客户机受管或容器受管的访问。

在使用客户机管理的端口访问服务时,部署工具必须对 Web 服务客户机部署描述符中声明的每个端口提供生成的存根或动态代理访问。选择生成的存根或动态代理是部署时绑定信息。如果在部署描述符中声明,那么容器必须为生成的服务接口提供实现。

在使用容器管理的端口访问时,容器必须对部署描述符中声明的每个端口提供生成的存根或动态代理访问。选择生成的存根或动态代理是部署时绑定信息。部署描述符可能包含 port-component-link,不仅用来将引用与服务实现关联,还用来将引用与定义它的 WSDL 关联。

一旦支持 Web 服务的可部署构件被转换为 J2EE 可部署构件,部署过程将继续使用常规的部署过程。

8.2. 容器提供者要求

这一节将详细描述容器提供者的要求。它不但包含容器运行时,还包含部署工具使用。

8.2.1. 部署构件

部署工具必须能够部署包含 Web 服务和/或 Web 服务引用的 EAR 文件(包含 WAR 和/或 EJB-JAR)、WAR 文件或 EJB-JAR。

8.2.2. 生成 Web 服务实现类

容器支持 JAX-RPC 服务端点或无状态会话 Bean 服务实现所需的任何运行时类的生成都是特定于提供者的。运行时类的行为必须与组件的部署描述符设置一致。JAX-RPC 服务端点必须与 web.xml 部署描述符中的 <servlet> 元素所定义的行为一致。无状态会话 Bean 服务实现必须与 ejb-jar.xml 部署描述符中的 <session> 元素和 <assembly-descriptor> 定义的行为一致。

8.2.3. 生成部署的 WSDL

容器必须为 Web 服务部署描述符(webservices.xml)中声明的每个 wsdl-file 元素更新和/或生成部署的 WSDL 文档。如果多个 wsdl-file 元素指向同一位置,那就必须为每个元素分开生成 WSDL 文档。

wsdl-file 元素所描述的 WSDL 文档必须包含服务和端口元素,而且部署描述符中的每个 port-component 都必须有对应的 WSDL 端口,反之亦然。部署工具必须更新 WSDL 端口地址元素,以生成部署的 WSDL 文档。生成的端口地址信息是部署时绑定信息。对于 Web 模块中的 port-component 这种情况,地址部分地被 Web 应用程序的 context-root 约束。

8.2.4. 发布部署的 WSDL

部署工具必须发布每个部署的 WSDL 文档。部署的 WSDL 文档可以被发布到文件、URL 或者注册中心。文件和 URL 发布必须被提供者支持。文件发布包含在应用程序生成的构件中。我们鼓励您发布到注册中心,如 UDDI 或 ebXML,但这不是必须的。

如果支持向文件或 URL 以外的位置发布,那么也必须支持包含该位置服务的 WSDL 文档。举例来说,Web 服务部署描述符声明了 wsdl-file StockQuoteDescription.xmlport-component,后者声明了 WSDL 文档中的 port QName。在部署时,StockQuoteDescription.xml 中的端口地址被更新为部署的位置。它会被发布到 UDDI 注册中心位置。在同一个应用程序中,service-ref 使用 port-component-link 来引用部署的 port-component。提供者必须支持从端口组件发布所在的注册中心查找该组件部署的 WSDL。这一项支持必须能够从不与包含服务的应用程序绑定在一起的部属的客户机使用。

选择从何处(什么位置以及几处地方)发布是部署时绑定信息。

8.2.5. 服务和生成的服务接口实现

容器必须提供 JAX-RPC 服务接口的实现。服务实现不需要在部署期间创建。容器可以用生成的服务接口实现替代一般的服务接口实现。

如果 Web 服务客户机部署描述符定义了 JAX-RPC 生成的服务接口,那么容器就必须提供该接口的实现。生成的服务接口实现一般会在部署期间提供。

服务接口实现必须为 WSDL 描述中的服务元素声明的所有端口提供静态存根和/或动态代理。容器提供者必须支持至少静态存根或动态代理的其中一个,但可能为两者提供支持。

容器必须在 JNDI 名称空间位置 java:comp/env/service-ref-name 提供所需的服务接口实现,其中 service-ref-name 是 Web 服务客户机部署描述符中使用 service-ref-name 元素声明的名称。

8.2.6. 静态存根生成

部署工具可以支持静态存根的生成。如果不支持动态代理,那么容器提供者必须提供静态存根生成。静态存根是特定于提供者的,而且一般来说,开发者都应该避免将它们与应用程序打包在一起。

静态存根(和动态代理)必须遵循 [JAX-RPC] 规范的第 8.2.1 节和第 8.2.2 节。

第 4.2.4 节 JAX_RPC 属性中所定义,容器需要在没有客户机代码干预的情况下支持凭证传播。存根/代理是否直接支持这一点或容器的另一部分不在本规范讨论的范围之内。

8.2.7. 类型映射

对类型映射的支持是特定于提供者的。本规范不需要提供创建可移植的类型映射的方法,因此也不需要提供声明它们或部署它们的方法。

8.2.8. 映射需要

部署工具必须使用 jaxrpc-mapping-file 定义的映射元数据需要。所有映射都必须在缺省规则应用前应用。

8.2.9. 部署失败的情况

如果出现下面的情况,部署可能会失败:

  • webservices.xml 部署描述符无效

  • WSDL 文件、JAX-RPC 映射文件与部署描述符冲突

  • 实现方法和操作冲突

  • 任何端口组件不能被部署

  • Web 服务部署描述符中定义的每个 WSDL 中的每个端口没有对应的 port-component 元素。

  • 如果服务实现 Bean 是 EJB,那么 SEI 定义的方法的事务属性就包括 Mandatory。

  • 如果服务实现 Bean 是 EJB,那么远程接口就不完全包含 SEI 方法。

  • JAX-RPC 服务组件不被打包在 WAR 文件中。

  • 无状态会话 bean Web 服务不被打包在 EJB-JAR 文件中。

  • Web Services for J2EE 运行时不支持 WSDL 端口使用的 WSDL 绑定。然而,如果不被任何端口使用,那么不支持的绑定可以在 WSDL 中声明。

  • Handler.getHeaders() 方法返回的 QName 不在处理程序代表端口-组件执行的 WSDL 中定义。

8.3. 部署者职责

部署者角色负责指定部署时绑定信息。它可能包括部署的 WSDL 端口地址以及进行请求(不使用 CallbackHandler)所用的请求标识和密码。

9. 安全性

这一节定义了 Web Services for J2EE 的安全性要求。第 5.2 节 概念中讨论了安全性的概念性概况,还讨论了它如何应用于 Web 服务。第 9.2 节 目标定义了本规范着眼于解决的问题,第 6.2 节 规范讨论了需求。

9.1. 概念

Web 服务安全性面临的挑战是如何理解并评估当前使基于 Web 的服务安全化可能要付出的风险,同时紧随新兴的标准并理解它们如何部署,从而减少将来的风险。任何安全性模型都必须说明数据可以如何在应用程序和网络拓扑结构中传送,以满足业务定义的需求,而不会将数据暴露在不当的风险下。Web 服务安全性模型应该支持与协议无关的声明性安全策略(Web Service for J2EE 提供者可以实施),以及附加在服务定义后的客户机可以用来安全地访问服务的描述性安全策略。

为了保证信息交换的安全,需要强调五点安全性要求:

  • 认证 — 申请人是否有权使用声明的标识和/或专利集合的验证。

  • 授权 — 赋予某个标识对资源执行特定操作的权力。

  • 完整性 — 确保消息在传送中没有被意外或故意修改。

  • 保密性 — 保证消息的内容没有被透露给未被授权的个体。

  • 不可抵赖性 — 保证消息的发送者不能否认他发送了消息。该请求也暗示了消息的原始认证。

与这些要求有关的风险可以通过结合 J2EE 环境中各种已有和新兴的技术及标准来避免。有很多基本的业务原因构成了各种安全性机制以减轻上面总结出的各种安全性风险。实体的认证是必需的。这有助于根据 Web 服务调用者的标识提供访问。数据完整性的商业原因在于事务中的每一方都可以对商业事务有信心。它还是商业合法性问题,使审计追踪和某些不可抵赖性的证据可以解决可靠性问题。越来越多的企业开始注意到来自员工或防火墙里面的其它人对其应用程序产生的内部威胁。某些商业事务要求在服务调用或其数据(如信用卡号码)上提供保密性。因特网上的企业还需要保护自身免受正在发起的拒绝服务攻击。这就是我们需要插入安全性服务模型的环境。

9.1.1. 认证

由于 Web 服务体系结构建立在已有的组件技术上,所以企业内的认证与当前的方法没什么不同。为了让两方或多方能够安全地通信,它们可能需要交换安全性凭证。Web 服务的安全性用来交换许多不同类型的凭证。凭证代表相关标识的可靠性,例如 Kerberos 票据。凭证可以被验证,以验证其可靠性,而且标识可以从凭证推断出。

当两方进行通信时,发送者要理解目标服务的安全性要求,这也很重要。这有助于发送者提供必要的凭证和请求。另一种情况是,目标将询问发送者以获取必要的凭证(与 HTTP 服务器询问 HTTP 客户机类似)。

将来,希望消息层安全机制将被支持。使用这种方法,凭证就可以与消息一起传播并脱离底层传输协议。类似地,使用消息层保护可以确保保密性和完整性。消息层安全性支持将有助于解决端对端安全性需要,这样请求就可以用独立于底层协议的安全的方式遍历多个网络层、拓扑结构和媒介。

将来,我们还估计到为了让客户机应用程序确定 Web 服务期望的安全性级别以及期望的凭证类型,关于认证策略的信息将包含在服务定义(WSDL)中,也可以通过它来获得。建立在这种服务定义的基础上,客户机提供了合适的凭证。如果容器有服务策略,那么它们必须被引用并使用。

图 11 安全性流概况

安全性流概况

请考虑这样一种情况:传入的 SOAP/WSDL 消息流经 HTTP(S)。上图提供了安全性流的简单概览。企业 Web 站点依赖于认证模型的 J2EE 服务器支持。站点还依赖于代理服务器对安全性的支持。在这几种情况中,J2EE 服务器接收到请求之前就会发生认证。在这几种情况下,代理服务器或 Web 服务器将认证凭证转发到 J2EE 应用程序服务器中。J2EE 应用程序服务器将按照类似于处理其它 HTTP 请求的方式处理请求。J2EE 应用程序服务器可以按照处理其它 HTTP 请求的方式处理请求。

根据已有的 J2EE 功能,Web Services for J2EE 中有两种形式的认证可以使用。它们是 HTTP 基本认证( HTTP BASIC-AUTH)和对称 HTTP(Symmetric HTTP),由 Servlet 2.3 规范定义。

使用上述认证模型,容器也能在执行路径的任一点执行传入凭证的凭证映射。映射将外部用户凭证转换为特定安全域中使用的凭证,举例来说,通过 Kerberos 或其它嵌入式第三方模型转换。

除了传播凭证所用的 J2EE 安全性模型之外,在 SOAP 消息本身(例如作为 SOAP 头)中传送标识信息可能也很有好处。这有助于对付需要支持 Web 服务,而本身对底层传输和协议的安全性支持可能并不充分的情况(例如 JMS)。JSR109 不需要在 SOAP 消息中具备任何对凭证传播的支持,并将该功能视为以后的事情。

9.1.2. 授权

在企业安全性模型中,每个应用程序服务器和中间件元素分别执行其资源(EJB、Servlet、队列和表等等)的授权。J2EE 认证/委派模型确保用户标识证明在对请求进行处理时是可以取得的。

一旦认证成功,通过认证的用户的标识就与请求有了关联。根据用户的标识做出了授权决策。基于 J2EE 1.3 安全性模型的 J2EE 服务器来执行这项任务是为了只允许对 EJB 和 Servlet/JSP 的方法进行授权的访问。对于实现为 JAX-RPC 服务端点的 Web 服务,对其进行授权要根据 servlet/JSP 安全性模型。

9.1.3. 完整性和保密性

一般来讲,完整性和保密性建立在已有的 J2EE 支持(如 HTTPS)的基础上。

消息发送方也许还想要确保,消息或消息的部件保密以及消息在传送过程中没有被修改。当消息需要保密时,消息的发送方可以使用 XML Encryption 加密消息中那些不可以公开的部分。当需要保证消息的完整性时,消息的发送方可以使用 XML Digital Signature 来确保消息在传送过程中没有被修改。本规范推荐,J2EE 服务器使用 XML Encryption 用于保密,XML Digital Signature 来确保完整性,不过要放到将来的标准化格式和 API 的工作中。

9.1.4. 审计

J2EE 服务器在处理请求时可以选择写隐式和显式审计记录。中间件使用户凭证和隐式上下文中的相关 ID 在所有操作上流动。管理工具可以收集多个日志、进行合并使用关联信息就可以看到处理每条进入的 Web 服务请求发出的所有记录。我们推荐采用 J2EE 服务器实现对审计记录的支持,但是委托给 J2EE 来标准化记录格式和 API 以支持审计日志。

9.1.5. 不可抵赖性

结合 HTTP/S 上的基本认证(Basic Authentication)在当今业界得到了广泛采用,确保保密性、认证和完整性。然而,它不能保证不可抵赖性。

我们推荐 J2EE 服务器实现对不可抵赖登录的支持,但是没有为定义和支持不可抵赖而定义标准机制。

9.2. 目标

J2EE 应用程序服务器中的 Web 服务的安全性模型应该易于设计和使用、普遍存在、成本效率高、基于开放源标准、可扩展,而且灵活。基本的功能需要能够用于多种安全性模型、安全性认证凭证、多信任域和多加密技术的构建。因此,安全性的目标包括以下几点:

  • 应该支持使用 J2EE 授权模型的 Web 服务的保护。

  • 应该支持将认证信息传播到提交 Web 服务请求使用的协议绑定上。

  • 应该支持传输层安全性,以确保消息请求的保密性和完整性。

  • 应该是防火墙友好的:能够穿越防火墙,而不需特殊协议的干预。

9.2.1. 假设

下面的假定适用于本章:

服务器依赖于 J2EE 应用程序服务器的安全性基础结构。

安全的 Web 服务容器的服务质量(Quality of Service,QoS)建立在底层 J2EE 应用程序服务器本身的 QoS 需求和功能(例如完整性)的基础之上。

服务器依赖于 HTTPS 和 RMI-IIOP over SSL 来实现逐段的保密性和完整性。

9.3. 规范

9.3.1. 认证

很少有用来认证消息发送者的认证模型可以作为标准而采用或提倡。基于表单的登录需要 html 处理功能,所以并不包括在这个列表中。Web Services for J2EE 产品提供者必须支持下面几项:

  • 基本认证:J2EE 服务器支持传送 SOAP 请求的 HTTP 头中基本的认证信息。J2EE 服务器必须能够使用特定于服务器的认证机制验证用户 ID 和密码。通常,用户 ID 和密码是根据用户注册中心来认证的。要确保密码信息的保密性,用户 ID 和密码将通过 SSL 连接(即 HTTPS)来发送。请参阅 Servlet 2.3 规范,以便详细地了解基本认证是如何必须被 J2EE 1.3 支持的,以及 HTTP 摘要认证如何能够被可选地支持。认证数据的客户机容器规范由 J2EE 1.3 规范的第 3.4.4 节描述。EJB 和 Web 容器必须支持使用基本认证将凭证信息传播到下游 Web 服务请求。尽管实现它的方法通常是使用生成的静态存根或动态代理实现处理的,但该方法还是特定于提供者。

  • 对称 HTTPS:J2EE 1.3 服务器目前支持通过对称 SSL 的认证,其中请求者和服务器都可以使用数字证书认证对方。对于 HTTP 客户机(即 SOAP/HTTP)来说,该模型是基于 Servlet 2.3 规范的。

9.3.2. 授权

Web Services for J2EE 依赖于 J2EE 容器提供的授权支持,这在 J2EE 1.3 规范的第 3.5 节中有所描述。

JAX-RPC 服务端点授权必须使用 POST 的 http-method 元素值定义。

9.3.3. 完整性和保密性

Web Services for J2EE 服务器提供者必须支持 HTTPS 以实现逐段的保密性和完整性。WSDL 端口地址可以用 https: 来指定客户机要求。

10. 附录

10.1. 附录 A. 与其它 Java 标准的关系

用于 XML 的 Java API

该清单中我们需要的 API 只有 JAX-RPC。列出其余的是考虑到您可能有兴趣了解。这些 API 在将来的规范中可能会变成必需的。

JAX-M(JSR 00067)集中讨论 XML 消息传递和 Java 语言。
JAX-R(JSR 00093)定义到 XML 注册中心的 Java 接口,如 JNDI、ebXML 和 UDDI。这些接口提供了客户机应用程序查找 Web 服务以及 Web 服务(和服务器)发布其接口所使用的机制。
JAX-P(JSR 00005 和 00063)定义解析 XML 的 API。
JAX-RPC(JSR 00101)集中描述 XML RPC 和 Java 语言,包括用 Java 表示基于 XML 的接口定义、基于 XML 的接口定义语言(例如 SOAP)中的 Java 定义和数据组织。
XML Trust(JSR00104)定义“信任的服务”的 API 和协议,从而将使用 XML 签名的复杂性最小化。
XML Digital Signature(JSR 00105)定义 XML 数字签名服务的 API。
XML Digital Encryption(JSR 00106)定义对 XML 片段进行加密的 API。
WSDL 的 Java API(JSR00110)定义操作 WSDL 文档的 API。

J2EE API

Enterprise JavaBeans 2.0定义实现在 EJB 容器中运行的 Web 服务的编程模型。
Servlet 2.3定义了实现在 servlet 容器中运行的 Web 服务的打包和容器服务模型。
J2EE 1.4、EJB 2.1 和 Servlet 2.4将包含本规范中定义的 Web 服务规范。我们将努力维持兼容性并使迁移到 J2EE 1.4 更加容易,但不能保证一直能够确保兼容性。JSR 109 1.1 维护发行版将着眼于基于 XML 模式的部署描述符、EJB 2.1 Web 服务视图,以及 J2EE 1.4 要使用的 EJB 容器中 Holder 和 Handler 类的使用。

10.2. 附录 B. 参考资料

JAX-RPC
JAX-RPC 1.0 规范,2002 年。http://java.sun.com/xml/
JAX-R
JAX-R 规范。2002 年。http://java.sun.com/xml/
SOAP
SOAP 1.1 W3C 纪要。2000 年。http://www.w3.org/TR/2000/NOTE-SOAP-20000508
WSDL
WSDL 1.1 W3C 纪要。2001 年。http://www.w3.org/TR/2001/NOTE-wsdl-20010315
Servlet
Servlet 2.3 规范。2000 年。http://java.sun.com/j2ee/
J2EE
J2EE 1.3 规范。2001 年。http://java.sun.com/j2ee/
EJB
EJB 2.0 规范。2001 年。http://java.sun.com/j2ee/

10.3. 附录 C. 修改纪录

10.3.1. 附录 C.1. 版本 0.8

  • 更新了 JAX-RPC 映射文件格式

10.3.2. 附录 C.2. 版本 0.7

  • 完全修改了 JAX-RPC 映射文件,以处理丢失映射的情况。支持开发时设计的最小映射。

10.3.3. 附录 C.3. 版本 0.6

  • 强化了对无模式服务对象的客户机访问模式。更新了第 4 章以反映出这一点,并更新了第 7 章以反映客户机部署描述符的变化。

  • 修改了第 7 章客户机部署描述符的平台角色职责,以阐述 WSDL 的部分使用。

  • 在第 6 章和第 8 章增加了要在 WSDL 中定义头的要求(如果头被声明为被处理程序处理)。

  • 修改了当处理程序按不正确的方式修改请求时的异常抛出。

  • 阐述了不在该版本讨论范围内的定制序列化器/反序列化器的使用。

10.3.4. 附录 C.4. 版本 0.5

  • 添加了 JAX-RPC 映射部署描述符

  • 阐述了平台角色职责

  • 阐述了部署

  • 修改了一些术语以与 JAX-RPC 同步

10.3.5. 附录 C.5. 版本 0.4 专家小组草案

  • 阐述了服务开发目标。

  • 阐述了 Web 服务注册中心目标。

  • 阐述了容器对向客户机提供存根/代理的要求。

  • 将 HandlerRegistry 和 TypeMappingRegistry 访问从可选改为不支持。

  • 阐述了 JAX-RPC 存根属性的使用。

  • 添加了客户机打包要求。

  • 加强了将 EJB 作为 Web 服务公开的要求。

  • 加入了处理程序一章。



到页首
您对这篇文章的看法如何?
真棒!(5)好材料 (4)一般;尚可 (3)需提高 (2)太差! (1)

建议?


(c) Copyright IBM Corp. 2001, (c) Copyright IBM China 2001, All Right Reserved
  关于 IBM  |  隐私条约  |  法律条款  |  联系 IBM