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.nsf System.out Messagebox
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 URL Agent.getHttpURL(); NotesAgent.HttpURL
Web 服務 Notes URL Agent.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 和輸出參數映射爲下列類,如下所示:

BigDecimalHolder CalendarHolder LongHolder
BigIntegerHolder DoubleHolder LongWrapperHolder
BooleanHolder DoubleWrapperHolder ObjectHolder
BooleanWrapperHolder FloatHolder QNameHolder
ByteArrayHolder FloatWrapperHolder ShortHolder
ByteHolder IntegerWrapperHolder ShortWrapperHolder
ByteWrapperHolder IntHolder StringHolder

這些類有一個應用程序可以獲得和設置的公共變量“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_HOLDER LONG_HOLDER
BOOLEANARRAY_HOLDER LONGARRAY_HOLDER
BYTE_HOLDER SINGLE_HOLDER
BYTEARRAY_HOLDER SINGLEARRAY_HOLDER
DOUBLE_HOLDER STRING_HOLDER
DOUBLEARRAY_HOLDER STRINGARRAY_HOLDER
INTEGER_HOLDER VARIANT_HOLDER
INTEGERARRAY_HOLDER VARIANTARRAY_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:boolean boolean
Boolean
xsd:boolean
soapenc:boolean java.lang.Boolean
XSD_BOOLEAN (1)
xsd:boolean
xsd:byte byte
XSD_BYTE (2)
xsd:byte
soapenc:byte java.lang.Byte
XSD_BYTE
xsd:byte
xsd:double double
Double
xsd:double
soapenc:double java.lang.Double
XSD_DOUBLE
xsd:double
xsd:float float
Single
xsd:float
soapenc:float java.lang.Float
XSD_FLOAT
xsd:float
xsd:int int
Long
xsd:int
soapenc:int java.lang.Integer
XSD_INT
xsd:int
xsd:long long
XSD_LONG (3)
xsd:long
soapenc:long java.lang.Long
XSD_LONG
xsd:long
xsd:short short
Integer
xsd:short
soapenc:short java.lang.Short
XSD_SHORT
xsd:short
xsd:string java.lang.String (4)
String
xsd:string
soapenc:string java.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:anyType java.lang.Object
XSD_ANYTYPE
Variant (1)
xsd:anyURI lotus.domino.types.URI
XSD_ANYURI
xsd:base64Binary
soapenc:base64 (2)
byte[]
xsd:date java.util.Date
XSD_DATE
xsd:dateTime java.util.Calendar
XSD_DATETIME
xsd:decimal
soapenc:decimal (3)
java.math.BigDecimal
XSD_DECIMAL
xsd:duration lotus.domino.types.Duration
XSD_DURATION
xsd:ENTITY lotus.domino.types.Entity
XSD_ENTITY
xsd:ENTITES lotus.domino.types.Entities
XSD_ENTITIES
xsd:gDay lotus.domino.types.GDay
XSD_GDAY
xsd:gMonth lotus.domino.types.GMonth
XSD_GMONTH
xsd:gMonthDay lotus.domino.types.GMonthDay
XSD_GMONTHDAY
xsd:gYear lotus.domino.types.GYear
XSD_GYEAR
xsd:gYearMonth lotus.domino.types.GYearMonth
XSD_GYEARMONTH
xsd:hexBinary lotus.domino.types.HexBinary
XSD_HEXBINARY
xsd:ID lotus.domino.types.Id
XSD_ID
xsd:IDREF lotus.domino.types.IDRef
XSD_IDREF
xsd:IDREFS lotus.domino.types.IDRefs
XSD_IDREFS
xsd:integer
soapenc:integer (3)
java.math.BigInteger
XSD_INTEGER
xsd:language lotus.domino.types.Language
XSD_LANGUAGE
xsd:Name lotus.domino.types.Name
XSD_NAME
xsd:NCName lotus.domino.types.NCName
XSD_NCNAME
xsd:negativeInteger lotus.domino.types.NegativeInteger
XSD_NEGATIVEINTEGER
xsd:NMTOKEN lotus.domino.types.NMToken
XSD_NMTOKEN
xsd:NMTOKENS lotus.domino.types.NMTokens
XSD_NMTOKENS
xsd:nonNegativeInteger lotus.domino.types.NonNegativeInteger
XSD_NONNEGATIVEINTEGER
xsd:nonPositiveInteger lotus.domino.types.NonPositiveInteger
XSD_NONPOSITIVEINTEGER
xsd:NOTATION lotus.domino.types.Notation
XSD_NOTATION
xsd:normalizedString lotus.domino.types.NormalizedString
XSD_NORMALIZEDSTRING
xsd:positiveInteger lotus.domino.types.PositiveInteger
XSD_NONPOSITIVEINTEGER
xsd:QName javax.xml.namespace.QName
XSD_QNAME
xsd:time lotus.domino.types.Time
XSD_TIME
xsd:token lotus.domino.types.Token
XSD_TOKEN
xsd:unsignedByte lotus.domino.types.UnsignedByte
Byte
XSD_UNSIGNEDBYTE (4)
xsd:unsignedInt lotus.domino.types.UnsignedInt
XSD_UNSIGNEDINT
xsd:unsignedLong lotus.domino.types.UnsignedLong
XSD_UNSIGNEDLONG
xsd:unsignedShort lotus.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 服務代碼放置在腳本庫中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章