Lotus Notes/Domino 7 Web Services

Web Services 是 Lotus Notes/Domino 7 的新特性。本文介绍新 Web Services 设计元素,展示如何在 Domino Designer 中创建这种设计元素,并描述了如何用 LotusScript 和 Java 代码示例来实现 Web Services。

[编者注:本文描述 Web Services 的 Lotus Notes/Domino 7 Beta 2 实现。它可能并不准确反映 Lotus Notes/Domino 7 的 Gold 版本的特性或功能。]

Web 服务是可以通过在 Internet 上发送消息来调用的远程操作的档案。Web 服务供应商发布用于查询和使用的 Web 服务,而 Web 服务消费者调用来自这些服务的操作。Web 服务供应商提供了定义服务接口的 WSDL(Web Services Description Language,Web 服务描述语言)文档。WSDL 文档是 XML 格式的。接口的底层由供应商实现,但大多数供应商将接口映射为支持的编程语言的过程调用。来自消费者的入站请求传递给底层代码,然后结果返回给消费者。

Lotus Domino 将 WSDL 接口映射为可以用 LotusScript 或 Java 编码的类似代理的 Web 服务设计元素。要被使用,Web 服务必须位于启用 HTTP 的 Domino 服务器上。(我们可以通过 Notes 客户机预览中的 HTTP 会话测试 Web 服务。)通过下列 Domino URL 命令之一进行访问:

  • ?OpenWebService 调用 Web 服务以响应通过 HTTP POST 发送的 SOAP 编码消息。HTTP GET(例如,浏览器查询)返回服务的名称及其操作。
  • ?WSDL 返回 WSDL 文档以响应 HTTP GET。

本文描述 Lotus Notes/Domino 7 中的 Web 服务器设计元素,并提供了设计元素的 LotusScript 和 Java 示例。本文假设您是了解 LotusScript 或 Java 的经验丰富的 Notes 应用程序开发人员。

示例

让我们看一个简单的例子。给定数据库名称、视图名称和文档号,我们的操作返回 Subject 项的内容。我们将调用操作 getNthSubject。


图 1. getNthSubject 图表
getNthSubject 图表

要让该操作可用于外部世界,将其发布在名为 GetSubject 的 Web 服务中。GetSubject 可以包含任意数目的操作。例如,可能发现 getFirstSubject 和 getLastSubject 都有用。但现在只处理示例操作 getNthSubject。下列代码段摘自描述包含这样一个操作的 Web 服务的 WSDL 文档。下面看一下代码段及其注释。

<wsdl:message name="getNthSubjectRequest"> 
        (4) 
  <wsdl:part name="dbname" type="xsd:string"/> 
        (5) 
  <wsdl:part name="viewname" type="xsd:string"/> 
        (5) 
  <wsdl:part name="n" type="xsd:int"/> 
        (5) 
</wsdl:message>
<wsdl:message name="getNthSubjectResponse"> 
        (4) 
 <wsdl:part name="getNthSubjectReturn" type="xsd:string"/> 
        (6) 
</wsdl:message>
<wsdl:portType name="GetSubjectPortType"> 
        (1) 
  <wsdl:operation name="getNthSubject" 
   parameterOrder="dbname viewname n"> 
        (2)                      
  <wsdl:input message="impl:getnthSubjectRequest" name="GetNthSubjectRequest"/> 
        (3) 
  <wsdl:output message="impl:getNthSubjectResponse" name="GetNthSubjectResponse"/> 
        (3) 
  </wsdl:operation>
</wsdl:portType>
      

首先看 portType 元素 (1),它定义了服务的操作集合。我们的服务只有一个 portType,它只有一个操作 getNthSubject (2)。该操作有两个“消息” (3):一个用于输入,一个用于输出。消息在消息元素 (4) 中定义。我们看到,输入消息有三个部分 (5):两个名为 dbname 和 viewname 的字符串,一个名为 n 的 int。输出消息只有一个部分 (6),即名为 getNthSubjectReturn 的字符串。

所以,我们的操作有三个输入部分和一个输出部分,这非常巧妙地映射为具有三个只读参数和一个返回值的过程。在 LotusScript 中,这样的过程将通过下列函数来定义:

Public Function getNthSubject(dbname As String, viewname As String, n As Long) As String

在 Java 中,通过下列方法来定义:

public String getNthSubject(String dbname, String viewname, int n)

Web 服务设计元素

在 Domino Designer 中创建 Web 服务设计元素有多种可行方法。可以完全用 LotusScript 或 Java 来编码。在这种情况下,保存设计元素会生成反映 LotusScript 或 Java 代码的 WSDL 文档。或者可以导入现有的 WSDL 文档。在这种情况下,在导入的 WSDL 中会生成反映操作的 LotusScript 或 Java 代码。Web 服务设计元素保存 WSDL 文档以及代码。如果公共接口未更改,则 WSDL 文档保持不变。如果在编码中更改了影响公共接口的部分,则会生成新的 WSDL。

在 Domino Designer 中,Web 服务设计元素驻留在 Shared 代码中的 Agents 之下。Web 服务设计窗口的外观与代理设计窗口非常相似。单击“New Web Service”按钮以创建新 Web 服务。双击现有 Web 服务以对其进行编辑。


图 2. New Web Service
New Web Service

Web Services Property 框有三个类似代理的选项卡。下面是 Basics 选项卡:


图 3. Web Services Property 框
Web Services Property 框

名称是必需的。别名和备注可以提供也可以不提供。如果编码更改引起新 WSDL 的生成,则会收到警告消息。

PortType 类是定义映射为 WSDL 操作的过程的类名。这些过程在 LotusScript 中必须是公共函数或子程序,在 Java 中必须是公共方法。私有函数、子程序和方法不通过 Web 服务接口暴露。不能在属性框中输入 PortType 类,除非已经通过编码或导入 WSDL 创建了该类。稍后将详细介绍代码。

Security 选项卡几乎与代理 Security 选项卡完全一样。稍后将详细介绍 Security。

Advanced 选项卡具有用于定义 Web 服务和生成 WSDL 的其他信息。稍后将详细介绍。

编辑器窗格与代理的编辑器窗格相似。在右下拉框中,可以选择 LotusScript 或 Java。下面显示的是选择 Java。左边是 Objects 和 Reference 窗格。


图 4. Web 服务 (Java)
Web 服务 (Java)

使用“Import WSDL”按钮以基于现有 WSDL 创建新 Web 服务。“Show WSDL”按钮编译对 Web 服务的任何更改,并显示定义公共接口的 WSDL 文档。“Export WSDL”按钮编译对 Web 服务的任何更改,并导出定义公共接口的 WSDL 文档。还可以通过保存或关闭 Web 服务来编译。仅当公共接口更改时,才会重新生成 WSDL。

基本编码

Web 服务的代码具有下列元素:

  • 实现代码的类定义。该类必须成为属性框的 Basics 选项卡中命名的 PortType 类,且必须是公共的。
  • 在类中,Web 服务中每个操作的过程(函数、子程序或方法)定义。这些过程必须是公共的。不想放在接口中的支持过程必须是私有的。
  • LotusScript 中 lsxsd.lss 的包含。Java 中 lotus.domino.types.* 的导入。
  • 访问 Domino Objects 对象时 NotesSession (LotusScript) 或 Session (Java) 的初始化。对于 LotusScriptobject,此操作最好是在新块中完成,对于 Java,最好是在无参构造函数中完成。对于 Java,使用 WebServiceBase.getCurrentSession() 来获得 Session 对象。我们可能还想使用 Session.getAgentContext() 来获得 AgentContext 对象。WebServiceBase 等同于 JavaAgent,但 Web 服务不能访问对象。惟一有用的方法是静态 getCurrentSession()。

下面是 LotusScript 代码的模板,其中 Web 服务包含一个操作。该操作是上述具有三个输入参数和一个返回值的示例操作。

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Class GetSubject
  Sub NEW
    Set s = New NotesSession
  End Sub
  Function getNthSubject(dbname As String, viewname As String, n As Long) As String
        ! Code for doing the operation goes here
  End Function
End Class

下面是 Java 代码的模板,其中 Web 服务包含一个操作。构造函数必须是默认构造函数(无参数)。其他构造函数被忽略。

import lotus.domino.*;
import lotus.domino.types.*;
public class GetSubject {
  Session s;
  public GetSubject() {
    s = WebServiceBase.getCurrentSession();
  }
  public String getNthSubject(String dbname, String viewname, int n) {
        // Code for doing operation goes here
  }
}

现在我们将扩展示例以包括工作代码。下面是 LotusScript 代码:

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Class GetSubject
  
  Sub NEW
    Set s = New NotesSession
  End Sub
  
  Function getNthSubject(dbname As String, viewname As String, n As Long) As String
    Dim db As NotesDatabase
    Dim view As NotesView
    Dim doc As NotesDocument
    Set db = s.GetDatabase("", dbname)
    If Not(db.IsOpen) Then
      getNthSubject = "Cannot open database " & dbname
      Exit Function
    End If
    Set view = db.GetView(viewname)
    If view Is Nothing Then
      getNthSubject = "Cannot open view " & viewname
      Exit Function
    End If
    Set doc = view.GetNthDocument(n)
    If doc Is Nothing Then
      getNthSubject = "Cannot get document " & n
      Exit Function
    End If
    If doc.HasItem("Subject") Then
      getNthSubject = doc.GetItemValue("Subject")(0)
    Else
      getNthSubject = "Document does not have Subject"
    End If
  End Function
End Class

下面是 Java 代码:

import lotus.domino.*;
import lotus.domino.types.*;
public class GetSubject {
  
  Session s;
  
  public GetSubject() {
    s = WebServiceBase.getCurrentSession();
  }
  public String getNthSubject(String dbname, String viewname, int n) {
    String subject = null;
    try {
      Database db = s.getDatabase(null, dbname);
      if (!db.isOpen()) subject = "Cannot open database " + dbname;
      else {
        View view = db.getView(viewname);
        if (view == null) subject = "Cannot open view " + viewname;
        else {
          Document doc = view.getNthDocument(n);
          if (doc == null) subject = "Cannot get document " + n;
          else {
            if (doc.hasItem("Subject"))
              subject = doc.getItemValueString("Subject");
            else subject = "Document does not have Subject";
          }
        }
      }
    }
    catch(Exception e) {
      subject = e.toString();
      e.printStackTrace();
    }
    
    return subject;
  }
}

调用和测试 Web 服务

最终,Web 服务设计元素必须驻留在运行 HTTP 的 Domino 7 服务器上。我们可以测试驻留于 Domino Designer 上的 Web 服务设计元素。首先必须在启动 HTTP 的任何位置(比如,窗体)选择 Web Browser 中的 Design - Preview。如果消费者与 Notes 客户机位于同一机器上,则使用 127.0.0.1 作为计算机地址。要扮演 Web 服务的消费者,必须在 HTTP 请求中向 Domino Web 服务的 URL 发送一条 SOAP 消息。URL 如下:

http://rperron300pl.notesdev.ibm.com/Webservices2.nsf/GetSubject?OpenWebService

SOAP 消息如下:

<SOAP-ENV:Envelope
 ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 <SOAP-ENV:Body>
  <ns0:getNthSubject 
        (1) 
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:ns0="urn:DefaultNamespace">
   <dbname xsi:type="xsd:string">Webservices2</dbname> 
        (2) 
   <viewname xsi:type="xsd:string">Main View</viewname> 
        (2) 
   <n xsi:type="xsd:int">2</n> 
        (2) 
  </ns0:getNthSubject>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
      

在本例中,SOAP 消息 (1) 标识操作, (2) 并提供输入部分的值。显示在 SOAP-ENV:body 中的特定元素由 WSDL 绑定特征确定,尤其是 SOAP 消息格式。(详细信息请参阅下文的“高级属性”)。

Web 服务的 WebSphere SDK 提供了调用 Web 服务和查看结果的工具。此 SDK 运行于 Eclipse 中。必须安装:

WebSpere SDK(截止撰写本文时)不与 Eclipse 3.0 一起使用。还可以使用 WebSphere Studio Application Developer 来调用 Web 服务。最新版本是 v5.1.2。

要支持 WebSphere SDK 工具,打开 Eclipse 并选择 Run - Launch the Web Services Explorer。Web Services Explorer 加载后:

  1. 单击 WSDL Page 图标。它是右上角右箭头之后的第三个图标。WSDL Main 链接显示在左边的 Navigator 窗格中。
  2. 单击 WSDL Main 链接。Open WSDL 框显示在右窗格中。
  3. 用命令 ?WSDL 输入 Web 服务的 URL,例如, http://rperron300pl.notesdev.ibm.com/Webservices2.nsf/GetSubject?WSDL,然后单击 Go。我们想要 ?WSDL(而非 ?OpenWebService),因为此处 Web Services Explorer 阅读 WSDL 文档。
  4. WSDL Binding Details 框显示在右窗格中,它包含到 Web 服务定义的操作的链接。
  5. 单击操作名称,例如 getNthSubject。显示 Invoke a WSDL Operation 框。
  6. 输入输入部分(参数)的值,然后单击 Go。

响应返回在底部 (Status) 窗格中。调用示例 Web 服务之后,Web Services Explorer 的外观如下。


图 5. Web Services Explorer
Web Services Explorer

Actions 框的右上角有 Source 链接。单击 Source 显示实际 SOAP 消息。可以修改 SOAP 消息,然后单击 Go 将其发送。单击右上角的 Form 以返回到原始显示。Status 框也有 Source 链接,该链接允许查看 SOAP 响应,如果状态指示没有要显示的内容(且期望响应),则代码可能失败了。

运行 Web 服务之后,检查服务器控制台或 log.nsf 以获得错误消息。可以通过插入 MessageBox 语句来登录或调试,从而打印到服务器控制台或 log.nsf。(不要使用 Beta 2 中的 Print 打印语句。这些语句转到代理的 HTTP 流并破坏 SOAP 响应。)

高级属性

属性框的 Advanced 选项卡影响 WSDL 文档反映的 Web 服务定义。


图 6. Web Services Property 框的 Advanced 选项卡
Web Services Property 框的 Advanced 选项卡

可以提供想要为端口类型、服务元素和服务端口命名的名称。例如,可以将 GetSubject 用作所有名称。为了清晰,使用反映元素类型的后缀。在属性框中提供名称时,这些名称插入到生成的 WSDL 文档中。如果导入 WSDL 文档,则 WSDL 文档中的名称自动插入到属性框中。

下面是 GetSubject 示例完整的 WSDL 文档。注释部分是 Web Services Property 框的 Advanced 选项卡反映的内容。

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="urn:DefaultNamespace" 
xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:apachesoap="http://xml.apache.org/xml-soap" 

     
     xmlns:impl="urn:DefaultNamespace" xmlns:intf="urn:DefaultNamespace" 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"

     
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <wsdl:message name="getNthSubjectResponse">
  <wsdl:part name="getNthSubjectReturn" type="xsd:string"/> 
        (6) 
 </wsdl:message>
 <wsdl:message name="getNthSubjectRequest">
 <wsdl:part name="dbname" type="xsd:string"/> 
        (6) 
 <wsdl:part name="viewname" type="xsd:string"/> 
        (6) 
 <wsdl:part name="n" type="xsd:int"/> 
        (6) 
</wsdl:message>
 <wsdl:portType name="GetSubjectPortType"> 
        (1) 
  <wsdl:operation name="getNthSubject"
        parameterOrder="dbname viewname n">
   <wsdl:input message="impl:getNthSubjectRequest"
                  name="getNthSubjectRequest"/>
   <wsdl:output message="impl:getNthSubjectResponse"
                   name="getNthSubjectResponse"/>
  </wsdl:operation>
 </wsdl:portType>
 <wsdl:binding name="GetSubjectPortSoapBinding"
               type="impl:GetSubjectPortType">
  <wsdlsoap:binding style="rpc" 
        (4) 
                transport="http://schemas.xmlsoap.org/soap/http"/>
  <wsdl:operation name="getNthSubject">
   <wsdlsoap:operation soapAction=""/> 
        (7) 
   <wsdl:input name="getNthSubjectRequest">
    <wsdlsoap:body
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
        (5) 
      namespace="urn:DefaultNamespace" use="encoded"/> 
        (5) 
  </wsdl:input>
   <wsdl:output name="getNthSubjectResponse">
    <wsdlsoap:body
      encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
        (5) 
      namespace="urn:DefaultNamespace" use="encoded"/> 
        (5) 
  </wsdl:output>
  </wsdl:operation>
 </wsdl:binding>
 <wsdl:service name="GetSubjectElement"> 
        (2) 
  <wsdl:port binding="impl:GetSubjectPortSoapBinding"
                name="GetSubjectPort"> 
        (3) 
   <wsdlsoap:address location="http://localhost"/>
  </wsdl:port>
 </wsdl:service>
</wsdl:definitions>
      

(1) 端口类型定义一组操作。WSDL 文档包含 wsdl:portType 的名称属性,对应于 Port 类型名称高级属性。 (2) 服务标识支持的端口。WSDL 文档包含 wsdl:service 的名称属性,对应于 Service 元素名称高级属性。如果 WSDL 是通过 Export WSDL、Show WSDL 或 Domino Designer 中的浏览器预览获得的,则 wsdlsoap:address 的位置属性不正确;如果 WSDL 是通过 ?WSDL URL 命令从服务器中获得的,则位置属性是正确的。 (3) 端口标识绑定,而绑定又反过来标识端口类型并提供了其他信息。WSDL 文档包含 wsdl:service 中 wsdl:port 的名称属性。Domino 允许一个服务,并且每个服务允许一个端口。 (4) 两种编程模型和四种 SOAP 消息格式可用。RPC 编程模型允许四种 SOAP 消息格式:RPC/encoded、RPC/literal、Doc/literal 和 Wrapped(Doc/encoded 的实用程序是第五种可用格式,但因为不好理解,所以此处不支持)。Message 编程模型强制 Doc/literal 消息格式,但只作为提示;在基于 Message 的 Web 服务中传递的实际 SOAP 消息格式没有发布,但通过消费者和供应商之间的私有合同来规定。 wsdlsoap:binding 的样式属性设置如下:

  • 对于 RPC/encoded 和 RPC/literal,wsdlsoap:binding style="rpc"
  • 对于 Doc/literal 和 Wrapped,wsdlsoap:binding style="document"

(5) 在 wsdl:binding 下的输入和输出元素中,wsdlsoap:body 的使用属性设置如下:

  • 对于 RPC/encoded,wsdlsoap:body use="encoded"。在这一情况下,有一个 encodingStyle 属性。
  • 对于 RPC/literal、Doc/literal 和 Wrapped,wsdlsoap:body use="literal"。在这些情况下,没有 encodingStyle 属性。

(6) 对于 RPC/encoded 和 RPC/literal,每个消息部分通过直接引用 XMLSchema 名称空间(例如,type="xsd:string" 或 type="xsd:int")或 WSDL "types" 部分(本例未显示)中定义的复杂类型来定义数据类型。

对于 Doc/literal,每个消息部分引用先前定义的数据元素。下面是带有指定 Doc/literal 的示例 WSDL 中的代码段。在 wsdl:types 下,每个输出部分在按照过程代码中相应参数命名的元素中定义,输出部分在按照过程加“Return”命名的元素中定义。

<wsdl:types>
  <schema targetNamespace="urn:DefaultNamespace"
          xmlns="http://www.w3.org/2001/XMLSchema">
   <element name="dbname" type="xsd:string"/>
   <element name="viewname" type="xsd:string"/>
   <element name="n" type="xsd:int"/>
   <element name="getNthSubjectReturn" type="xsd:string"/>
  </schema>
</wsdl:types>
<wsdl:message name="getNthSubjectResponse">
  <wsdl:part element="impl:getNthSubjectReturn"
             name="getNthSubjectReturn"/>
</wsdl:message>
<wsdl:message name="getNthSubjectRequest">
  <wsdl:part element="impl:dbname" name="dbname"/>
  <wsdl:part element="impl:viewname" name="viewname"/>
  <wsdl:part element="impl:n" name="n"/>
</wsdl:message>

对于 Wrapped,每个消息有一个部分,该部分引用先前定义的 complexType 类型的元素,元素按照使用它且无属性的操作命名。下面是具有指定 Wrapped 的 WSDL 代码段。

<wsdl:types>
  <schema targetNamespace="urn:DefaultNamespace"
          xmlns="http://www.w3.org/2001/XMLSchema">
   <element name="getNthSubject">
    <complexType>
     <sequence>
      <element name="dbname" type="xsd:string"/>
      <element name="viewname" type="xsd:string"/>
      <element name="n" type="xsd:int"/>
     </sequence>
    </complexType>
   </element>
   <element name="getNthSubjectResponse">
    <complexType>
     <sequence>
      <element name="getNthSubjectReturn" type="xsd:string"/>
     </sequence>
    </complexType>
   </element>
  </schema>
</wsdl:types>
<wsdl:message name="getNthSubjectResponse">
  <wsdl:part element="impl:getNthSubjectResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="getNthSubjectRequest">
  <wsdl:part element="impl:getNthSubject" name="parameters"/>
</wsdl:message>

有关 SOAP 格式的完美讨论,参阅由 Russell Butek 撰写的 developerWorks 文章“ Which style of WSDL should I use?”。

(7) soapAction="" if "Include operation name in SOAP action" 保留不选中。如果选中该选项,则 soapAction 指定操作的名称,例如:

<wsdlsoap:operation soapAction="getNthSubject"/>

安全性

Web 服务安全性类似于从 Web 中调用的服务器代理的安全性。下面是 Web Services Property 框中 Security 选项卡的示例。


图 7. Web Services Property 框中的 Security 选项卡
Web Services Property 框中的 Security 选项卡

前两行确定谁在运行 Web 服务,即谁是有效用户:如果两行都不使用,则有效用户是 Web 服务的所有者(编辑或签名设计元素的最后一个用户)。

  • 如果选中“Run as Web user”选项,则有效用户是协商网络访问包含 Web 服务的数据库的用户:如果数据库允许匿名访问则为 Anonymous,否则为提供给认证过程的名称。
  • 如果填充了“Run on behalf of”字段,则有效用户是该用户。

Web 服务的消费者必须能够协商访问服务器。如果 HTTP 端口允许匿名访问,则访问自动进行。否则,用户必须提供有效的名称和 Internet 密码进行认证。数据库 ACL 必须给予有效用户至少一个选中 Read 公共文档的 Depositor 访问权。

“Compile Java code with debugging information”允许从 Java 调试器(比如支持 JPDA (Java Platform Debugger Architecture,Java 平台调试器架构)的 Eclipse)连接到运行中的 Web 服务。Java 调试是版本 7 的新特性,且仅工作在 Notes 客户机上。为了调试,Web 服务必须驻留在 Notes 客户机上。通过选择任何位置的 Web Browser 中的 Design - Preview,启动客户机上的 HTTP 任务。调用 Web 服务。Web 服务应包含只调试代码,以暂停片刻。然后将调试器连接到运行中的 Web 服务。

对于 LotusScript Web 服务,“Allow remote debugging”代替 Java 调试行。Web 服务的远程调试与代理的远程调试相同。在这种情况下,Web 服务必须驻留在服务器上。

“Profile this Web service”允许收集 Domino Objects 用去的时间。要报告所选 Web 服务的结果,选择 Design - View Profile Results。概要分析是版本 7 的新特性,用于 LotusScript 和 Java 编码的代理,以及 Web 服务。

“Set runtime security level”框允许三个级别的安全性。编号越高的安全性级别允许潜在损坏操作,比如写入文件系统,操作环境变量,等等。

对于“Default access to this Web service”,可以允许所有读者及以上用户,或者可以列举具有访问权的用户。

Web 服务上下文

Web 服务使用与代理相同的框架。在后端,大多数但非全部代理上下文应用于 Web 服务。我们已经看到如何在 Java 中获得 Session 和 AgentContext 对象,如何在 LotusScript 中获得 NotesSession 对象。下面是与 Web 服务关联的其他主要上下文元素。

上下文元素 Java LotusScript
当前 Web 服务AgentContext.getCurrentAgent();NotesSession.CurrentAgent
当前数据库AgentContext.getCurrentDatabase();NotesSession.CurrentDatabase
打印到服务器控制台和 log.nsfSystem.outMessagebox
Web 服务名称和别名Agent.getName();NotesAgent.Name
Web 服务所有者(完整名称)Agent.getOwner();NotesAgent.Owner
Web 服务所有者(共用名称)Agent.getCommonOwner();NotesAgent.CommonOwner
Web 服务运行时所有者Agent.getOnBehalfOf();NotesAgent.OnBehalfOf
Web 服务备注Agent.getComment();NotesAgent.Comment
Web 服务 HTTP URLAgent.getHttpURL();NotesAgent.HttpURL
Web 服务 Notes URLAgent.getNotesURL();NotesAgent.NotesURL
Web 服务父数据库Agent.getParent();NotesAgent.Parent
Web 服务锁持有者Agent.getLockHolders();NotesAgent.LockHolders

Web 服务设计元素与代理一样,可以加锁和解锁。

下面是 LotusScript 示例,展示了获得与 Web 服务上下文关联的属性。Web 服务具有三个操作。

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Dim agent As NotesAgent
Class GetAgentContext
  
  Sub NEW
    Set s = New NotesSession
    Set agent = s.CurrentAgent
  End Sub
  
  Function getAgentName() As String
    getAgentName = agent.Name
  End Function
  
  Function getEffectiveUserName() As String
    getEffectiveUserName = s.EffectiveUserName
  End Function
  
  Function getDatabaseFileName() As String
    Dim db As NotesDatabase
    Set db = s.CurrentDatabase
    getDatabaseFileName = db.FileName
  End Function
  
End Class

下面是 Java 代码。

import lotus.domino.*;
import lotus.domino.types.*;
public class GetAgentContext {
  
  Session s;
  AgentContext ac;
  
  public GetAgentContext() {
    s = WebServiceBase.getCurrentSession();
    try {
      ac = s.getAgentContext();
    } catch(Exception e) {
      e.printStackTrace(); }
  }
  public java.lang.String getAgentName() {
    String agentName = null;
    try {
      Agent agent = ac.getCurrentAgent();
      agentName = agent.getName();  }
    catch(Exception e) {
      e.printStackTrace(); }
    return agentName;
  }
  public java.lang.String getEffectiveUserName() {
    String userName = null;
    try {
      userName = ac.getEffectiveUserName();  }
    catch(Exception e) {
      e.printStackTrace(); }
    return userName;
  }
  public java.lang.String getCurrentDatabase() {
    String dbFileName = null;
    try {
      Database db = ac.getCurrentDatabase();
      dbFileName = db.getFileName();  }
    catch(Exception e) {
      e.printStackTrace(); }
    return dbFileName;
  }
}

复杂数据类型

使用下列模型的操作不需要复杂数据类型:

  • 单个标量输出值(或无输出值)
  • 标量输入值(或无输入值)

返回多个标量输出值或接受多个标量输入值的操作需要复杂数据类型。使用复杂数据类型允许移动大的、各种不同的数据结构。

下面几节讨论复杂数据类型:

  • 数组
  • Inout 和输出参数

数组
数组映射为按数据类型加后缀的名为 ArrayOf 的 complexType WSDL 元素。WSDL 将 complexType 元素定义为数组。

例如,按 Java 方法实现的下列操作返回 String 数组。

public java.lang.String[] getAll() {
  String[] info = new String[3];
  try {
    info[0] = ac.getEffectiveUserName();
    info[1] = s.getPlatform();
    info[2] = s.getNotesVersion(); }
  catch(Exception e) {
    e.printStackTrace(); }
  return info;
}

Java String 数组映射为名为 ArrayOf_xsd_string 的 WSDL complexType 元素,该元素被定义为 string 类型的数组。定义 getAll 操作 (getAllResponse) 返回值的消息有一个部分,其类型为 ArrayOf_xsd_string。

- <wsdl:types>
  - <schema targetNamespace="urn:DefaultNamespace"
      xmlns="http://www.w3.org/2001/XMLSchema">
      <import namespace="http://schemas.xmlsoap.org/soap/encoding/" /> 
    - <complexType name="ArrayOf_xsd_string">
      - <complexContent>
        - <restriction base="soapenc:Array">
            <attribute ref="soapenc:arrayType"
              wsdl:arrayType="xsd:string[]" /> 
          </restriction>
        </complexContent>
      </complexType>
    </schema>
  </wsdl:types>
- <wsdl:message name="getAllResponse">
    <wsdl:part name="getAllReturn" type="impl:ArrayOf_xsd_string" /> 
  </wsdl:message>

在 LotusScript 中,不能为 Web 服务消费者返回数组。语言规则要求数据返回值必须定义为不提供足够信息的 Variant,以便在生成 WSDL 时解释类型。解决方案是将数组放在类中,如下所示。

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Class infoArray
  Public info() As String
End Class
Class GetSessionInfo
  Sub NEW
    Set s = New NotesSession
  End Sub
  
  Function getItAll() As infoArray
    Set getItAll = New infoArray
    Redim getItAll.info(1 To 3)
    getItAll.info(1) = s.EffectiveUserName
    getItAll.info(2) = s.Platform
    getItAll.info(3) = s.NotesVersion
  End Function
End Class


类映射为按类命名的 complexType WSDL 元素。下面的 Java 示例提供与 Arrays 示例相同的数据,但不是返回数组,而是返回对象。

public InfoClass getAll2() {
  InfoClass info = new InfoClass();
  try {
    info.effectiveUserName = ac.getEffectiveUserName();
    info.platform = s.getPlatform();
    info.notesVersion = s.getNotesVersion(); }
  catch(Exception e) {
    e.printStackTrace(); }
  return info;
}
public class InfoClass {
  public String effectiveUserName;
  public String platform;
  public String notesVersion;
}

Java 类 InfoClass 映射为同名的 complexType。complexType 有三个元素,每个元素的类型都为 xsd:string,按 Java InfoClass 类中的公共数据元素命名。

- <wsdl:types>
  - <schema targetNamespace="urn:DefaultNamespace"
      xmlns="http://www.w3.org/2001/XMLSchema">
      <import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
    - <complexType name="InfoClass">
      - <sequence>
          <element name="notesVersion"
            nillable="true" type="xsd:string" /> 
          <element name="platform"
            nillable="true" type="xsd:string" /> 
          <element name="effectiveUserName"
            nillable="true" type="xsd:string" /> 
        </sequence>
      </complexType>
    </schema>
  </wsdl:types>
- <wsdl:message name="getAll2Response">
    <wsdl:part name="getAll2Return" type="impl:InfoClass" /> 
  </wsdl:message>

下面是等价的 LotusScript 示例。

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Class InfoClass
  Public EffectiveUserName As String
  Public Platform As String
  Public NotesVersion As String
End Class
Class GetSessionInfo
  Sub NEW
    Set s = New NotesSession
  End Sub
  
  Function getItAll2() As InfoClass
    Set getItAll2 = New InfoClass
    getItAll2.EffectiveUserName = s.EffectiveUserName
    getItAll2.Platform = s.Platform
    getItAll2.NotesVersion = s.NotesVersion
  End Function
End Class

Inout 和输出参数
当输出消息有一个部分时,不管它是简单类型还是复杂类型,输出都映射为函数或方法的返回值。如果输出消息有多个部分,则输出映射为参数,而非返回值。完整的映射取决于输入部分以及输入部分与输出部分的组合。如果第一个输出部分与任何输入都不匹配,且其余输出部分与输入部分相匹配,则第一个输出部分映射为函数或方法的返回值,而其余部分映射为 inout 参数。

否则,匹配的输入和输出部分映射为 inout 参数,不匹配的输入部分映射为输入参数,不匹配的输出部分映射为输出参数。在这种情况下,没有返回值,而且对于 LotusScript,使用子程序而非函数。

下列 WSDL 代码段是第一个示例的变种,它返回输入值作为响应:

- <wsdl:message name="getNthSubjectResponse">
    <wsdl:part name="getNthSubjectReturn" type="xsd:string" /> 
        (1)
    <wsdl:part name="dbname" type="xsd:string" /> 
        (2)
    <wsdl:part name="viewname" type="xsd:string" /> 
        (3)
    <wsdl:part name="n" type="xsd:int" /> 
        (4)
  </wsdl:message>
- <wsdl:message name="getNthSubjectRequest">
    <wsdl:part name="dbname" type="xsd:string" /> 
        (2)
    <wsdl:part name="viewname" type="xsd:string" /> 
        (3)
    <wsdl:part name="n" type="xsd:int" /> 
        (4)
  </wsdl:message>
      

(1) 一个输出部分与输入部分不匹配 —— getNthSubjectReturn。该部分映射为函数或方法返回值。 (2) (3) (4) 其余三个输出部分 —— dbname、viewname 和 n —— 与三个输入部分相同。这几个部分映射为 inout 参数。

Inout 和输出参数不能是基本数据类型。标准 Java 提供包 javax.xml.rpc.holders,其中具有保存各种类型的 inout 和输出参数的方法。Lotus Domino 将 inout 和输出参数映射为下列类,如下所示:

BigDecimalHolderCalendarHolderLongHolder
BigIntegerHolderDoubleHolderLongWrapperHolder
BooleanHolderDoubleWrapperHolderObjectHolder
BooleanWrapperHolderFloatHolderQNameHolder
ByteArrayHolderFloatWrapperHolderShortHolder
ByteHolderIntegerWrapperHolderShortWrapperHolder
ByteWrapperHolderIntHolderStringHolder

这些类有一个应用程序可以获得和设置的公共变量“value”。下例是 getNthSubject 示例的变种,它像以前一样返回一个 String,但通过使用 StringHolder 和 IntHolder 类生成三个 inout 参数。这些参数的值作为 SOAP 响应传回给消费者。

import lotus.domino.*;
import lotus.domino.types.*;
public class GetSubject {
  
  Session s;
  
  public GetSubject() {
    s = WebServiceBase.getCurrentSession();
  }
  public String getNthSubject(javax.xml.rpc.holders.StringHolder dbname,
      javax.xml.rpc.holders.StringHolder viewname,
      javax.xml.rpc.holders.IntHolder n) {
    String subject = null;
    try {
      Database db = s.getDatabase(null, dbname.value);
      if (!db.isOpen()) subject = "Cannot open database " + dbname.value;
      else {
        View view = db.getView(viewname.value);
        if (view == null) subject = "Cannot open view " + viewname.value;
        else {
          Document doc = view.getNthDocument(n.value);
          if (doc == null) subject = "Cannot get document " + n.value;
          else {
            if (doc.hasItem("Subject"))
              subject = doc.getItemValueString("Subject");
            else subject = "Document does not have Subject";
          }
        }
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    
    return subject;
  }
}

对于 LotusScript,include 文件 lsxsd.lss 为 inout 和输出参数定义了下列持有者类。

BOOLEAN_HOLDERLONG_HOLDER
BOOLEANARRAY_HOLDERLONGARRAY_HOLDER
BYTE_HOLDERSINGLE_HOLDER
BYTEARRAY_HOLDERSINGLEARRAY_HOLDER
DOUBLE_HOLDERSTRING_HOLDER
DOUBLEARRAY_HOLDERSTRINGARRAY_HOLDER
INTEGER_HOLDERVARIANT_HOLDER
INTEGERARRAY_HOLDERVARIANTARRAY_HOLDER

这些类有一个应用程序可以获得和设置的公共变量“Value”。下一个 LotusScript 示例与前面的 Java 示例相同。持有者类用于三个 inout 参数。

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Class GetSubject
  
  Sub NEW
    Set s = New NotesSession
  End Sub
  
  Function getNthSubject(dbname As String_Holder, _
  viewname As String_Holder, _
  n As Long_Holder) As String
    Dim db As NotesDatabase
    Dim view As NotesView
    Dim doc As NotesDocument
    Set db = s.GetDatabase("", dbname.Value)
    If Not(db.IsOpen) Then
      getNthSubject = "Cannot open database " & _
          dbname.Value
      Exit Function
    End If
    
    Set view = db.GetView(viewname.Value)
    If view Is Nothing Then
      getNthSubject = "Cannot open view " & _
           viewname.Value
      Exit Function
    End If
    Set doc = view.GetNthDocument(n.Value)
    If doc Is Nothing Then
      getNthSubject = "Cannot get document " & _
          n.Value
      Exit Function
    End If
    If doc.HasItem("Subject") Then
      getNthSubject = doc.GetItemValue("Subject")(0)
    Else
      getNthSubject = "Document does not have Subject"
    End If
  End Function
  
End Class

数据类型映射

基本数据类型及其 XSD 对应物一般来回映射。例外情况是导入的 SOAPENC 数据类型映射为对象。但是,对象在输出到生成的 WSDL 时,映射为 XSD 数据类型。

导入的 WSDL Java 数据类型
LotusScript 数据类型
生成的 WSDL
xsd:booleanboolean
Boolean
xsd:boolean
soapenc:booleanjava.lang.Boolean
XSD_BOOLEAN (1)
xsd:boolean
xsd:bytebyte
XSD_BYTE (2)
xsd:byte
soapenc:bytejava.lang.Byte
XSD_BYTE
xsd:byte
xsd:doubledouble
Double
xsd:double
soapenc:doublejava.lang.Double
XSD_DOUBLE
xsd:double
xsd:floatfloat
Single
xsd:float
soapenc:floatjava.lang.Float
XSD_FLOAT
xsd:float
xsd:intint
Long
xsd:int
soapenc:intjava.lang.Integer
XSD_INT
xsd:int
xsd:longlong
XSD_LONG (3)
xsd:long
soapenc:longjava.lang.Long
XSD_LONG
xsd:long
xsd:shortshort
Integer
xsd:short
soapenc:shortjava.lang.Short
XSD_SHORT
xsd:short
xsd:stringjava.lang.String (4)
String
xsd:string
soapenc:stringjava.lang.String
XSD_STRING
xsd:string

(1) Java 使用 java.lang 中定义的包装器类:java.lang.Boolean、java.lang.Byte,等等。LotusScript 使用 lsxsd.lss 中定义的 XSD_ 类:XSD_BOOLEAN、XSD_BYTE,等等。LotusScript 类继承下列方法:

Function GetValueAsString() As String
Sub SetValueAsString(value As String)

注意: 在未来的 Beta 版本中,名称 SetValueAsString 将更改为 SetValueFromString。

下面是返回 java.lang.Boolean 类型的操作的 Java 示例:

import lotus.domino.*;
import lotus.domino.types.*;
public class GetDatabaseInfo {
  
  Session s;
  AgentContext ac;
  Database db;
  
  public GetDatabaseInfo() {
    s = WebServiceBase.getCurrentSession();
    try {
      ac = s.getAgentContext();
      db = ac.getCurrentDatabase();
    } catch(Exception e) {
      e.printStackTrace(); }
  }
  public Boolean doesViewExist(String viewName) {
    Boolean b = null;
    try {
      if (db.getView(viewName) == null)
        b = new Boolean(false);
      else
        b = new Boolean(true);
    } catch(Exception e) {
      e.printStackTrace(); }
    return b;
  }
}

LotusScript 中的对应操作返回 XSD_BOOLEAN 类型:

Option Public
%INCLUDE "lsxsd.lss"
Dim s As NotesSession
Dim db As NotesDatabase
Class GetDatabaseInfo
  
  Sub NEW
    Set s = New NotesSession
    Set db = s.CurrentDatabase
  End Sub
  
  Function DoesViewExist(viewName As String) As XSD_BOOLEAN
    Set b = New XSD_BOOLEAN
    If db.GetView(viewName) Is Nothing Then
      Call b.SetValueAsString("False")
    Else
      Call b.SetValueAsString("True")
    End If
    Set DoesViewExist = b
  End Function
  
End Class

(2) LotusScript 不为 xsd:byte 使用基本数据类型。它通常映射为 XSD_BYTE(LotusScript 基本数据类型映射为 xsd:unsignedByte)。 (3) LotusScript 不为 xsd:long 使用基本数据类型。它通常映射为 XSD_LONG(LotusScript 基本数据类型映射为 xsd:int)。 (4) Java 没有 xsd:string 的基本数据类型。它通常映射为 java.lang.String。

其他 XSD 数据类型在 Java 中映射为 java.lang、java.math、java.util 和 lotus.domino.types(Lotus Notes/Domino 7 的新特性)对象,在 LotusScript 中映射为 XSD_ objects。

WSDL Java 数据类型
LotusScript 数据类型
xsd:anyTypejava.lang.Object
XSD_ANYTYPE
Variant (1)
xsd:anyURIlotus.domino.types.URI
XSD_ANYURI
xsd:base64Binary
soapenc:base64 (2)
byte[]
xsd:datejava.util.Date
XSD_DATE
xsd:dateTimejava.util.Calendar
XSD_DATETIME
xsd:decimal
soapenc:decimal (3)
java.math.BigDecimal
XSD_DECIMAL
xsd:durationlotus.domino.types.Duration
XSD_DURATION
xsd:ENTITYlotus.domino.types.Entity
XSD_ENTITY
xsd:ENTITESlotus.domino.types.Entities
XSD_ENTITIES
xsd:gDaylotus.domino.types.GDay
XSD_GDAY
xsd:gMonthlotus.domino.types.GMonth
XSD_GMONTH
xsd:gMonthDaylotus.domino.types.GMonthDay
XSD_GMONTHDAY
xsd:gYearlotus.domino.types.GYear
XSD_GYEAR
xsd:gYearMonthlotus.domino.types.GYearMonth
XSD_GYEARMONTH
xsd:hexBinarylotus.domino.types.HexBinary
XSD_HEXBINARY
xsd:IDlotus.domino.types.Id
XSD_ID
xsd:IDREFlotus.domino.types.IDRef
XSD_IDREF
xsd:IDREFSlotus.domino.types.IDRefs
XSD_IDREFS
xsd:integer
soapenc:integer (3)
java.math.BigInteger
XSD_INTEGER
xsd:languagelotus.domino.types.Language
XSD_LANGUAGE
xsd:Namelotus.domino.types.Name
XSD_NAME
xsd:NCNamelotus.domino.types.NCName
XSD_NCNAME
xsd:negativeIntegerlotus.domino.types.NegativeInteger
XSD_NEGATIVEINTEGER
xsd:NMTOKENlotus.domino.types.NMToken
XSD_NMTOKEN
xsd:NMTOKENSlotus.domino.types.NMTokens
XSD_NMTOKENS
xsd:nonNegativeIntegerlotus.domino.types.NonNegativeInteger
XSD_NONNEGATIVEINTEGER
xsd:nonPositiveIntegerlotus.domino.types.NonPositiveInteger
XSD_NONPOSITIVEINTEGER
xsd:NOTATIONlotus.domino.types.Notation
XSD_NOTATION
xsd:normalizedStringlotus.domino.types.NormalizedString
XSD_NORMALIZEDSTRING
xsd:positiveIntegerlotus.domino.types.PositiveInteger
XSD_NONPOSITIVEINTEGER
xsd:QNamejavax.xml.namespace.QName
XSD_QNAME
xsd:timelotus.domino.types.Time
XSD_TIME
xsd:tokenlotus.domino.types.Token
XSD_TOKEN
xsd:unsignedBytelotus.domino.types.UnsignedByte
Byte
XSD_UNSIGNEDBYTE (4)
xsd:unsignedIntlotus.domino.types.UnsignedInt
XSD_UNSIGNEDINT
xsd:unsignedLonglotus.domino.types.UnsignedLong
XSD_UNSIGNEDLONG
xsd:unsignedShortlotus.domino.types.UnsignedShort
XSD_UNSIGNEDSHORT

(1) Variant 在输出到生成的 WSDL 时映射为 xsd:anyType。 (2) soapenc:base64 在从 WSDL 导入时映射为 byte[] 和 Byte。生成的 WSDL 通常映射为 xsd:base64Binary。 (3) soapenc:decimal 和 soapenc:integer 在从 WSDL 导入时映射为 XSD:DECIMAL 和 XSD:INTEGER。生成的 WSDL 通常映射为 xsd:decimal 和 xsd:integer。 (4) xsd:unsignedByte 在从 WSDL 导入时映射为 Byte。Byte 和 XSD_UNSIGNEDBYTE 在生成的 WSDL 中都映射为 xsd:unsignedByte。

私有过程

Domino Web 服务在实现类中暴露公共函数、子程序和方法。私有过程被隐藏了。下面是 GetSubject 示例的变种,它使用公共过程来暴露操作 getFirstSubject、getLastSubject 和 getNthSubject。公用代码通过私有过程 openDatabase、openView 和 getSubject 提供。

Dim s As NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim doc As NotesDocument
Dim msg As String
Class GetSubject
  
  Sub NEW
    Set s = New NotesSession
  End Sub
  
  Function getFirstSubject(dbname As String, viewname As String) As String
    If openDatabase(dbname) Then
      If openView(viewname) Then
        Set doc = view.GetFirstDocument
        If doc Is Nothing Then
          msg = "Cannot get first document "
        Else
          Call getSubject
        End If
      End If
    End If
    getFirstSubject = msg
  End Function
 Function getLastSubject(dbname As String, viewname As String) As String
    If openDatabase(dbname) Then
      If openView(viewname) Then
        Set doc = view.GetLastDocument
        If doc Is Nothing Then
          msg = "Cannot get last document "
        Else
          Call getSubject
        End If
      End If
    End If
    getLastSubject = msg
  End Function
  
  Function getNthSubject(dbname As String, viewname As String, n As Integer) As String
    If openDatabase(dbname) Then
      If openView(viewname) Then
        Set doc = view.GetNthDocument(n)
        If doc Is Nothing Then
          msg = "Cannot get document " & n
        Else
          Call getSubject
        End If
      End If
    End If
    getNthSubject = msg
  End Function
  
  Private  Function openDatabase(dbname As String) As Boolean
    Set db = s.GetDatabase("", dbname)
    If db.IsOpen Then
      openDatabase = True
    Else
      openDatabase = False
      msg = "Cannot open database " & dbname
    End If
  End Function
  
  Private Function openView(viewname As String) As Boolean
    Set view = db.GetView(viewname)
    If view Is Nothing Then
      openView = False
      msg = "Cannot open view " & viewname
    Else
      openView = True
    End If
  End Function
  
  Private Sub getSubject
    If doc.HasItem("Subject") Then
      msg = doc.GetItemValue("Subject")(0)
    Else
      msg = "Document does not have Subject"
    End If
  End Sub
  
End Class

下面是 Java 示例。

import lotus.domino.*;
import lotus.domino.types.*;
public class GetSubject {
  
  Session s;
  Database db;
  View view;
  Document doc;
  String msg;
  
  public GetSubject() {
    s = WebServiceBase.getCurrentSession();
  }
  public String getFirstSubject(String dbname, String viewname) {
    try {
      if (openDatabase(dbname)) {
        if (openView(viewname)) {
          doc = view.getFirstDocument();
          if (doc == null)
            msg = "Cannot get first document ";
          else
            getSubject();
        }
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    return msg;
  }
  public String getLastSubject(String dbname, String viewname) {
    try {
      if (openDatabase(dbname)) {
        if (openView(viewname)) {
          doc = view.getLastDocument();
          if (doc == null)
            msg = "Cannot get last document ";
          else
            getSubject();
        }
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    return msg;
  }
  public String getNthSubject(String dbname, String viewname, int n) {
    try {
      if (openDatabase(dbname)) {
        if (openView(viewname)) {
          doc = view.getNthDocument(n);
          if (doc == null)
            msg = "Cannot get document " + n;
          else
            getSubject();
        }
      }
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    return msg;
  }
  private boolean openDatabase(String dbname) {
    boolean b = false;
    try {
      db = s.getDatabase(null, dbname);
      if (db.isOpen())
        b = true;
      else
        msg = "Cannot open database " + dbname;
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    return b;
  }
  private boolean openView(String viewname) {
    boolean b = false;
    try {
      view = db.getView(viewname);
      if (view != null)
        b = true;
      else
        msg = "Cannot open view " + viewname;
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    return b;
  }
  private void getSubject() {
    try {
      if (doc.hasItem("Subject"))
        msg = doc.getItemValueString("Subject");
      else
        msg = "Document does not have Subject";
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
 
}





回页首


结束语

Lotus Notes/Domino 7 通过用 Java 或 LotusScript 编码的类似代理的设计元素来支持 Web 服务的供应商端。Web 服务必须驻留在启用 HTTP 的 Domino 7 服务器上,此外,Web 服务可以通过 Notes 客户机上的 Web 预览来测试和调试。消费者通过 SOAP 编码的 HTTP POST 请求来访问 Domino Web 服务。

Web 服务操作映射为公共 Java 方法和公共 LotusScript 函数和子程序。Web 服务数据部分映射为参数和返回值。可能的话,XSD 数据类型映射为 Java 和 LotusScript 基本类型。否则,complexType 元素映射为对象。

本文基于 Lotus Notes/Domino 7 的 Beta 2 版本。在开发过程中可能进行增强。例如,未来版本预期支持将 Web 服务代码放置在脚本库中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值