IBM Lotus Domino 7 中的實用 Web 服務,第 2 部分: 編寫和測試簡單的 Web 服務

IBM Lotus Domino 7 中的實用 Web 服務,第 2 部分: 編寫和測試簡單的 Web 服務

 

: 中級

Julian Robichaux, 開發人員, Independent Consultant

2006 年 12 月 26 日

在本 Web 服務系列文章的第 2 篇中,我們將演示如何在 IBM Lotus Domino V7.0 中編寫簡單的 Web 服務,該服務將接受並返回簡單的數據類型、數組以及 InOut 參數。我們還將討論幾個測試方法,會涉及 soapUI、Eclipse、MSSOAP toolkit 和 Apache Axis 測試工具。

您現在想要編寫 Web 服務。太棒了!如果您閱讀了我們的第一篇文章,“IBM Lotus Domino 7 中的實用 Web 服務:什麼是 Web 服務以及它們爲何如此重要”,那麼您已經對什麼是 Web 服務以及它們爲何如此重要有了很好的理解。通過 IBM Lotus Domino V7.0,您可以很方便地創建自己的 Web 服務,其他客戶機或系統可以使用這些 Web 服務。在某種程度上,它就像編寫代理一樣容易。

IBM Lotus Domino Designer 允許使用 LotusScript 或 Java 來編寫 Web 服務,但本文中所有的示例都是使用 LotusScript 編寫的。不過,本文的示例數據庫(請參閱 下載 部分)有用 LotusScript 和 Java 兩種語言編寫的示例 Web 服務以供參考。

背景知識簡介

Lotus Domino V7.0 在 Lotus Domino Designer 中引入了新的 Web 服務設計元素。如果在 Lotus Domino Designer V7.0 客戶機中打開數據庫,就可以看到 Web Services 條目正好位於常見的設計元素樹的 Shared Code 部分的 Agents 條目下(參見圖 1)。

Lotus Domino 負責處理所有的 WSDL 創建和 SOAP 操作,因此您所要做的事情就是在 Web 服務設計元素中編寫代碼,就像爲代理編寫代碼一樣。一旦指定哪一個類用作服務的接口類,Lotus Domino 就可以發佈 WSDL 文件、將引入的 SOAP 請求轉換爲類上的方法調用以及返回方法的結果(如果有的話)作爲 SOAP 響應。

從編寫代碼的立場上看,您所做的一切就是編寫 LotusScript 或 Java 類。Lotus Domino 完成了其餘工作!





回頁首


編寫一個簡單的 Web 服務

現在我們來編寫一個簡單的 Web 服務。爲了新建一個 Web 服務,在 Lotus Domino Designer 中打開數據庫,轉到數據庫設計的 Web Services 部分,然後單擊 New Web Service 按鈕(參見圖 1)。


圖 1. Lotus Domino Designer 中的 Web Service 設計元素部分
Lotus Domino Designer 中的 Web Service 設計元素部分

該屏幕與新建代理時打開的窗口(參見圖 2)很相似。在 Web Services Properties 框中,設置新 Web 服務的名稱 —— 本示例中使用 EchoTestService —— 然後關閉該框。稍後我們將討論 Properties 框中的各個字段。


圖 2. Lotus Domino Designer 中的 Web Service 設計元素
Lotus Domino Designer 中的 Web Service 設計元素

現在應該看到一個與編寫 LotusScript 代理時所使用的窗口很相似的屏幕。單擊 LotusScript 事件中 Objects 附籤的 (Declarations) 以編寫類(必須始終在 (Declarations) 部分中定義類)。將下列代碼輸入到 IDE:


清單 1. 一個非常簡單的返回字符串的 Web 服務
				
Class EchoTest
	Public Function Echo (txt As String) As String
		Echo = txt
	End Function
End Class

該代碼進行以下工作:

  • 創建類 EchoTest。
  • 在類中定義方法 Echo,該方法接受字符串作爲參數並返回字符串作爲結果(類中的函數和 sub 被稱爲方法)。

EchoTest 中的 Echo 方法獲取字符串作爲參數並返回相同的字符串。現在看一下它是否是有效的 Web 服務。嘗試保存並關閉該服務。將收到下面的錯誤:

The Web Service has been saved, but is not valid: 
Please specify which class exposes your Web service interface(s), 
using the 'PortType class' field of the Web Service properties panel.

若要避免此錯誤,請打開 Web Service Properties 框,然後指定要使用的類。因爲 Web 服務代碼中可能定義了多個類,所以必須僅選擇其中一個作爲 Web 服務的接口。接口類就是具有 Public 方法的類,Web 服務客戶機可以調用 Public 方法。

在 Properties 框中,在第一個附籤的 PortType class 字段中輸入 EchoTest(您剛剛編寫的類名)。關閉該框,然後再次嘗試保存並關閉 Web 服務。這次一切正常。現在您有了一個正常運轉的 Web 服務!





回頁首


Web Service Properties 框

下面再次打開 Web service 和 Web Service Properties 框。框中的第一個附籤(Basics 附籤)如圖 3 所示。


圖 3. Web Service Properties 框中的 Basics 附籤
Web Service Properties 框中的 Basics 附籤

對 Basic 附簽上的字段說明如下:

  • Name(必需的):Web 服務的名稱,是客戶機訪問 WSDL 文件或服務的方法時所使用的名稱。
  • Alias:除 Name 之外的另一名稱,用戶使用該名稱可以訪問服務。
  • Comment:有關 Web 服務的信息數據的字段(通常,該字段的信息不超過一句話;有關 Web 服務的較長描述或信息應寫在代碼的註釋中)。
  • Warn if the WSDL interface is modified:該選項警告您對代碼所做的更改是否修改了由 Web 服務產生的 WSDL 文件。這對於確保 WSDL 文件的一致很有用,但是應該意識到,如果選中了該選項,則您將無法保存帶有已修改的 WSDL 文件的服務。
  • PortType class(必需的):用作 Web 服務接口的類的名稱。換句話說,它就是 Web 服務代碼中帶有用戶可訪問的 public 方法的類。

框中的第二個附籤是 Security 附籤(參見圖 4)。


圖 4. Web Service Properties 框中的 Security 附籤
Web Service Properties 框中的 Security 附籤

對 Security 附簽上的字段說明如下:

  • Run as web user:該選項使 Web 服務代碼能夠在調用 Web 服務的用戶的安全性上下文中運行(默認情況下,它將在 Lotus Domino Designer 中最後簽名 Web 服務的那個 ID 的安全性上下文中運行)。
  • Run on behalf of:該字段允許指定用戶,如果想讓 Web 服務代碼運行在特定用戶的安全性上下文中,而不是 Lotus Domino Designer 中最後簽名 Web 服務的那個 ID 的安全性上下文中。
  • Allow remote debugging:該選項允許遠程調試 Web 服務(有關遠程調試的信息,請參閱 Lotus Domino Designer 幫助主題 “Using the Remote Debugger”)。
  • Profile this web service:該選項將在 Web 服務運行時使其生成分析信息(有關分析的信息,請參閱 Lotus Domino Designer 幫助主題 “Profiling agents and Web services”)。
  • Set runtime security level:設置爲 1,允許大多數 LotusScript 和 Java 操作正確運行;對於讀/寫文件、創建 COM 對象或執行網絡操作等,根據需要,設置爲 2 或 3(有關更多信息,請參閱 Lotus Domino Designer 幫助主題 “Restricted LotusScript and Java agent operations”)。
  • Default access for this web service:該選項允許控制哪些用戶可以訪問 Web 服務,並超出了使用數據庫 ACL 所能進行的控制(如果 Anonymous 用戶無法訪問 Web 服務,則當用戶嘗試進行連接時,將收到錯誤 401 Access Denied 或 404 Not Found)。
  • Allow Public Access users to use this web service:該選項使得僅擁有數據庫 ACL 中 “Read Public Documents” 訪問權的用戶可以使用該 Web 服務,當不想爲大量用戶授予完全的 Reader 訪問權限(或更高級別)時,這點很有用。

框中的第三個附籤是 Options 附籤(參見圖 5)。


圖 5. Web Service Properties 框中的 Options 附籤
Web Service Properties 框中的 Options 附籤

對 Options 附簽上的字段說明如下:

  • Programming model:可用選項是 RPC 或 Message(大多數情況下使用 RPC)。
  • SOAP message format:在該字段中,爲此 Web 服務選擇 SOAP 消息格式(有關格式的更多信息,請參閱下一節)。Lotus Domino V7.0 中的默認格式是 RPC/encoded。
  • Include operation name in SOAP action:該選項要求操作名稱存在於外來請求的 SOAP 動作標頭中(很少需要)。
  • Port type name:默認情況下,該字段值與 Basics 附簽上 PortType class 字段的值相同(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。
  • Service element name:默認情況下,該字段值是 PortType 名稱加上單詞 Service(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。
  • Service port name:默認情況下,該字段值是 Domino(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。

如您所見,可以設置很多屬性,儘管其中只有 Web service name 和 port type class 是必需的。其他所有屬性都是可選的或是有適當的默認值。

SOAP 消息格式

在 Web Service Properties 框中,有很多不同的 SOAP 消息格式可以選擇,所以不易決定到底應該使用哪一個。各種格式將創建略有不同的 WSDL 文件,反過來會產生略有不同的 SOAP 請求和響應。

從編寫代碼的立場看,您不會注意到這些不同,因爲無論使用哪一種格式,所編寫的 Web 服務是完全相同的。但是,這會使調用 Web 服務的用戶客戶機有所不同。

通常,RPC/encoded 格式是較早的 Web 服務客戶機技術(如 Apache SOAP 和 MSSOAP)廣泛支持的格式。Doc/literal 由 Microsoft .NET 客戶機和服務器默認使用,並在過去的幾年中漸受歡迎。

消息格式的選擇依賴於調用服務的客戶機所使用的技術以及哪一種 SOAP 格式最易於使用該客戶機技術。如果不能控制調用服務的客戶機,則 RPC/encoded 和 Doc/literal 都是很好的選擇。

有關不同格式以及其如何影響 WSDL 結構和 SOAP 消息的詳細說明,請參閱經常被提到的 developerWorks 文章 “Which style of WSDL should I use?”。





回頁首


使用簡單數據類型的 Web 服務

現在回過頭來編寫 Web 服務代碼。我們知道用來公開 Web 服務的 LotusScript 代碼需要作爲類進行編寫。實際上,通常用 LotusScript 編寫的任何函數或 sub 在 Web 服務中都是作爲類方法使用的,並帶有以下限制:

  • 不要使用原生 LotusScript 類(如 NotesDatabase、NotesDocument 等)作爲參數或返回值。
  • 不要使用變量或貨幣數據類型作爲參數或返回值。
  • 不要使用列表或數組作爲參數或返回值(可以使用數組,不過必須使用稍後在本文中所描述的一種特定數據類型)。
  • 不要使用定製類型作爲參數或返回值。

相反,可以在 Web 服務類方法中使用以下內容作爲參數或返回值:

  • 簡單的數據類型(字符串、整數等)
  • 定製的用戶定義的類
  • lsxsd.lss 文件中定義的特殊類(該文件包含在 Lotus Notes/Domino V7.0 客戶機和服務器文件中)

將用戶定義的類是一種複雜的數據類型,我們將在下一篇文章中進行討論。lsxsd.lss 文件(可以在本地的 Notes 程序目錄中找到)中的類是很有用的,允許傳遞字符串數組、文件和數據。稍後本文將對其中一些類進行討論,其餘的類將在下一篇文章中進行討論。

現在先來看一些在類中使用簡單數據類型的示例。考慮下面的類:


清單 2. 帶有多個方法的 LotusScript Web 服務
				
Class DatabaseInfo
	Private session As NotesSession
	Private db As NotesDatabase
	
	Public Sub New ()
		Set session = New NotesSession
		Set db = session.CurrentDatabase
	End Sub
	
	Public Function GetDbName () As String
		GetDbName = db.Title
	End Function
	
	Public Sub UpdateFTIndex ()
		Call db.UpdateFTIndex(True)
	End Sub
	
	Public Function GetUserRoles (userName As String) As String
		GetUserRoles = Join(getRoles(userName), ",")
	End Function
	
	Private Function getRoles (userName As String) As Variant
		Dim acl As NotesACL
		Dim entry As NotesACLEntry
		Dim sep As String
		
		Set acl = db.ACL
		Set entry = acl.GetEntry(userName)
		
		If (entry Is Nothing) Then
			Dim returnArray(0) As String
			getRoles = returnArray
		Else
			getRoles = entry.Roles
		End If
	End Function
End Class

以上代碼淺顯易懂,不過對於各種方法,請注意以下內容:

  • New:方法 New 是可選的,且不能用於那些調用 Web 服務的客戶機。如果需要的話,僅用於初始化代碼。同時,如果編寫 New 方法,那麼它必須是 sub 且沒有任何參數。
  • GetDbName:方法 GetDbName 沒有任何參數。這是規定的。
  • UpdateFTIndex:方法 UpdateFTIndex 沒有任何參數且不返回值。這也是規定的。
  • GetUserRoles:方法 GetUserRoles 將調用其他方法來執行大部分工作。也可以調用其他函數和 sub(類以外的),甚至可以使用 Use 語句引用 script 庫,從 script 庫中調用類、函數和 sub。這很有用,因爲這樣不僅可以保持 Web 服務代碼的簡潔,而且有助於從已有的任何業務邏輯代碼中分離出 Web 服務代碼。
  • getRoles:方法 getRoles 聲明爲 Private,因此類中的其他方法可以使用該方法,但是,不能用於那些調用 Web 服務的客戶機。將一些方法聲明爲 Private 是一個很好的做法,以便保持代碼和邏輯位於類中,同時不允許用戶直接調用方法。

    但是,請記住如果既沒有將方法聲明爲 Public,也沒有將其聲明爲 Private,則該方法將作爲 Public 方法使用。

到目前爲止,實際上沒有什麼複雜的東西。由您決定用戶可以調用的函數/sub,然後將其作爲方法包含在類中。如果已經編寫了所需的代碼或邏輯,那麼您還可以從 script 庫中引用其他類、函數和 sub。





回頁首


返回數組

您可能已注意到方法 GetUserRoles 在返回值前,將 getRoles 方法返回的字符串數組轉化爲單一的一個分隔的字符串。這是因爲不能直接從 Web 服務作爲數組或變量返回 LotusScript 數組。

但是,通過返回 lsxsd.lss 文件中其中一個 ARRAY_HOLDER 類的實例,可以返回數組。將 ARRAY_HOLDER 類(STRINGARRAY_HOLDER、INTEGERARRAY_HOLDER 等)作爲值返回時,這些類將自動轉換爲支持 SOAP 的數組。

爲了舉例說明,可以將 %INCLUDE "lsxsd.lss" 行添加到 Web 服務的 (Options) 部分,然後重寫 GetUserRoles 方法,如下所示:


清單 3. 在 LotusScript Web 服務中返回字符串數組
				
	Public Function GetUserRolesArray (userName As String) As STRINGARRAY_HOLDER
		Dim returnArray As New STRINGARRAY_HOLDER
		Dim roles As Variant
		Dim i As Integer
		
		roles = getRoles(userName)
		Redim returnArray.Value(Ubound(roles))
		For i = 0 To Ubound(roles)
			returnArray.Value(i) = roles(i)
		Next
		
		Set GetUserRolesArray = returnArray
	End Function

就用戶的客戶機而言,GetUserRolesArray 方法將返回常規的字符串數組,而不是特定的 STRINGARRAY_HOLDER 對象。這是因爲訪問服務時,Domino Web 服務在後臺完成了 STRINGARRAY_HOLDER 和字符串數組之間的轉化。還需要做一些額外工作將 getRoles 數組的元素添加到 STRINGARRAY_HOLDER 的 Value 成員中(因爲不能直接將 Value 設置爲等於另一個數組),不過這只是幾行代碼的事。

當然,字符串數組不是惟一可以接受或返回的數組類型,INTEGERARRAY_HOLDER、LONGARRAY_HOLDER、和 lsxsd.lss 文件中定義的類似的類也可以爲其他原生數據類型提供相同的功能。有關更多信息,請參閱 Lotus Domino Designer 幫助或 lsxsd.lss 文件。

返回數組的另一種選擇是將數組作爲複雜數據類型的組成部分返回,該技巧我們將在下一篇文章中進行討論。





回頁首


使用 InOut 參數返回多個值

當僅希望使用簡單數據類型時,另一種可以使用的方法是 InOut 參數。有些參數既可以接收輸入值,也可以返回輸出值。例如,考慮下面的類:


清單 4. 在 LotusScript Web 服務中使用 InOut 參數
				
Class InOutTest
	Public Sub AddOne (inout As INTEGER_HOLDER)
		inout.Value = inout.Value + 1
	End Sub
	
	Public Function SwapAndAdd (inout1 As INTEGER_HOLDER, _
	inout2 As INTEGER_HOLDER) As Integer
		SwapAndAdd = inout1.Value + inout2.Value
		inout1.Value = inout2.Value
		inout2.Value = SwapAndAdd - inout2.Value
	End Function
End Class

第一個方法 (AddOne) 使用整數作爲輸入參數。方法中的代碼爲傳遞的值增加 1 —— 因爲它是 INTEGER_HOLDER —— 並將新值返回到 SOAP 響應中。

這是 lsxsd.lss 文件中所定義的 HOLDER 類的特殊屬性。將該類用作方法參數時,它們將變成 SOAP 請求/響應中的 InOut 參數,因此可以接收並返回值。

方法 AddOne 並不是一個很實際的示例,因爲通常只需接收常規整數作爲參數,並且作爲能返回修改的整數的函數編寫此方法。但是,如果有一個或多個 InOut 參數作爲方法返回值,那麼就可以在方法響應中返回多個獨立的值而不是單個值。

現在看一下第二個方法 SwapAndAdd。該方法有兩個 InOut 值作爲參數,並返回整數。在用戶客戶機上,它們生成 SOAP 請求用來作爲參數發送兩個整數值,並且接收 SOAP 請求,該 SOAP 請求的響應具有三個整數值:其中兩個作爲參數進行傳遞(並且通過方法進行修改),另一個是結果。

不可否認,InOut 參數不那麼常見,因爲返回多個值通常是通過返回複雜數據類型來處理的,但這仍是個值得注意的好方法。再次說明,我們將在本系列的下一篇文章中討論複雜數據類型。





回頁首


使用日期和時間

您需要使用的最後一個簡單數據類型是日期/時間對象。下面的示例演示了使用參數中的日期/時間並返回對象:


清單 5. 在 LotusScript Web 服務中使用日期和時間
				
Class DateTester
	Public Function getCurrentTime () As XSD_DATETIME
		Dim dt As New NotesDateTime(Now)
		Set getCurrentTime = New XSD_DATETIME
		Call getCurrentTime.SetValueFromNotesDateTime(dt)
	End Function
 	
	Public Function getLocalDateFormat (xdt As XSD_DATETIME) As String
		Dim dt As NotesDateTime
		Set dt = xdt.GetValueAsNotesDateTime()
		getLocalDateFormat = dt.LocalTime
	End Function
End Class

lsxsd.lss 類再次發揮了作用。可以只接收或返回 XSD_DATETIME(變成了 SOAP dateTime 元素)類型變量並在它與 NotesDateTime 對象之間進行轉換。

但是,應注意到時間值的時區處理會比較困難,因爲服務器和客戶機可能正確也可能會不正確地添加或解釋 SOAP dateTime 元素的時區偏移。最新的 W3C Note 對該問題的某些方面進行了討論。通常,首先應試着徹底測試 Web 服務客戶機。





回頁首


測試 Web 服務

在本地數據庫上測試 Web 服務

如果您有數據庫的本地副本和要測試的 Web 服務,那麼首先請確保 Notes HTTP 服務在後臺運行。最方便的做法是:

  1. 在 Lotus Domino Designer 中打開數據庫。
  2. 在數據庫中選擇 Form 或 View。
  3. 選擇 Design - Preview in Web Browser - Default Browser,然後等待 Web 瀏覽器中出現窗體或視圖。

在 Web 瀏覽器中看到窗體或視圖後,可以選擇瀏覽器窗口,然後測試 Web 服務。HTTP 服務繼續在後臺運行,直到完全關閉 Notes 客戶機。有些個人防火牆會阻塞本地 HTTP 服務的操作,因此可能需要調整防火牆設置。

已經編寫了 Web 服務之後,肯定想對它進行測試。爲了訪問 Web 服務的 WSDL,必須使用 Web 服務的完整 URL 路徑,該路徑以 ?WSDL URL 命令結尾。

例如,可以對 DNS 名爲 mydomino.example.com 的服務器上的 WSTest.nsf 數據庫的 Web 服務 MyNewWebService 使用下面的 URL:

http://mydomino.example.com/WSTest.nsf/MyNewWebService?WSDL

有很多可用於測試 Web 服務的測試工具 —— 既有免費工具,也有商業工具 —— 可以很方便地編寫較長的文章或教程來描述各種測試方法。

下面是幾個測試工具可用於測試和調用 Web 服務,每個測試工具都有一段簡短描述。熟悉每個工具的詳細信息是留給讀者的練習。

soapUI

測試 Web 服務時,最易於使用的工具之一是 soapUI,可從 soapUI Web 站點 獲得。SoapUI 是用 Java 編寫的免費的桌面程序,因此可以在不同操作系統上運行。下面是使用 SoapUI 對 Web 服務進行測試的步驟:

  1. 請確保在本地機器上正確安裝了 Java 1.5 或更高版本。
  2. 下載 soapUI program 並將其解壓縮。
  3. 在解壓縮文件的 /bin 目錄中,運行 soapui.bat 文件(Windows 操作系統下)或 soapui.sh 文件(其他操作系統下)來打開 soapUI。
  4. 選擇 File - New WSDL Project,然後根據提示,輸入項目名稱。
  5. 在左側導航欄中,右鍵單擊屬性列表中的新項目,然後選擇 “Add WSDL From URL” 選項。
  6. 輸入測試服務的 URL(例如,http://localhost/DWSTest.nsf/EchoTestService?WSDL),如果提示要爲所有操作創建默認請求,則單擊 Yes。
  7. 現在,可以在左側完全展開新項目並查看可用於調用的每個 Web 服務方法的條目。如果雙擊方法名稱下的 Request 條目,將看到預構建的 SOAP 請求,可以將其作爲一個測試進行發送(參見圖 6)。

    圖 6. soapUI 接口
    soapUI 接口

  8. 對於圖 6 中的 EchoTest 服務,有一個簡單 SOAP 請求用於發送。如果想測試該服務,則在請求 envelope 的 <TXT> 節點中輸入文本,然後單擊位於 SOAP 請求文本上方的工具欄中的綠色箭頭按鈕。這將發送請求到服務並在右側窗格中顯示得到的 SOAP 響應。

SoapUI 允許您構造測試套件,適於對 Web 服務進行單元測試。這樣,就可以創建一套測試,當修改了 Web 服務後,可以運行預先編寫的測試來確保各方面仍正確運行。

其缺點是所有事情都必須通過原始 XML SOAP 請求和響應來執行。如果您習慣使用 XML 和 SOAP,就不會覺得很難,因爲最難的部分(首先要編寫 SOAP 請求)已經替您完成了,並且您可以查看 SOAP 響應。但是,如果您更喜歡在較抽象的層面上工作 —— 在程序中使用簡單的 API 或函數 —— 那麼該工具對於您來說就過於低級了。

Eclipse 和 Web Tools Platform (WTP)

如果已經安裝了 Eclipse(或者需要理由來使用 Eclipse),有一個非常好的包 Web Tools Platform (WTP) 爲測試 Web 服務提供了更高水平的接口。不需要使用原始 SOAP 請求,WTP 可以爲每個 Web 服務方法創建窗體,您只需在窗體中輸入值,然後發送請求。

下面是安裝和使用 WTP 的基本步驟:

  1. 下載並安裝 Eclipse platform
  2. 安裝 WTP 組件。對於 Eclipse 3.2 之前的版本,請參閱 WTP Web 站點上的安裝指南。對於 Eclipse 3.2 或更高版本,這些指南是 “Web and J2EE Development” 下的 Callisto toolkit 的一部分。進行以下操作:
    1. 選擇 Help - Software Updates - Find and Install。
    2. 在下一個屏幕上,選擇 “Search for new features to install2”,然後單擊 Next。
    3. 請確保選中了 Callisto Discovery Site 選項,然後單擊 Next。
    4. 在要安裝的包列表的 Callisto Discovery Site 部分下,選擇 “Web and J2EE Development” 項(也選擇了該項下的所有項)。然後單擊 “Select Required” 按鈕以獲取所有其他所需組件,並單擊 Next 進行安裝(參見圖 7)。安裝過程需要幾分鐘的時間。


    圖 7. Eclipse 中的 WST 包安裝
    Eclipse 中的 WST 包安裝

  3. 完成安裝後,重新啓動 Eclipse。從主 Workbench 頁面,選擇 Run - Launch the Web Services Explorer。
  4. 在 Web Services Explorer 視圖中,單擊 WSDL Page 按鈕,將 WSDL Main 添加到 Navigator 窗格(參見圖 8)。

    圖 8. WST 中的 WSDL Explorer
    WST 中的 WSDL Explorer

  5. 可以在 Actions 窗格中輸入 WSDL 路徑。輸入測試服務的 URL(例如,http://localhost/DWSTest.nsf/EchoTestService?WSDL),然後單擊 Go 按鈕。
  6. 找到 WSDL 文件後,在 Navigator 窗格的 WSDL Main 條目下應該有一個樹狀結構,列出了 Web 服務中的所有方法。
  7. 雙擊 WSDL 樹中的任一方法名,將在 Actions 窗格中出現窗體,允許您在該窗體中輸入方法的每個參數值,並將值發送到 Web 服務。響應將顯示在底部的 Status 窗格中(參見圖 9)。

    圖 9. WST 中的 SOAP 請求
    WST 中的 SOAP 請求

  8. 如果您想查看由 Web 服務調用發送和接收的原始 XML SOAP 消息,則單擊 Status 窗格中的 Source link。

雖然 Eclipse WTP 的初始設置比 soapUI 工具更復雜,但它提供了更友好的用戶接口(用窗體代替了原始請求)。如果需要底層的細節,仍可以查看發送和接收的原始消息,不過一些人發現使用基於窗體的方法更易於創建和發送請求。

MSSOAP toolkit

很多使用 Windows 平臺的 LotusScript 編程人員已經成功使用 MSSOAP toolkit 來調用 Web 服務。雖然該 toolkit 不再受支持也不再由 Microsoft 更新(已經被 Microsoft .NET 框架取代),但它仍是一個通用的技術,因此在這裏值得一提。

MSSOAP 是一個 DLL 文件,可以從 Microsoft 下載或作爲標準 Windows 安裝的一部分安裝在工作站上。使用 LotusScript,可以將 DLL 作爲 COM 對象進行調用,如下所示:


清單 6. 來自 LotusScript 的簡單 MSSOAP 調用
				
Dim Client As Variant
Set Client = CreateObject("MSSOAP.SoapClient")
Call Client.MSSoapInit("http://localhost/DWSTest.nsf/EchoTestService?WSDL")
Print "Echo said " & Client.Echo("echo")

顯然,需要對所使用的 Web 服務中的方法、參數和數據類型有一些瞭解。如果調用另一個 Web 服務,可以手動讀取並解釋 WSDL 文件(可能很麻煩),也可以使用類似 soapUI 或 Eclipse WTP 的工具來解釋所有事情。

不幸的是,我們發現在 Windows 操作系統上使用的 MSSOAP 版本一般是 1.x 版,只能使用 RPC/Encoded Web 服務,該服務使用簡單數據類型作爲參數。當返回複雜數據類型時,通常是 IXMLDOMNodeList 對象,但將複雜數據類型作爲參數進行傳遞時,需要創建新的 IXMLDOMNodeList 對象且不易處理。一般情況下,MSSOAP 1.x 也無法理解使用了枚舉的 Web 服務(將在本系列的下一篇文章中進行討論)。

如果您可以控制使用 MSSOAP 庫的服務器或工作站,那麼可以選擇下載並安裝 SOAP Toolkit 版本 3.0,它允許您調用更廣泛的 Web 服務。安裝該 toolkit 後,您可以將上述代碼由 CreateObject("MSSOAP.SoapClient") 更改爲 CreateObject("MSSOAP.SoapClient30") 以便使用較新版本的庫。表 1 列出了兩個版本之間的差別。


表 1. MSSOAP 1.x 和 3.0 之間的差別
MSSOAP 1.x MSSOAP 3.0
默認情況下,在大多數使用 Windows XP/2000 的機器上 必須 下載 並安裝
CreateObject("MSSOAP.SoapClient") CreateObject("MSSOAP.SoapClient30")
僅適用 RPC/Encoded Web 服務 RPC/Encoded、RPC/Literal、Doc/Literal、來自 LotusScript Web 的 Wrapped
不能解釋枚舉 可以解釋由 LotusScript Web 服務返回的枚舉,但有可能不能正確解釋從 Java Web 服務返回的枚舉

MSSOAP 允許動態調用 Web 服務(這很方便),關於使用 MSSOAP(在 LotusScript 和 Visual Basic 中,後者可以方便地轉換爲 LotusScript)有大量的代碼示例。因此,如果您從使用 Windows 的機器上調用 Web 服務,這是個很好的選擇。

Apache Axis

在 Lotus Notes 環境中,Apache Axis 框架是調用 Web 服務的另一種很好的選擇。Axis 是一個非常成熟的 Java 包,多年來一直用於在不同平臺上創建、提供和使用 Web 服務。實際上,Axis 是允許 Lotus Domino V7 提供 Web 服務的底層技術!

如果使用 Axis 作爲客戶機來調用 Web 服務,通常基於服務的 WSDL 文件會使用 Java 命令行工具(隨 Axis 提供的)wsdl2java 來創建調用 Web 服務的 stub 文件。這些 stub 文件是用作複雜代碼的包裝程序的 Java 類,這些複雜代碼是訪問和使用 Web 服務時所需要的,因此所有您需要做的事情就是使用 stub 類來調用方法並返回響應。雖然您必須爲要調用的任何 Web 服務完成生成 stub 文件的前端工作,但這將減少後續麻煩,即必須瞭解錯綜複雜的 Web 服務(消息格式、名稱空間、響應解析等)。

如果要在 Lotus Notes 中使用 Apache Axis 來編寫代碼以便調用 Web 服務,比較好的起點是 developerWorks 文章 “通過 Lotus Domino Java 代理消費 Web 服務” 和開源 Stubby 數據庫,該數據庫可從 OpenNTF Web 站點獲取。作爲示例,下面演示瞭如何使用 Stubby 來創建 Axis 代碼以調用 EchoTest 服務:

  1. 從 OpenNTF.org 下載 Stubby 數據庫 並在 Lotus Notes V7 客戶機中打開。
  2. 單擊 Create New Doc 按鈕,在數據庫中創建新文檔,並在窗體的 WSDL File 字段輸入 EchoTest 服務的 URL (http://localhost/DWSTest.nsf/EchoTestService?WSDL) (參見圖 10)。

    圖 10. Stubby 數據庫文檔
    Stubby 數據庫文檔

  3. 單擊窗體上的 Generate Stub Files 按鈕,創建 Axis stub 文件。同時創建了 JAR 文件,包含了所有已編譯的且可以使用的 stub 文件。創建的所有文件附在 Stubby 文檔的 generated files 附籤的字段中。
  4. 將 generated files 附簽上的 JAR 文件(在本例中爲 EchoTestService.jar)移至本地文件系統。
  5. 使用 Lotus Domino Designer V7 在數據庫中創建新的 Java 代理,然後使用 Edit Project 按鈕附上前一步中的 JAR 文件。
  6. 從 Stubby 文檔的 sample code 附簽上,複製所生成的示例代理代碼,然後粘貼到代理中。還需要添加一行代碼用來調用 Web 服務的 Echo 方法。得到的代理代碼類似清單 7 中所示(爲了簡潔,刪除了註釋和空行):

    清單 7. 在 Lotus Notes Java 代理中使用 Apache Axis stub 文件
    						
    import lotus.domino.*;
    import DefaultNamespace.*;
    public class JavaAgent extends AgentBase {
        public void NotesMain() {
            try {
                EchoTestServiceLocator locator = new EchoTestServiceLocator();
                EchoTest service = locator.getDomino();
                System.out.println("Echo said " + service.ECHO("echo"));
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

  7. 現在您可以在任何 Lotus Notes/Domino V7 客戶機或服務器上運行該代理以訪問 Web 服務。

對於喜歡使用 LotusScript 的編程人員,Stubby 數據庫中還有很多示例使用 LS2J 調用以 LotusScript 編寫的 Web 服務 stub 代碼。有關 LS2J 的更多信息,請參閱 Lotus Domino Designer 幫助。

PHP nuSOAP

測試 Web 服務時,您可以嘗試的另一個有趣的事情是 PHP nuSOAP 庫。它不僅可以很方便地用於使用 Web 服務,而且可以提供一種很好的方式,用於顯示有關 Domino Web 服務的信息。

例如,您有一個可用的 PHP 服務器(或者有一個本地的 PHP 安裝,如 WAMP server),那麼您可以將 nuSOAP 庫複製到該服務器上並創建以下頁面:


清單 8. 使用 PHP nuSOAP 來獲取有關 WSDL 文件的詳細信息
				
<?php
$wsdlURL = 

IBM Lotus Domino 7 中的實用 Web 服務,第 2 部分: 編寫和測試簡單的 Web 服務

 

: 中級

Julian Robichaux, 開發人員, Independent Consultant

2006 年 12 月 26 日

在本 Web 服務系列文章的第 2 篇中,我們將演示如何在 IBM Lotus Domino V7.0 中編寫簡單的 Web 服務,該服務將接受並返回簡單的數據類型、數組以及 InOut 參數。我們還將討論幾個測試方法,會涉及 soapUI、Eclipse、MSSOAP toolkit 和 Apache Axis 測試工具。

您現在想要編寫 Web 服務。太棒了!如果您閱讀了我們的第一篇文章,“IBM Lotus Domino 7 中的實用 Web 服務:什麼是 Web 服務以及它們爲何如此重要”,那麼您已經對什麼是 Web 服務以及它們爲何如此重要有了很好的理解。通過 IBM Lotus Domino V7.0,您可以很方便地創建自己的 Web 服務,其他客戶機或系統可以使用這些 Web 服務。在某種程度上,它就像編寫代理一樣容易。

IBM Lotus Domino Designer 允許使用 LotusScript 或 Java 來編寫 Web 服務,但本文中所有的示例都是使用 LotusScript 編寫的。不過,本文的示例數據庫(請參閱 下載 部分)有用 LotusScript 和 Java 兩種語言編寫的示例 Web 服務以供參考。

背景知識簡介

Lotus Domino V7.0 在 Lotus Domino Designer 中引入了新的 Web 服務設計元素。如果在 Lotus Domino Designer V7.0 客戶機中打開數據庫,就可以看到 Web Services 條目正好位於常見的設計元素樹的 Shared Code 部分的 Agents 條目下(參見圖 1)。

Lotus Domino 負責處理所有的 WSDL 創建和 SOAP 操作,因此您所要做的事情就是在 Web 服務設計元素中編寫代碼,就像爲代理編寫代碼一樣。一旦指定哪一個類用作服務的接口類,Lotus Domino 就可以發佈 WSDL 文件、將引入的 SOAP 請求轉換爲類上的方法調用以及返回方法的結果(如果有的話)作爲 SOAP 響應。

從編寫代碼的立場上看,您所做的一切就是編寫 LotusScript 或 Java 類。Lotus Domino 完成了其餘工作!





回頁首


編寫一個簡單的 Web 服務

現在我們來編寫一個簡單的 Web 服務。爲了新建一個 Web 服務,在 Lotus Domino Designer 中打開數據庫,轉到數據庫設計的 Web Services 部分,然後單擊 New Web Service 按鈕(參見圖 1)。


圖 1. Lotus Domino Designer 中的 Web Service 設計元素部分
Lotus Domino Designer 中的 Web Service 設計元素部分

該屏幕與新建代理時打開的窗口(參見圖 2)很相似。在 Web Services Properties 框中,設置新 Web 服務的名稱 —— 本示例中使用 EchoTestService —— 然後關閉該框。稍後我們將討論 Properties 框中的各個字段。


圖 2. Lotus Domino Designer 中的 Web Service 設計元素
Lotus Domino Designer 中的 Web Service 設計元素

現在應該看到一個與編寫 LotusScript 代理時所使用的窗口很相似的屏幕。單擊 LotusScript 事件中 Objects 附籤的 (Declarations) 以編寫類(必須始終在 (Declarations) 部分中定義類)。將下列代碼輸入到 IDE:


清單 1. 一個非常簡單的返回字符串的 Web 服務
				
Class EchoTest
	Public Function Echo (txt As String) As String
		Echo = txt
	End Function
End Class

該代碼進行以下工作:

  • 創建類 EchoTest。
  • 在類中定義方法 Echo,該方法接受字符串作爲參數並返回字符串作爲結果(類中的函數和 sub 被稱爲方法)。

EchoTest 中的 Echo 方法獲取字符串作爲參數並返回相同的字符串。現在看一下它是否是有效的 Web 服務。嘗試保存並關閉該服務。將收到下面的錯誤:

The Web Service has been saved, but is not valid: 
Please specify which class exposes your Web service interface(s), 
using the 'PortType class' field of the Web Service properties panel.

若要避免此錯誤,請打開 Web Service Properties 框,然後指定要使用的類。因爲 Web 服務代碼中可能定義了多個類,所以必須僅選擇其中一個作爲 Web 服務的接口。接口類就是具有 Public 方法的類,Web 服務客戶機可以調用 Public 方法。

在 Properties 框中,在第一個附籤的 PortType class 字段中輸入 EchoTest(您剛剛編寫的類名)。關閉該框,然後再次嘗試保存並關閉 Web 服務。這次一切正常。現在您有了一個正常運轉的 Web 服務!





回頁首


Web Service Properties 框

下面再次打開 Web service 和 Web Service Properties 框。框中的第一個附籤(Basics 附籤)如圖 3 所示。


圖 3. Web Service Properties 框中的 Basics 附籤
Web Service Properties 框中的 Basics 附籤

對 Basic 附簽上的字段說明如下:

  • Name(必需的):Web 服務的名稱,是客戶機訪問 WSDL 文件或服務的方法時所使用的名稱。
  • Alias:除 Name 之外的另一名稱,用戶使用該名稱可以訪問服務。
  • Comment:有關 Web 服務的信息數據的字段(通常,該字段的信息不超過一句話;有關 Web 服務的較長描述或信息應寫在代碼的註釋中)。
  • Warn if the WSDL interface is modified:該選項警告您對代碼所做的更改是否修改了由 Web 服務產生的 WSDL 文件。這對於確保 WSDL 文件的一致很有用,但是應該意識到,如果選中了該選項,則您將無法保存帶有已修改的 WSDL 文件的服務。
  • PortType class(必需的):用作 Web 服務接口的類的名稱。換句話說,它就是 Web 服務代碼中帶有用戶可訪問的 public 方法的類。

框中的第二個附籤是 Security 附籤(參見圖 4)。


圖 4. Web Service Properties 框中的 Security 附籤
Web Service Properties 框中的 Security 附籤

對 Security 附簽上的字段說明如下:

  • Run as web user:該選項使 Web 服務代碼能夠在調用 Web 服務的用戶的安全性上下文中運行(默認情況下,它將在 Lotus Domino Designer 中最後簽名 Web 服務的那個 ID 的安全性上下文中運行)。
  • Run on behalf of:該字段允許指定用戶,如果想讓 Web 服務代碼運行在特定用戶的安全性上下文中,而不是 Lotus Domino Designer 中最後簽名 Web 服務的那個 ID 的安全性上下文中。
  • Allow remote debugging:該選項允許遠程調試 Web 服務(有關遠程調試的信息,請參閱 Lotus Domino Designer 幫助主題 “Using the Remote Debugger”)。
  • Profile this web service:該選項將在 Web 服務運行時使其生成分析信息(有關分析的信息,請參閱 Lotus Domino Designer 幫助主題 “Profiling agents and Web services”)。
  • Set runtime security level:設置爲 1,允許大多數 LotusScript 和 Java 操作正確運行;對於讀/寫文件、創建 COM 對象或執行網絡操作等,根據需要,設置爲 2 或 3(有關更多信息,請參閱 Lotus Domino Designer 幫助主題 “Restricted LotusScript and Java agent operations”)。
  • Default access for this web service:該選項允許控制哪些用戶可以訪問 Web 服務,並超出了使用數據庫 ACL 所能進行的控制(如果 Anonymous 用戶無法訪問 Web 服務,則當用戶嘗試進行連接時,將收到錯誤 401 Access Denied 或 404 Not Found)。
  • Allow Public Access users to use this web service:該選項使得僅擁有數據庫 ACL 中 “Read Public Documents” 訪問權的用戶可以使用該 Web 服務,當不想爲大量用戶授予完全的 Reader 訪問權限(或更高級別)時,這點很有用。

框中的第三個附籤是 Options 附籤(參見圖 5)。


圖 5. Web Service Properties 框中的 Options 附籤
Web Service Properties 框中的 Options 附籤

對 Options 附簽上的字段說明如下:

  • Programming model:可用選項是 RPC 或 Message(大多數情況下使用 RPC)。
  • SOAP message format:在該字段中,爲此 Web 服務選擇 SOAP 消息格式(有關格式的更多信息,請參閱下一節)。Lotus Domino V7.0 中的默認格式是 RPC/encoded。
  • Include operation name in SOAP action:該選項要求操作名稱存在於外來請求的 SOAP 動作標頭中(很少需要)。
  • Port type name:默認情況下,該字段值與 Basics 附簽上 PortType class 字段的值相同(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。
  • Service element name:默認情況下,該字段值是 PortType 名稱加上單詞 Service(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。
  • Service port name:默認情況下,該字段值是 Domino(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。

如您所見,可以設置很多屬性,儘管其中只有 Web service name 和 port type class 是必需的。其他所有屬性都是可選的或是有適當的默認值。

SOAP 消息格式

在 Web Service Properties 框中,有很多不同的 SOAP 消息格式可以選擇,所以不易決定到底應該使用哪一個。各種格式將創建略有不同的 WSDL 文件,反過來會產生略有不同的 SOAP 請求和響應。

從編寫代碼的立場看,您不會注意到這些不同,因爲無論使用哪一種格式,所編寫的 Web 服務是完全相同的。但是,這會使調用 Web 服務的用戶客戶機有所不同。

通常,RPC/encoded 格式是較早的 Web 服務客戶機技術(如 Apache SOAP 和 MSSOAP)廣泛支持的格式。Doc/literal 由 Microsoft .NET 客戶機和服務器默認使用,並在過去的幾年中漸受歡迎。

消息格式的選擇依賴於調用服務的客戶機所使用的技術以及哪一種 SOAP 格式最易於使用該客戶機技術。如果不能控制調用服務的客戶機,則 RPC/encoded 和 Doc/literal 都是很好的選擇。

有關不同格式以及其如何影響 WSDL 結構和 SOAP 消息的詳細說明,請參閱經常被提到的 developerWorks 文章 “Which style of WSDL should I use?”。





回頁首


使用簡單數據類型的 Web 服務

現在回過頭來編寫 Web 服務代碼。我們知道用來公開 Web 服務的 LotusScript 代碼需要作爲類進行編寫。實際上,通常用 LotusScript 編寫的任何函數或 sub 在 Web 服務中都是作爲類方法使用的,並帶有以下限制:

  • 不要使用原生 LotusScript 類(如 NotesDatabase、NotesDocument 等)作爲參數或返回值。
  • 不要使用變量或貨幣數據類型作爲參數或返回值。
  • 不要使用列表或數組作爲參數或返回值(可以使用數組,不過必須使用稍後在本文中所描述的一種特定數據類型)。
  • 不要使用定製類型作爲參數或返回值。

相反,可以在 Web 服務類方法中使用以下內容作爲參數或返回值:

  • 簡單的數據類型(字符串、整數等)
  • 定製的用戶定義的類
  • lsxsd.lss 文件中定義的特殊類(該文件包含在 Lotus Notes/Domino V7.0 客戶機和服務器文件中)

將用戶定義的類是一種複雜的數據類型,我們將在下一篇文章中進行討論。lsxsd.lss 文件(可以在本地的 Notes 程序目錄中找到)中的類是很有用的,允許傳遞字符串數組、文件和數據。稍後本文將對其中一些類進行討論,其餘的類將在下一篇文章中進行討論。

現在先來看一些在類中使用簡單數據類型的示例。考慮下面的類:


清單 2. 帶有多個方法的 LotusScript Web 服務
				
Class DatabaseInfo
	Private session As NotesSession
	Private db As NotesDatabase
	
	Public Sub New ()
		Set session = New NotesSession
		Set db = session.CurrentDatabase
	End Sub
	
	Public Function GetDbName () As String
		GetDbName = db.Title
	End Function
	
	Public Sub UpdateFTIndex ()
		Call db.UpdateFTIndex(True)
	End Sub
	
	Public Function GetUserRoles (userName As String) As String
		GetUserRoles = Join(getRoles(userName), ",")
	End Function
	
	Private Function getRoles (userName As String) As Variant
		Dim acl As NotesACL
		Dim entry As NotesACLEntry
		Dim sep As String
		
		Set acl = db.ACL
		Set entry = acl.GetEntry(userName)
		
		If (entry Is Nothing) Then
			Dim returnArray(0) As String
			getRoles = returnArray
		Else
			getRoles = entry.Roles
		End If
	End Function
End Class

以上代碼淺顯易懂,不過對於各種方法,請注意以下內容:

  • New:方法 New 是可選的,且不能用於那些調用 Web 服務的客戶機。如果需要的話,僅用於初始化代碼。同時,如果編寫 New 方法,那麼它必須是 sub 且沒有任何參數。
  • GetDbName:方法 GetDbName 沒有任何參數。這是規定的。
  • UpdateFTIndex:方法 UpdateFTIndex 沒有任何參數且不返回值。這也是規定的。
  • GetUserRoles:方法 GetUserRoles 將調用其他方法來執行大部分工作。也可以調用其他函數和 sub(類以外的),甚至可以使用 Use 語句引用 script 庫,從 script 庫中調用類、函數和 sub。這很有用,因爲這樣不僅可以保持 Web 服務代碼的簡潔,而且有助於從已有的任何業務邏輯代碼中分離出 Web 服務代碼。
  • getRoles:方法 getRoles 聲明爲 Private,因此類中的其他方法可以使用該方法,但是,不能用於那些調用 Web 服務的客戶機。將一些方法聲明爲 Private 是一個很好的做法,以便保持代碼和邏輯位於類中,同時不允許用戶直接調用方法。

    但是,請記住如果既沒有將方法聲明爲 Public,也沒有將其聲明爲 Private,則該方法將作爲 Public 方法使用。

到目前爲止,實際上沒有什麼複雜的東西。由您決定用戶可以調用的函數/sub,然後將其作爲方法包含在類中。如果已經編寫了所需的代碼或邏輯,那麼您還可以從 script 庫中引用其他類、函數和 sub。





回頁首


返回數組

您可能已注意到方法 GetUserRoles 在返回值前,將 getRoles 方法返回的字符串數組轉化爲單一的一個分隔的字符串。這是因爲不能直接從 Web 服務作爲數組或變量返回 LotusScript 數組。

但是,通過返回 lsxsd.lss 文件中其中一個 ARRAY_HOLDER 類的實例,可以返回數組。將 ARRAY_HOLDER 類(STRINGARRAY_HOLDER、INTEGERARRAY_HOLDER 等)作爲值返回時,這些類將自動轉換爲支持 SOAP 的數組。

爲了舉例說明,可以將 %INCLUDE "lsxsd.lss" 行添加到 Web 服務的 (Options) 部分,然後重寫 GetUserRoles 方法,如下所示:


清單 3. 在 LotusScript Web 服務中返回字符串數組
				
	Public Function GetUserRolesArray (userName As String) As STRINGARRAY_HOLDER
		Dim returnArray As New STRINGARRAY_HOLDER
		Dim roles As Variant
		Dim i As Integer
		
		roles = getRoles(userName)
		Redim returnArray.Value(Ubound(roles))
		For i = 0 To Ubound(roles)
			returnArray.Value(i) = roles(i)
		Next
		
		Set GetUserRolesArray = returnArray
	End Function

就用戶的客戶機而言,GetUserRolesArray 方法將返回常規的字符串數組,而不是特定的 STRINGARRAY_HOLDER 對象。這是因爲訪問服務時,Domino Web 服務在後臺完成了 STRINGARRAY_HOLDER 和字符串數組之間的轉化。還需要做一些額外工作將 getRoles 數組的元素添加到 STRINGARRAY_HOLDER 的 Value 成員中(因爲不能直接將 Value 設置爲等於另一個數組),不過這只是幾行代碼的事。

當然,字符串數組不是惟一可以接受或返回的數組類型,INTEGERARRAY_HOLDER、LONGARRAY_HOLDER、和 lsxsd.lss 文件中定義的類似的類也可以爲其他原生數據類型提供相同的功能。有關更多信息,請參閱 Lotus Domino Designer 幫助或 lsxsd.lss 文件。

返回數組的另一種選擇是將數組作爲複雜數據類型的組成部分返回,該技巧我們將在下一篇文章中進行討論。





回頁首


使用 InOut 參數返回多個值

當僅希望使用簡單數據類型時,另一種可以使用的方法是 InOut 參數。有些參數既可以接收輸入值,也可以返回輸出值。例如,考慮下面的類:


清單 4. 在 LotusScript Web 服務中使用 InOut 參數
				
Class InOutTest
	Public Sub AddOne (inout As INTEGER_HOLDER)
		inout.Value = inout.Value + 1
	End Sub
	
	Public Function SwapAndAdd (inout1 As INTEGER_HOLDER, _
	inout2 As INTEGER_HOLDER) As Integer
		SwapAndAdd = inout1.Value + inout2.Value
		inout1.Value = inout2.Value
		inout2.Value = SwapAndAdd - inout2.Value
	End Function
End Class

第一個方法 (AddOne) 使用整數作爲輸入參數。方法中的代碼爲傳遞的值增加 1 —— 因爲它是 INTEGER_HOLDER —— 並將新值返回到 SOAP 響應中。

這是 lsxsd.lss 文件中所定義的 HOLDER 類的特殊屬性。將該類用作方法參數時,它們將變成 SOAP 請求/響應中的 InOut 參數,因此可以接收並返回值。

方法 AddOne 並不是一個很實際的示例,因爲通常只需接收常規整數作爲參數,並且作爲能返回修改的整數的函數編寫此方法。但是,如果有一個或多個 InOut 參數作爲方法返回值,那麼就可以在方法響應中返回多個獨立的值而不是單個值。

現在看一下第二個方法 SwapAndAdd。該方法有兩個 InOut 值作爲參數,並返回整數。在用戶客戶機上,它們生成 SOAP 請求用來作爲參數發送兩個整數值,並且接收 SOAP 請求,該 SOAP 請求的響應具有三個整數值:其中兩個作爲參數進行傳遞(並且通過方法進行修改),另一個是結果。

不可否認,InOut 參數不那麼常見,因爲返回多個值通常是通過返回複雜數據類型來處理的,但這仍是個值得注意的好方法。再次說明,我們將在本系列的下一篇文章中討論複雜數據類型。





回頁首


使用日期和時間

您需要使用的最後一個簡單數據類型是日期/時間對象。下面的示例演示了使用參數中的日期/時間並返回對象:


清單 5. 在 LotusScript Web 服務中使用日期和時間
				
Class DateTester
	Public Function getCurrentTime () As XSD_DATETIME
		Dim dt As New NotesDateTime(Now)
		Set getCurrentTime = New XSD_DATETIME
		Call getCurrentTime.SetValueFromNotesDateTime(dt)
	End Function
 	
	Public Function getLocalDateFormat (xdt As XSD_DATETIME) As String
		Dim dt As NotesDateTime
		Set dt = xdt.GetValueAsNotesDateTime()
		getLocalDateFormat = dt.LocalTime
	End Function
End Class

lsxsd.lss 類再次發揮了作用。可以只接收或返回 XSD_DATETIME(變成了 SOAP dateTime 元素)類型變量並在它與 NotesDateTime 對象之間進行轉換。

但是,應注意到時間值的時區處理會比較困難,因爲服務器和客戶機可能正確也可能會不正確地添加或解釋 SOAP dateTime 元素的時區偏移。最新的 W3C Note 對該問題的某些方面進行了討論。通常,首先應試着徹底測試 Web 服務客戶機。





回頁首


測試 Web 服務

在本地數據庫上測試 Web 服務

如果您有數據庫的本地副本和要測試的 Web 服務,那麼首先請確保 Notes HTTP 服務在後臺運行。最方便的做法是:

  1. 在 Lotus Domino Designer 中打開數據庫。
  2. 在數據庫中選擇 Form 或 View。
  3. 選擇 Design - Preview in Web Browser - Default Browser,然後等待 Web 瀏覽器中出現窗體或視圖。

在 Web 瀏覽器中看到窗體或視圖後,可以選擇瀏覽器窗口,然後測試 Web 服務。HTTP 服務繼續在後臺運行,直到完全關閉 Notes 客戶機。有些個人防火牆會阻塞本地 HTTP 服務的操作,因此可能需要調整防火牆設置。

已經編寫了 Web 服務之後,肯定想對它進行測試。爲了訪問 Web 服務的 WSDL,必須使用 Web 服務的完整 URL 路徑,該路徑以 ?WSDL URL 命令結尾。

例如,可以對 DNS 名爲 mydomino.example.com 的服務器上的 WSTest.nsf 數據庫的 Web 服務 MyNewWebService 使用下面的 URL:

http://mydomino.example.com/WSTest.nsf/MyNewWebService?WSDL

有很多可用於測試 Web 服務的測試工具 —— 既有免費工具,也有商業工具 —— 可以很方便地編寫較長的文章或教程來描述各種測試方法。

下面是幾個測試工具可用於測試和調用 Web 服務,每個測試工具都有一段簡短描述。熟悉每個工具的詳細信息是留給讀者的練習。

soapUI

測試 Web 服務時,最易於使用的工具之一是 soapUI,可從 soapUI Web 站點 獲得。SoapUI 是用 Java 編寫的免費的桌面程序,因此可以在不同操作系統上運行。下面是使用 SoapUI 對 Web 服務進行測試的步驟:

  1. 請確保在本地機器上正確安裝了 Java 1.5 或更高版本。
  2. 下載 soapUI program 並將其解壓縮。
  3. 在解壓縮文件的 /bin 目錄中,運行 soapui.bat 文件(Windows 操作系統下)或 soapui.sh 文件(其他操作系統下)來打開 soapUI。
  4. 選擇 File - New WSDL Project,然後根據提示,輸入項目名稱。
  5. 在左側導航欄中,右鍵單擊屬性列表中的新項目,然後選擇 “Add WSDL From URL” 選項。
  6. 輸入測試服務的 URL(例如,http://localhost/DWSTest.nsf/EchoTestService?WSDL),如果提示要爲所有操作創建默認請求,則單擊 Yes。
  7. 現在,可以在左側完全展開新項目並查看可用於調用的每個 Web 服務方法的條目。如果雙擊方法名稱下的 Request 條目,將看到預構建的 SOAP 請求,可以將其作爲一個測試進行發送(參見圖 6)。

    圖 6. soapUI 接口
    soapUI 接口

  8. 對於圖 6 中的 EchoTest 服務,有一個簡單 SOAP 請求用於發送。如果想測試該服務,則在請求 envelope 的 <TXT> 節點中輸入文本,然後單擊位於 SOAP 請求文本上方的工具欄中的綠色箭頭按鈕。這將發送請求到服務並在右側窗格中顯示得到的 SOAP 響應。

SoapUI 允許您構造測試套件,適於對 Web 服務進行單元測試。這樣,就可以創建一套測試,當修改了 Web 服務後,可以運行預先編寫的測試來確保各方面仍正確運行。

其缺點是所有事情都必須通過原始 XML SOAP 請求和響應來執行。如果您習慣使用 XML 和 SOAP,就不會覺得很難,因爲最難的部分(首先要編寫 SOAP 請求)已經替您完成了,並且您可以查看 SOAP 響應。但是,如果您更喜歡在較抽象的層面上工作 —— 在程序中使用簡單的 API 或函數 —— 那麼該工具對於您來說就過於低級了。

Eclipse 和 Web Tools Platform (WTP)

如果已經安裝了 Eclipse(或者需要理由來使用 Eclipse),有一個非常好的包 Web Tools Platform (WTP) 爲測試 Web 服務提供了更高水平的接口。不需要使用原始 SOAP 請求,WTP 可以爲每個 Web 服務方法創建窗體,您只需在窗體中輸入值,然後發送請求。

下面是安裝和使用 WTP 的基本步驟:

  1. 下載並安裝 Eclipse platform
  2. 安裝 WTP 組件。對於 Eclipse 3.2 之前的版本,請參閱 WTP Web 站點上的安裝指南。對於 Eclipse 3.2 或更高版本,這些指南是 “Web and J2EE Development” 下的 Callisto toolkit 的一部分。進行以下操作:
    1. 選擇 Help - Software Updates - Find and Install。
    2. 在下一個屏幕上,選擇 “Search for new features to install2”,然後單擊 Next。
    3. 請確保選中了 Callisto Discovery Site 選項,然後單擊 Next。
    4. 在要安裝的包列表的 Callisto Discovery Site 部分下,選擇 “Web and J2EE Development” 項(也選擇了該項下的所有項)。然後單擊 “Select Required” 按鈕以獲取所有其他所需組件,並單擊 Next 進行安裝(參見圖 7)。安裝過程需要幾分鐘的時間。


    圖 7. Eclipse 中的 WST 包安裝
    Eclipse 中的 WST 包安裝

  3. 完成安裝後,重新啓動 Eclipse。從主 Workbench 頁面,選擇 Run - Launch the Web Services Explorer。
  4. 在 Web Services Explorer 視圖中,單擊 WSDL Page 按鈕,將 WSDL Main 添加到 Navigator 窗格(參見圖 8)。

    圖 8. WST 中的 WSDL Explorer
    WST 中的 WSDL Explorer

  5. 可以在 Actions 窗格中輸入 WSDL 路徑。輸入測試服務的 URL(例如,http://localhost/DWSTest.nsf/EchoTestService?WSDL),然後單擊 Go 按鈕。
  6. 找到 WSDL 文件後,在 Navigator 窗格的 WSDL Main 條目下應該有一個樹狀結構,列出了 Web 服務中的所有方法。
  7. 雙擊 WSDL 樹中的任一方法名,將在 Actions 窗格中出現窗體,允許您在該窗體中輸入方法的每個參數值,並將值發送到 Web 服務。響應將顯示在底部的 Status 窗格中(參見圖 9)。

    圖 9. WST 中的 SOAP 請求
    WST 中的 SOAP 請求

  8. 如果您想查看由 Web 服務調用發送和接收的原始 XML SOAP 消息,則單擊 Status 窗格中的 Source link。

雖然 Eclipse WTP 的初始設置比 soapUI 工具更復雜,但它提供了更友好的用戶接口(用窗體代替了原始請求)。如果需要底層的細節,仍可以查看發送和接收的原始消息,不過一些人發現使用基於窗體的方法更易於創建和發送請求。

MSSOAP toolkit

很多使用 Windows 平臺的 LotusScript 編程人員已經成功使用 MSSOAP toolkit 來調用 Web 服務。雖然該 toolkit 不再受支持也不再由 Microsoft 更新(已經被 Microsoft .NET 框架取代),但它仍是一個通用的技術,因此在這裏值得一提。

MSSOAP 是一個 DLL 文件,可以從 Microsoft 下載或作爲標準 Windows 安裝的一部分安裝在工作站上。使用 LotusScript,可以將 DLL 作爲 COM 對象進行調用,如下所示:


清單 6. 來自 LotusScript 的簡單 MSSOAP 調用
				
Dim Client As Variant
Set Client = CreateObject("MSSOAP.SoapClient")
Call Client.MSSoapInit("http://localhost/DWSTest.nsf/EchoTestService?WSDL")
Print "Echo said " & Client.Echo("echo")

顯然,需要對所使用的 Web 服務中的方法、參數和數據類型有一些瞭解。如果調用另一個 Web 服務,可以手動讀取並解釋 WSDL 文件(可能很麻煩),也可以使用類似 soapUI 或 Eclipse WTP 的工具來解釋所有事情。

不幸的是,我們發現在 Windows 操作系統上使用的 MSSOAP 版本一般是 1.x 版,只能使用 RPC/Encoded Web 服務,該服務使用簡單數據類型作爲參數。當返回複雜數據類型時,通常是 IXMLDOMNodeList 對象,但將複雜數據類型作爲參數進行傳遞時,需要創建新的 IXMLDOMNodeList 對象且不易處理。一般情況下,MSSOAP 1.x 也無法理解使用了枚舉的 Web 服務(將在本系列的下一篇文章中進行討論)。

如果您可以控制使用 MSSOAP 庫的服務器或工作站,那麼可以選擇下載並安裝 SOAP Toolkit 版本 3.0,它允許您調用更廣泛的 Web 服務。安裝該 toolkit 後,您可以將上述代碼由 CreateObject("MSSOAP.SoapClient") 更改爲 CreateObject("MSSOAP.SoapClient30") 以便使用較新版本的庫。表 1 列出了兩個版本之間的差別。


表 1. MSSOAP 1.x 和 3.0 之間的差別
MSSOAP 1.x MSSOAP 3.0
默認情況下,在大多數使用 Windows XP/2000 的機器上 必須 下載 並安裝
CreateObject("MSSOAP.SoapClient") CreateObject("MSSOAP.SoapClient30")
僅適用 RPC/Encoded Web 服務 RPC/Encoded、RPC/Literal、Doc/Literal、來自 LotusScript Web 的 Wrapped
不能解釋枚舉 可以解釋由 LotusScript Web 服務返回的枚舉,但有可能不能正確解釋從 Java Web 服務返回的枚舉

MSSOAP 允許動態調用 Web 服務(這很方便),關於使用 MSSOAP(在 LotusScript 和 Visual Basic 中,後者可以方便地轉換爲 LotusScript)有大量的代碼示例。因此,如果您從使用 Windows 的機器上調用 Web 服務,這是個很好的選擇。

Apache Axis

在 Lotus Notes 環境中,Apache Axis 框架是調用 Web 服務的另一種很好的選擇。Axis 是一個非常成熟的 Java 包,多年來一直用於在不同平臺上創建、提供和使用 Web 服務。實際上,Axis 是允許 Lotus Domino V7 提供 Web 服務的底層技術!

如果使用 Axis 作爲客戶機來調用 Web 服務,通常基於服務的 WSDL 文件會使用 Java 命令行工具(隨 Axis 提供的)wsdl2java 來創建調用 Web 服務的 stub 文件。這些 stub 文件是用作複雜代碼的包裝程序的 Java 類,這些複雜代碼是訪問和使用 Web 服務時所需要的,因此所有您需要做的事情就是使用 stub 類來調用方法並返回響應。雖然您必須爲要調用的任何 Web 服務完成生成 stub 文件的前端工作,但這將減少後續麻煩,即必須瞭解錯綜複雜的 Web 服務(消息格式、名稱空間、響應解析等)。

如果要在 Lotus Notes 中使用 Apache Axis 來編寫代碼以便調用 Web 服務,比較好的起點是 developerWorks 文章 “通過 Lotus Domino Java 代理消費 Web 服務” 和開源 Stubby 數據庫,該數據庫可從 OpenNTF Web 站點獲取。作爲示例,下面演示瞭如何使用 Stubby 來創建 Axis 代碼以調用 EchoTest 服務:

  1. 從 OpenNTF.org 下載 Stubby 數據庫 並在 Lotus Notes V7 客戶機中打開。
  2. 單擊 Create New Doc 按鈕,在數據庫中創建新文檔,並在窗體的 WSDL File 字段輸入 EchoTest 服務的 URL (http://localhost/DWSTest.nsf/EchoTestService?WSDL) (參見圖 10)。

    圖 10. Stubby 數據庫文檔
    Stubby 數據庫文檔

  3. 單擊窗體上的 Generate Stub Files 按鈕,創建 Axis stub 文件。同時創建了 JAR 文件,包含了所有已編譯的且可以使用的 stub 文件。創建的所有文件附在 Stubby 文檔的 generated files 附籤的字段中。
  4. 將 generated files 附簽上的 JAR 文件(在本例中爲 EchoTestService.jar)移至本地文件系統。
  5. 使用 Lotus Domino Designer V7 在數據庫中創建新的 Java 代理,然後使用 Edit Project 按鈕附上前一步中的 JAR 文件。
  6. 從 Stubby 文檔的 sample code 附簽上,複製所生成的示例代理代碼,然後粘貼到代理中。還需要添加一行代碼用來調用 Web 服務的 Echo 方法。得到的代理代碼類似清單 7 中所示(爲了簡潔,刪除了註釋和空行):

    清單 7. 在 Lotus Notes Java 代理中使用 Apache Axis stub 文件
    						
    import lotus.domino.*;
    import DefaultNamespace.*;
    public class JavaAgent extends AgentBase {
        public void NotesMain() {
            try {
                EchoTestServiceLocator locator = new EchoTestServiceLocator();
                EchoTest service = locator.getDomino();
                System.out.println("Echo said " + service.ECHO("echo"));
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

  7. 現在您可以在任何 Lotus Notes/Domino V7 客戶機或服務器上運行該代理以訪問 Web 服務。

對於喜歡使用 LotusScript 的編程人員,Stubby 數據庫中還有很多示例使用 LS2J 調用以 LotusScript 編寫的 Web 服務 stub 代碼。有關 LS2J 的更多信息,請參閱 Lotus Domino Designer 幫助。

PHP nuSOAP

測試 Web 服務時,您可以嘗試的另一個有趣的事情是 PHP nuSOAP 庫。它不僅可以很方便地用於使用 Web 服務,而且可以提供一種很好的方式,用於顯示有關 Domino Web 服務的信息。

例如,您有一個可用的 PHP 服務器(或者有一個本地的 PHP 安裝,如 WAMP server),那麼您可以將 nuSOAP 庫複製到該服務器上並創建以下頁面:


清單 8. 使用 PHP nuSOAP 來獲取有關 WSDL 文件的詳細信息
___FCKpd___8

如果您將該頁面保存到 PHP 服務器並在瀏覽器中打開它,將提示您輸入 WSDL 文件的 URL 位置。輸入 URL 並單擊 Submit 按鈕後,您將看到一個頁面,描述了 Web 服務的每個 public 方法(參見圖 11)。


圖 11. PHP nuSOAP WSDL 文檔示例
PHP nuSOAP WSDL 文檔示例

注意:如果 Web 服務是在本地機器的數據庫中,則需要從本地安裝的 PHP 服務器上運行該頁面(再次說明,可以很方便地設置和使用 WAMP 服務器),並且需要確保本地 PHP 服務器未使用端口 80(因此不會干擾本地的 Notes HTTP 服務)。

用於 Domino SOAP 消息跟蹤的 SoapLog

可以考慮使用的另一個工具是 SoapLog DSAPI Filter。這是一個 DLL 文件和 Notes 數據庫(可以複製到服務器),並且它記錄了發送到服務器上 Web 服務的 SOAP 消息。在撰寫本文的時候,DLL 僅用於 Windows 服務器,而且還沒有免費版的 SoapLog DSAPI Filter。

可以按照以下步驟來安裝 SoapLog 工具:

  1. 下載 SoapLog 並將其解壓縮到本地工作站。
  2. 將 soaplog.dll 文件複製到 Domino 服務器上的 Notes program 目錄中。
  3. 將 SoapLog.nsf 數據庫複製到 Domino 服務器上的數據目錄中,然後根據需要調整 ACL(主要確保服務器可以寫入)。
  4. 將 SOAPLOG_DBNAME 變量添加到服務器的 Notes.ini 文件,指向 SoapLog.nsf 數據庫。例如,如果 SoapLog.nsf 數據庫位於根數據目錄中,則將下面一行代碼添加到 Notes.ini 文件:
    SOAPLOG_DBNAME=SoapLog.nsf
    

  5. 在 Domino Directory 中打開服務器文檔。在 Internet Protocols - HTTP 附簽上,將在右側頁面中部看到 DSAPI。在該字段中添加 soaplog.dll 條目(如果該字段中已經有條目,則在添加 soaplog.dll 條目前,先新添一行)。
  6. 在 Domino 服務器上重新啓動 HTTP 任務。應看到一條消息,指明已裝入 SoapLog DSAPI。

裝入過濾器後,服務器上 Web 服務的所有 SOAP 消息請求將在 SoapLog.nsf 數據庫中創建新的日誌文檔(參見圖 12 和 13)。


圖 12. SoapLog request 附籤
SoapLog request 附籤

圖 13. SoapLog response 附籤
SoapLog response 附籤

還可以設置其他的 Notes.ini 參數以便進一步過濾日誌。有關如何操作的更多信息,請參閱 SoapLog.nsf 數據庫中的 Using This Database 文檔。





回頁首


結束語

本文簡單介紹了在 Lotus Domino V7 中創建和測試一個簡單的 Web 服務的步驟。在 Domino V7 平臺上可以很方便地創建和提供 Web 服務,使用的代碼與您爲 LotusScript 或 Java 代理編寫的代碼很相似。雖然在 Lotus Notes 中測試和調用 Web 服務並不像提供服務一樣自然,但還是有很多很好的方法可用來編寫能夠與服務進行交互的 Web 服務客戶機。

這種做法最大的優點在於您的企業中使用其他(非 Domino)Web 服務的系統仍可以方便地訪問和使用您所編寫的 Web 服務,這使得 Lotus Domino 被廣泛應用於 SOA 環境中。

本系列的下一篇文章將着重介紹如何編寫更復雜的 Web 服務,這些服務使用了複雜數據類型,可以發送和接收文件附件或生成定製錯誤。






回頁首


下載

描述 名字 大小 下載方法
示例數據庫內含代碼 DWSTest.nsf 1 MB HTTP
關於下載方法的信息 Get Adobe® Reader®


參考資料

學習

獲得產品和技術

討論


關於作者

 

Julian Robichaux 是專門研究 IBM Lotus Notes 和 Java 開發的軟件開發人員和專業程序員。他擅長於各種與開發、架構及培訓有關的項目。在業餘時間,他喜歡在 http://www.nsftools.com 上添加個人 Web 站點/博客。他的家人無法理解他爲什麼總要隨身攜帶筆記本電腦,就連他自己也不是很清楚其中的原因。

  POST["wsdlurl"]; if ($wsdlURL) { // MODIFY THIS -- make sure the path below is set correctly require_once('../nusoap/lib/nusoap.php'); $wsdlURL = urldecode($wsdlURL); $wsdl = new wsdl($wsdlURL); $wsdlerror = $wsdl->getError(); if ($wsdlerror) { echo 'There was an error getting the WSDL file at ' . htmlspecialchars($wsdlURL) . ':<br>' . $wsdlerror; } else { echo $wsdl->WebDescription(); } } else { $htmlPage = '<html> <head> <title>nuSoap WSDL Documentation Generator</title> </head> <body> <h3>nuSoap WSDL Documentation Generator</h3> This page uses the <a href="http://sourceforge.net/projects/nusoap/">PHP nuSOAP</a> library to generate a nice description of a given WSDL file and all of its available methods.<p> <form method="post" action="' .

IBM Lotus Domino 7 中的實用 Web 服務,第 2 部分: 編寫和測試簡單的 Web 服務

 

: 中級

Julian Robichaux, 開發人員, Independent Consultant

2006 年 12 月 26 日

在本 Web 服務系列文章的第 2 篇中,我們將演示如何在 IBM Lotus Domino V7.0 中編寫簡單的 Web 服務,該服務將接受並返回簡單的數據類型、數組以及 InOut 參數。我們還將討論幾個測試方法,會涉及 soapUI、Eclipse、MSSOAP toolkit 和 Apache Axis 測試工具。

您現在想要編寫 Web 服務。太棒了!如果您閱讀了我們的第一篇文章,“IBM Lotus Domino 7 中的實用 Web 服務:什麼是 Web 服務以及它們爲何如此重要”,那麼您已經對什麼是 Web 服務以及它們爲何如此重要有了很好的理解。通過 IBM Lotus Domino V7.0,您可以很方便地創建自己的 Web 服務,其他客戶機或系統可以使用這些 Web 服務。在某種程度上,它就像編寫代理一樣容易。

IBM Lotus Domino Designer 允許使用 LotusScript 或 Java 來編寫 Web 服務,但本文中所有的示例都是使用 LotusScript 編寫的。不過,本文的示例數據庫(請參閱 下載 部分)有用 LotusScript 和 Java 兩種語言編寫的示例 Web 服務以供參考。

背景知識簡介

Lotus Domino V7.0 在 Lotus Domino Designer 中引入了新的 Web 服務設計元素。如果在 Lotus Domino Designer V7.0 客戶機中打開數據庫,就可以看到 Web Services 條目正好位於常見的設計元素樹的 Shared Code 部分的 Agents 條目下(參見圖 1)。

Lotus Domino 負責處理所有的 WSDL 創建和 SOAP 操作,因此您所要做的事情就是在 Web 服務設計元素中編寫代碼,就像爲代理編寫代碼一樣。一旦指定哪一個類用作服務的接口類,Lotus Domino 就可以發佈 WSDL 文件、將引入的 SOAP 請求轉換爲類上的方法調用以及返回方法的結果(如果有的話)作爲 SOAP 響應。

從編寫代碼的立場上看,您所做的一切就是編寫 LotusScript 或 Java 類。Lotus Domino 完成了其餘工作!





回頁首


編寫一個簡單的 Web 服務

現在我們來編寫一個簡單的 Web 服務。爲了新建一個 Web 服務,在 Lotus Domino Designer 中打開數據庫,轉到數據庫設計的 Web Services 部分,然後單擊 New Web Service 按鈕(參見圖 1)。


圖 1. Lotus Domino Designer 中的 Web Service 設計元素部分
Lotus Domino Designer 中的 Web Service 設計元素部分

該屏幕與新建代理時打開的窗口(參見圖 2)很相似。在 Web Services Properties 框中,設置新 Web 服務的名稱 —— 本示例中使用 EchoTestService —— 然後關閉該框。稍後我們將討論 Properties 框中的各個字段。


圖 2. Lotus Domino Designer 中的 Web Service 設計元素
Lotus Domino Designer 中的 Web Service 設計元素

現在應該看到一個與編寫 LotusScript 代理時所使用的窗口很相似的屏幕。單擊 LotusScript 事件中 Objects 附籤的 (Declarations) 以編寫類(必須始終在 (Declarations) 部分中定義類)。將下列代碼輸入到 IDE:


清單 1. 一個非常簡單的返回字符串的 Web 服務
				
Class EchoTest
	Public Function Echo (txt As String) As String
		Echo = txt
	End Function
End Class

該代碼進行以下工作:

  • 創建類 EchoTest。
  • 在類中定義方法 Echo,該方法接受字符串作爲參數並返回字符串作爲結果(類中的函數和 sub 被稱爲方法)。

EchoTest 中的 Echo 方法獲取字符串作爲參數並返回相同的字符串。現在看一下它是否是有效的 Web 服務。嘗試保存並關閉該服務。將收到下面的錯誤:

The Web Service has been saved, but is not valid: 
Please specify which class exposes your Web service interface(s), 
using the 'PortType class' field of the Web Service properties panel.

若要避免此錯誤,請打開 Web Service Properties 框,然後指定要使用的類。因爲 Web 服務代碼中可能定義了多個類,所以必須僅選擇其中一個作爲 Web 服務的接口。接口類就是具有 Public 方法的類,Web 服務客戶機可以調用 Public 方法。

在 Properties 框中,在第一個附籤的 PortType class 字段中輸入 EchoTest(您剛剛編寫的類名)。關閉該框,然後再次嘗試保存並關閉 Web 服務。這次一切正常。現在您有了一個正常運轉的 Web 服務!





回頁首


Web Service Properties 框

下面再次打開 Web service 和 Web Service Properties 框。框中的第一個附籤(Basics 附籤)如圖 3 所示。


圖 3. Web Service Properties 框中的 Basics 附籤
Web Service Properties 框中的 Basics 附籤

對 Basic 附簽上的字段說明如下:

  • Name(必需的):Web 服務的名稱,是客戶機訪問 WSDL 文件或服務的方法時所使用的名稱。
  • Alias:除 Name 之外的另一名稱,用戶使用該名稱可以訪問服務。
  • Comment:有關 Web 服務的信息數據的字段(通常,該字段的信息不超過一句話;有關 Web 服務的較長描述或信息應寫在代碼的註釋中)。
  • Warn if the WSDL interface is modified:該選項警告您對代碼所做的更改是否修改了由 Web 服務產生的 WSDL 文件。這對於確保 WSDL 文件的一致很有用,但是應該意識到,如果選中了該選項,則您將無法保存帶有已修改的 WSDL 文件的服務。
  • PortType class(必需的):用作 Web 服務接口的類的名稱。換句話說,它就是 Web 服務代碼中帶有用戶可訪問的 public 方法的類。

框中的第二個附籤是 Security 附籤(參見圖 4)。


圖 4. Web Service Properties 框中的 Security 附籤
Web Service Properties 框中的 Security 附籤

對 Security 附簽上的字段說明如下:

  • Run as web user:該選項使 Web 服務代碼能夠在調用 Web 服務的用戶的安全性上下文中運行(默認情況下,它將在 Lotus Domino Designer 中最後簽名 Web 服務的那個 ID 的安全性上下文中運行)。
  • Run on behalf of:該字段允許指定用戶,如果想讓 Web 服務代碼運行在特定用戶的安全性上下文中,而不是 Lotus Domino Designer 中最後簽名 Web 服務的那個 ID 的安全性上下文中。
  • Allow remote debugging:該選項允許遠程調試 Web 服務(有關遠程調試的信息,請參閱 Lotus Domino Designer 幫助主題 “Using the Remote Debugger”)。
  • Profile this web service:該選項將在 Web 服務運行時使其生成分析信息(有關分析的信息,請參閱 Lotus Domino Designer 幫助主題 “Profiling agents and Web services”)。
  • Set runtime security level:設置爲 1,允許大多數 LotusScript 和 Java 操作正確運行;對於讀/寫文件、創建 COM 對象或執行網絡操作等,根據需要,設置爲 2 或 3(有關更多信息,請參閱 Lotus Domino Designer 幫助主題 “Restricted LotusScript and Java agent operations”)。
  • Default access for this web service:該選項允許控制哪些用戶可以訪問 Web 服務,並超出了使用數據庫 ACL 所能進行的控制(如果 Anonymous 用戶無法訪問 Web 服務,則當用戶嘗試進行連接時,將收到錯誤 401 Access Denied 或 404 Not Found)。
  • Allow Public Access users to use this web service:該選項使得僅擁有數據庫 ACL 中 “Read Public Documents” 訪問權的用戶可以使用該 Web 服務,當不想爲大量用戶授予完全的 Reader 訪問權限(或更高級別)時,這點很有用。

框中的第三個附籤是 Options 附籤(參見圖 5)。


圖 5. Web Service Properties 框中的 Options 附籤
Web Service Properties 框中的 Options 附籤

對 Options 附簽上的字段說明如下:

  • Programming model:可用選項是 RPC 或 Message(大多數情況下使用 RPC)。
  • SOAP message format:在該字段中,爲此 Web 服務選擇 SOAP 消息格式(有關格式的更多信息,請參閱下一節)。Lotus Domino V7.0 中的默認格式是 RPC/encoded。
  • Include operation name in SOAP action:該選項要求操作名稱存在於外來請求的 SOAP 動作標頭中(很少需要)。
  • Port type name:默認情況下,該字段值與 Basics 附簽上 PortType class 字段的值相同(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。
  • Service element name:默認情況下,該字段值是 PortType 名稱加上單詞 Service(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。
  • Service port name:默認情況下,該字段值是 Domino(儘管您可以使用任何想用的名稱)。生成 WSDL 文件時使用該值。

如您所見,可以設置很多屬性,儘管其中只有 Web service name 和 port type class 是必需的。其他所有屬性都是可選的或是有適當的默認值。

SOAP 消息格式

在 Web Service Properties 框中,有很多不同的 SOAP 消息格式可以選擇,所以不易決定到底應該使用哪一個。各種格式將創建略有不同的 WSDL 文件,反過來會產生略有不同的 SOAP 請求和響應。

從編寫代碼的立場看,您不會注意到這些不同,因爲無論使用哪一種格式,所編寫的 Web 服務是完全相同的。但是,這會使調用 Web 服務的用戶客戶機有所不同。

通常,RPC/encoded 格式是較早的 Web 服務客戶機技術(如 Apache SOAP 和 MSSOAP)廣泛支持的格式。Doc/literal 由 Microsoft .NET 客戶機和服務器默認使用,並在過去的幾年中漸受歡迎。

消息格式的選擇依賴於調用服務的客戶機所使用的技術以及哪一種 SOAP 格式最易於使用該客戶機技術。如果不能控制調用服務的客戶機,則 RPC/encoded 和 Doc/literal 都是很好的選擇。

有關不同格式以及其如何影響 WSDL 結構和 SOAP 消息的詳細說明,請參閱經常被提到的 developerWorks 文章 “Which style of WSDL should I use?”。





回頁首


使用簡單數據類型的 Web 服務

現在回過頭來編寫 Web 服務代碼。我們知道用來公開 Web 服務的 LotusScript 代碼需要作爲類進行編寫。實際上,通常用 LotusScript 編寫的任何函數或 sub 在 Web 服務中都是作爲類方法使用的,並帶有以下限制:

  • 不要使用原生 LotusScript 類(如 NotesDatabase、NotesDocument 等)作爲參數或返回值。
  • 不要使用變量或貨幣數據類型作爲參數或返回值。
  • 不要使用列表或數組作爲參數或返回值(可以使用數組,不過必須使用稍後在本文中所描述的一種特定數據類型)。
  • 不要使用定製類型作爲參數或返回值。

相反,可以在 Web 服務類方法中使用以下內容作爲參數或返回值:

  • 簡單的數據類型(字符串、整數等)
  • 定製的用戶定義的類
  • lsxsd.lss 文件中定義的特殊類(該文件包含在 Lotus Notes/Domino V7.0 客戶機和服務器文件中)

將用戶定義的類是一種複雜的數據類型,我們將在下一篇文章中進行討論。lsxsd.lss 文件(可以在本地的 Notes 程序目錄中找到)中的類是很有用的,允許傳遞字符串數組、文件和數據。稍後本文將對其中一些類進行討論,其餘的類將在下一篇文章中進行討論。

現在先來看一些在類中使用簡單數據類型的示例。考慮下面的類:


清單 2. 帶有多個方法的 LotusScript Web 服務
				
Class DatabaseInfo
	Private session As NotesSession
	Private db As NotesDatabase
	
	Public Sub New ()
		Set session = New NotesSession
		Set db = session.CurrentDatabase
	End Sub
	
	Public Function GetDbName () As String
		GetDbName = db.Title
	End Function
	
	Public Sub UpdateFTIndex ()
		Call db.UpdateFTIndex(True)
	End Sub
	
	Public Function GetUserRoles (userName As String) As String
		GetUserRoles = Join(getRoles(userName), ",")
	End Function
	
	Private Function getRoles (userName As String) As Variant
		Dim acl As NotesACL
		Dim entry As NotesACLEntry
		Dim sep As String
		
		Set acl = db.ACL
		Set entry = acl.GetEntry(userName)
		
		If (entry Is Nothing) Then
			Dim returnArray(0) As String
			getRoles = returnArray
		Else
			getRoles = entry.Roles
		End If
	End Function
End Class

以上代碼淺顯易懂,不過對於各種方法,請注意以下內容:

  • New:方法 New 是可選的,且不能用於那些調用 Web 服務的客戶機。如果需要的話,僅用於初始化代碼。同時,如果編寫 New 方法,那麼它必須是 sub 且沒有任何參數。
  • GetDbName:方法 GetDbName 沒有任何參數。這是規定的。
  • UpdateFTIndex:方法 UpdateFTIndex 沒有任何參數且不返回值。這也是規定的。
  • GetUserRoles:方法 GetUserRoles 將調用其他方法來執行大部分工作。也可以調用其他函數和 sub(類以外的),甚至可以使用 Use 語句引用 script 庫,從 script 庫中調用類、函數和 sub。這很有用,因爲這樣不僅可以保持 Web 服務代碼的簡潔,而且有助於從已有的任何業務邏輯代碼中分離出 Web 服務代碼。
  • getRoles:方法 getRoles 聲明爲 Private,因此類中的其他方法可以使用該方法,但是,不能用於那些調用 Web 服務的客戶機。將一些方法聲明爲 Private 是一個很好的做法,以便保持代碼和邏輯位於類中,同時不允許用戶直接調用方法。

    但是,請記住如果既沒有將方法聲明爲 Public,也沒有將其聲明爲 Private,則該方法將作爲 Public 方法使用。

到目前爲止,實際上沒有什麼複雜的東西。由您決定用戶可以調用的函數/sub,然後將其作爲方法包含在類中。如果已經編寫了所需的代碼或邏輯,那麼您還可以從 script 庫中引用其他類、函數和 sub。





回頁首


返回數組

您可能已注意到方法 GetUserRoles 在返回值前,將 getRoles 方法返回的字符串數組轉化爲單一的一個分隔的字符串。這是因爲不能直接從 Web 服務作爲數組或變量返回 LotusScript 數組。

但是,通過返回 lsxsd.lss 文件中其中一個 ARRAY_HOLDER 類的實例,可以返回數組。將 ARRAY_HOLDER 類(STRINGARRAY_HOLDER、INTEGERARRAY_HOLDER 等)作爲值返回時,這些類將自動轉換爲支持 SOAP 的數組。

爲了舉例說明,可以將 %INCLUDE "lsxsd.lss" 行添加到 Web 服務的 (Options) 部分,然後重寫 GetUserRoles 方法,如下所示:


清單 3. 在 LotusScript Web 服務中返回字符串數組
				
	Public Function GetUserRolesArray (userName As String) As STRINGARRAY_HOLDER
		Dim returnArray As New STRINGARRAY_HOLDER
		Dim roles As Variant
		Dim i As Integer
		
		roles = getRoles(userName)
		Redim returnArray.Value(Ubound(roles))
		For i = 0 To Ubound(roles)
			returnArray.Value(i) = roles(i)
		Next
		
		Set GetUserRolesArray = returnArray
	End Function

就用戶的客戶機而言,GetUserRolesArray 方法將返回常規的字符串數組,而不是特定的 STRINGARRAY_HOLDER 對象。這是因爲訪問服務時,Domino Web 服務在後臺完成了 STRINGARRAY_HOLDER 和字符串數組之間的轉化。還需要做一些額外工作將 getRoles 數組的元素添加到 STRINGARRAY_HOLDER 的 Value 成員中(因爲不能直接將 Value 設置爲等於另一個數組),不過這只是幾行代碼的事。

當然,字符串數組不是惟一可以接受或返回的數組類型,INTEGERARRAY_HOLDER、LONGARRAY_HOLDER、和 lsxsd.lss 文件中定義的類似的類也可以爲其他原生數據類型提供相同的功能。有關更多信息,請參閱 Lotus Domino Designer 幫助或 lsxsd.lss 文件。

返回數組的另一種選擇是將數組作爲複雜數據類型的組成部分返回,該技巧我們將在下一篇文章中進行討論。





回頁首


使用 InOut 參數返回多個值

當僅希望使用簡單數據類型時,另一種可以使用的方法是 InOut 參數。有些參數既可以接收輸入值,也可以返回輸出值。例如,考慮下面的類:


清單 4. 在 LotusScript Web 服務中使用 InOut 參數
				
Class InOutTest
	Public Sub AddOne (inout As INTEGER_HOLDER)
		inout.Value = inout.Value + 1
	End Sub
	
	Public Function SwapAndAdd (inout1 As INTEGER_HOLDER, _
	inout2 As INTEGER_HOLDER) As Integer
		SwapAndAdd = inout1.Value + inout2.Value
		inout1.Value = inout2.Value
		inout2.Value = SwapAndAdd - inout2.Value
	End Function
End Class

第一個方法 (AddOne) 使用整數作爲輸入參數。方法中的代碼爲傳遞的值增加 1 —— 因爲它是 INTEGER_HOLDER —— 並將新值返回到 SOAP 響應中。

這是 lsxsd.lss 文件中所定義的 HOLDER 類的特殊屬性。將該類用作方法參數時,它們將變成 SOAP 請求/響應中的 InOut 參數,因此可以接收並返回值。

方法 AddOne 並不是一個很實際的示例,因爲通常只需接收常規整數作爲參數,並且作爲能返回修改的整數的函數編寫此方法。但是,如果有一個或多個 InOut 參數作爲方法返回值,那麼就可以在方法響應中返回多個獨立的值而不是單個值。

現在看一下第二個方法 SwapAndAdd。該方法有兩個 InOut 值作爲參數,並返回整數。在用戶客戶機上,它們生成 SOAP 請求用來作爲參數發送兩個整數值,並且接收 SOAP 請求,該 SOAP 請求的響應具有三個整數值:其中兩個作爲參數進行傳遞(並且通過方法進行修改),另一個是結果。

不可否認,InOut 參數不那麼常見,因爲返回多個值通常是通過返回複雜數據類型來處理的,但這仍是個值得注意的好方法。再次說明,我們將在本系列的下一篇文章中討論複雜數據類型。





回頁首


使用日期和時間

您需要使用的最後一個簡單數據類型是日期/時間對象。下面的示例演示了使用參數中的日期/時間並返回對象:


清單 5. 在 LotusScript Web 服務中使用日期和時間
				
Class DateTester
	Public Function getCurrentTime () As XSD_DATETIME
		Dim dt As New NotesDateTime(Now)
		Set getCurrentTime = New XSD_DATETIME
		Call getCurrentTime.SetValueFromNotesDateTime(dt)
	End Function
 	
	Public Function getLocalDateFormat (xdt As XSD_DATETIME) As String
		Dim dt As NotesDateTime
		Set dt = xdt.GetValueAsNotesDateTime()
		getLocalDateFormat = dt.LocalTime
	End Function
End Class

lsxsd.lss 類再次發揮了作用。可以只接收或返回 XSD_DATETIME(變成了 SOAP dateTime 元素)類型變量並在它與 NotesDateTime 對象之間進行轉換。

但是,應注意到時間值的時區處理會比較困難,因爲服務器和客戶機可能正確也可能會不正確地添加或解釋 SOAP dateTime 元素的時區偏移。最新的 W3C Note 對該問題的某些方面進行了討論。通常,首先應試着徹底測試 Web 服務客戶機。





回頁首


測試 Web 服務

在本地數據庫上測試 Web 服務

如果您有數據庫的本地副本和要測試的 Web 服務,那麼首先請確保 Notes HTTP 服務在後臺運行。最方便的做法是:

  1. 在 Lotus Domino Designer 中打開數據庫。
  2. 在數據庫中選擇 Form 或 View。
  3. 選擇 Design - Preview in Web Browser - Default Browser,然後等待 Web 瀏覽器中出現窗體或視圖。

在 Web 瀏覽器中看到窗體或視圖後,可以選擇瀏覽器窗口,然後測試 Web 服務。HTTP 服務繼續在後臺運行,直到完全關閉 Notes 客戶機。有些個人防火牆會阻塞本地 HTTP 服務的操作,因此可能需要調整防火牆設置。

已經編寫了 Web 服務之後,肯定想對它進行測試。爲了訪問 Web 服務的 WSDL,必須使用 Web 服務的完整 URL 路徑,該路徑以 ?WSDL URL 命令結尾。

例如,可以對 DNS 名爲 mydomino.example.com 的服務器上的 WSTest.nsf 數據庫的 Web 服務 MyNewWebService 使用下面的 URL:

http://mydomino.example.com/WSTest.nsf/MyNewWebService?WSDL

有很多可用於測試 Web 服務的測試工具 —— 既有免費工具,也有商業工具 —— 可以很方便地編寫較長的文章或教程來描述各種測試方法。

下面是幾個測試工具可用於測試和調用 Web 服務,每個測試工具都有一段簡短描述。熟悉每個工具的詳細信息是留給讀者的練習。

soapUI

測試 Web 服務時,最易於使用的工具之一是 soapUI,可從 soapUI Web 站點 獲得。SoapUI 是用 Java 編寫的免費的桌面程序,因此可以在不同操作系統上運行。下面是使用 SoapUI 對 Web 服務進行測試的步驟:

  1. 請確保在本地機器上正確安裝了 Java 1.5 或更高版本。
  2. 下載 soapUI program 並將其解壓縮。
  3. 在解壓縮文件的 /bin 目錄中,運行 soapui.bat 文件(Windows 操作系統下)或 soapui.sh 文件(其他操作系統下)來打開 soapUI。
  4. 選擇 File - New WSDL Project,然後根據提示,輸入項目名稱。
  5. 在左側導航欄中,右鍵單擊屬性列表中的新項目,然後選擇 “Add WSDL From URL” 選項。
  6. 輸入測試服務的 URL(例如,http://localhost/DWSTest.nsf/EchoTestService?WSDL),如果提示要爲所有操作創建默認請求,則單擊 Yes。
  7. 現在,可以在左側完全展開新項目並查看可用於調用的每個 Web 服務方法的條目。如果雙擊方法名稱下的 Request 條目,將看到預構建的 SOAP 請求,可以將其作爲一個測試進行發送(參見圖 6)。

    圖 6. soapUI 接口
    soapUI 接口

  8. 對於圖 6 中的 EchoTest 服務,有一個簡單 SOAP 請求用於發送。如果想測試該服務,則在請求 envelope 的 <TXT> 節點中輸入文本,然後單擊位於 SOAP 請求文本上方的工具欄中的綠色箭頭按鈕。這將發送請求到服務並在右側窗格中顯示得到的 SOAP 響應。

SoapUI 允許您構造測試套件,適於對 Web 服務進行單元測試。這樣,就可以創建一套測試,當修改了 Web 服務後,可以運行預先編寫的測試來確保各方面仍正確運行。

其缺點是所有事情都必須通過原始 XML SOAP 請求和響應來執行。如果您習慣使用 XML 和 SOAP,就不會覺得很難,因爲最難的部分(首先要編寫 SOAP 請求)已經替您完成了,並且您可以查看 SOAP 響應。但是,如果您更喜歡在較抽象的層面上工作 —— 在程序中使用簡單的 API 或函數 —— 那麼該工具對於您來說就過於低級了。

Eclipse 和 Web Tools Platform (WTP)

如果已經安裝了 Eclipse(或者需要理由來使用 Eclipse),有一個非常好的包 Web Tools Platform (WTP) 爲測試 Web 服務提供了更高水平的接口。不需要使用原始 SOAP 請求,WTP 可以爲每個 Web 服務方法創建窗體,您只需在窗體中輸入值,然後發送請求。

下面是安裝和使用 WTP 的基本步驟:

  1. 下載並安裝 Eclipse platform
  2. 安裝 WTP 組件。對於 Eclipse 3.2 之前的版本,請參閱 WTP Web 站點上的安裝指南。對於 Eclipse 3.2 或更高版本,這些指南是 “Web and J2EE Development” 下的 Callisto toolkit 的一部分。進行以下操作:
    1. 選擇 Help - Software Updates - Find and Install。
    2. 在下一個屏幕上,選擇 “Search for new features to install2”,然後單擊 Next。
    3. 請確保選中了 Callisto Discovery Site 選項,然後單擊 Next。
    4. 在要安裝的包列表的 Callisto Discovery Site 部分下,選擇 “Web and J2EE Development” 項(也選擇了該項下的所有項)。然後單擊 “Select Required” 按鈕以獲取所有其他所需組件,並單擊 Next 進行安裝(參見圖 7)。安裝過程需要幾分鐘的時間。


    圖 7. Eclipse 中的 WST 包安裝
    Eclipse 中的 WST 包安裝

  3. 完成安裝後,重新啓動 Eclipse。從主 Workbench 頁面,選擇 Run - Launch the Web Services Explorer。
  4. 在 Web Services Explorer 視圖中,單擊 WSDL Page 按鈕,將 WSDL Main 添加到 Navigator 窗格(參見圖 8)。

    圖 8. WST 中的 WSDL Explorer
    WST 中的 WSDL Explorer

  5. 可以在 Actions 窗格中輸入 WSDL 路徑。輸入測試服務的 URL(例如,http://localhost/DWSTest.nsf/EchoTestService?WSDL),然後單擊 Go 按鈕。
  6. 找到 WSDL 文件後,在 Navigator 窗格的 WSDL Main 條目下應該有一個樹狀結構,列出了 Web 服務中的所有方法。
  7. 雙擊 WSDL 樹中的任一方法名,將在 Actions 窗格中出現窗體,允許您在該窗體中輸入方法的每個參數值,並將值發送到 Web 服務。響應將顯示在底部的 Status 窗格中(參見圖 9)。

    圖 9. WST 中的 SOAP 請求
    WST 中的 SOAP 請求

  8. 如果您想查看由 Web 服務調用發送和接收的原始 XML SOAP 消息,則單擊 Status 窗格中的 Source link。

雖然 Eclipse WTP 的初始設置比 soapUI 工具更復雜,但它提供了更友好的用戶接口(用窗體代替了原始請求)。如果需要底層的細節,仍可以查看發送和接收的原始消息,不過一些人發現使用基於窗體的方法更易於創建和發送請求。

MSSOAP toolkit

很多使用 Windows 平臺的 LotusScript 編程人員已經成功使用 MSSOAP toolkit 來調用 Web 服務。雖然該 toolkit 不再受支持也不再由 Microsoft 更新(已經被 Microsoft .NET 框架取代),但它仍是一個通用的技術,因此在這裏值得一提。

MSSOAP 是一個 DLL 文件,可以從 Microsoft 下載或作爲標準 Windows 安裝的一部分安裝在工作站上。使用 LotusScript,可以將 DLL 作爲 COM 對象進行調用,如下所示:


清單 6. 來自 LotusScript 的簡單 MSSOAP 調用
				
Dim Client As Variant
Set Client = CreateObject("MSSOAP.SoapClient")
Call Client.MSSoapInit("http://localhost/DWSTest.nsf/EchoTestService?WSDL")
Print "Echo said " & Client.Echo("echo")

顯然,需要對所使用的 Web 服務中的方法、參數和數據類型有一些瞭解。如果調用另一個 Web 服務,可以手動讀取並解釋 WSDL 文件(可能很麻煩),也可以使用類似 soapUI 或 Eclipse WTP 的工具來解釋所有事情。

不幸的是,我們發現在 Windows 操作系統上使用的 MSSOAP 版本一般是 1.x 版,只能使用 RPC/Encoded Web 服務,該服務使用簡單數據類型作爲參數。當返回複雜數據類型時,通常是 IXMLDOMNodeList 對象,但將複雜數據類型作爲參數進行傳遞時,需要創建新的 IXMLDOMNodeList 對象且不易處理。一般情況下,MSSOAP 1.x 也無法理解使用了枚舉的 Web 服務(將在本系列的下一篇文章中進行討論)。

如果您可以控制使用 MSSOAP 庫的服務器或工作站,那麼可以選擇下載並安裝 SOAP Toolkit 版本 3.0,它允許您調用更廣泛的 Web 服務。安裝該 toolkit 後,您可以將上述代碼由 CreateObject("MSSOAP.SoapClient") 更改爲 CreateObject("MSSOAP.SoapClient30") 以便使用較新版本的庫。表 1 列出了兩個版本之間的差別。


表 1. MSSOAP 1.x 和 3.0 之間的差別
MSSOAP 1.x MSSOAP 3.0
默認情況下,在大多數使用 Windows XP/2000 的機器上 必須 下載 並安裝
CreateObject("MSSOAP.SoapClient") CreateObject("MSSOAP.SoapClient30")
僅適用 RPC/Encoded Web 服務 RPC/Encoded、RPC/Literal、Doc/Literal、來自 LotusScript Web 的 Wrapped
不能解釋枚舉 可以解釋由 LotusScript Web 服務返回的枚舉,但有可能不能正確解釋從 Java Web 服務返回的枚舉

MSSOAP 允許動態調用 Web 服務(這很方便),關於使用 MSSOAP(在 LotusScript 和 Visual Basic 中,後者可以方便地轉換爲 LotusScript)有大量的代碼示例。因此,如果您從使用 Windows 的機器上調用 Web 服務,這是個很好的選擇。

Apache Axis

在 Lotus Notes 環境中,Apache Axis 框架是調用 Web 服務的另一種很好的選擇。Axis 是一個非常成熟的 Java 包,多年來一直用於在不同平臺上創建、提供和使用 Web 服務。實際上,Axis 是允許 Lotus Domino V7 提供 Web 服務的底層技術!

如果使用 Axis 作爲客戶機來調用 Web 服務,通常基於服務的 WSDL 文件會使用 Java 命令行工具(隨 Axis 提供的)wsdl2java 來創建調用 Web 服務的 stub 文件。這些 stub 文件是用作複雜代碼的包裝程序的 Java 類,這些複雜代碼是訪問和使用 Web 服務時所需要的,因此所有您需要做的事情就是使用 stub 類來調用方法並返回響應。雖然您必須爲要調用的任何 Web 服務完成生成 stub 文件的前端工作,但這將減少後續麻煩,即必須瞭解錯綜複雜的 Web 服務(消息格式、名稱空間、響應解析等)。

如果要在 Lotus Notes 中使用 Apache Axis 來編寫代碼以便調用 Web 服務,比較好的起點是 developerWorks 文章 “通過 Lotus Domino Java 代理消費 Web 服務” 和開源 Stubby 數據庫,該數據庫可從 OpenNTF Web 站點獲取。作爲示例,下面演示瞭如何使用 Stubby 來創建 Axis 代碼以調用 EchoTest 服務:

  1. 從 OpenNTF.org 下載 Stubby 數據庫 並在 Lotus Notes V7 客戶機中打開。
  2. 單擊 Create New Doc 按鈕,在數據庫中創建新文檔,並在窗體的 WSDL File 字段輸入 EchoTest 服務的 URL (http://localhost/DWSTest.nsf/EchoTestService?WSDL) (參見圖 10)。

    圖 10. Stubby 數據庫文檔
    Stubby 數據庫文檔

  3. 單擊窗體上的 Generate Stub Files 按鈕,創建 Axis stub 文件。同時創建了 JAR 文件,包含了所有已編譯的且可以使用的 stub 文件。創建的所有文件附在 Stubby 文檔的 generated files 附籤的字段中。
  4. 將 generated files 附簽上的 JAR 文件(在本例中爲 EchoTestService.jar)移至本地文件系統。
  5. 使用 Lotus Domino Designer V7 在數據庫中創建新的 Java 代理,然後使用 Edit Project 按鈕附上前一步中的 JAR 文件。
  6. 從 Stubby 文檔的 sample code 附簽上,複製所生成的示例代理代碼,然後粘貼到代理中。還需要添加一行代碼用來調用 Web 服務的 Echo 方法。得到的代理代碼類似清單 7 中所示(爲了簡潔,刪除了註釋和空行):

    清單 7. 在 Lotus Notes Java 代理中使用 Apache Axis stub 文件
    						
    import lotus.domino.*;
    import DefaultNamespace.*;
    public class JavaAgent extends AgentBase {
        public void NotesMain() {
            try {
                EchoTestServiceLocator locator = new EchoTestServiceLocator();
                EchoTest service = locator.getDomino();
                System.out.println("Echo said " + service.ECHO("echo"));
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

  7. 現在您可以在任何 Lotus Notes/Domino V7 客戶機或服務器上運行該代理以訪問 Web 服務。

對於喜歡使用 LotusScript 的編程人員,Stubby 數據庫中還有很多示例使用 LS2J 調用以 LotusScript 編寫的 Web 服務 stub 代碼。有關 LS2J 的更多信息,請參閱 Lotus Domino Designer 幫助。

PHP nuSOAP

測試 Web 服務時,您可以嘗試的另一個有趣的事情是 PHP nuSOAP 庫。它不僅可以很方便地用於使用 Web 服務,而且可以提供一種很好的方式,用於顯示有關 Domino Web 服務的信息。

例如,您有一個可用的 PHP 服務器(或者有一個本地的 PHP 安裝,如 WAMP server),那麼您可以將 nuSOAP 庫複製到該服務器上並創建以下頁面:


清單 8. 使用 PHP nuSOAP 來獲取有關 WSDL 文件的詳細信息
___FCKpd___8

如果您將該頁面保存到 PHP 服務器並在瀏覽器中打開它,將提示您輸入 WSDL 文件的 URL 位置。輸入 URL 並單擊 Submit 按鈕後,您將看到一個頁面,描述了 Web 服務的每個 public 方法(參見圖 11)。


圖 11. PHP nuSOAP WSDL 文檔示例
PHP nuSOAP WSDL 文檔示例

注意:如果 Web 服務是在本地機器的數據庫中,則需要從本地安裝的 PHP 服務器上運行該頁面(再次說明,可以很方便地設置和使用 WAMP 服務器),並且需要確保本地 PHP 服務器未使用端口 80(因此不會干擾本地的 Notes HTTP 服務)。

用於 Domino SOAP 消息跟蹤的 SoapLog

可以考慮使用的另一個工具是 SoapLog DSAPI Filter。這是一個 DLL 文件和 Notes 數據庫(可以複製到服務器),並且它記錄了發送到服務器上 Web 服務的 SOAP 消息。在撰寫本文的時候,DLL 僅用於 Windows 服務器,而且還沒有免費版的 SoapLog DSAPI Filter。

可以按照以下步驟來安裝 SoapLog 工具:

  1. 下載 SoapLog 並將其解壓縮到本地工作站。
  2. 將 soaplog.dll 文件複製到 Domino 服務器上的 Notes program 目錄中。
  3. 將 SoapLog.nsf 數據庫複製到 Domino 服務器上的數據目錄中,然後根據需要調整 ACL(主要確保服務器可以寫入)。
  4. 將 SOAPLOG_DBNAME 變量添加到服務器的 Notes.ini 文件,指向 SoapLog.nsf 數據庫。例如,如果 SoapLog.nsf 數據庫位於根數據目錄中,則將下面一行代碼添加到 Notes.ini 文件:
    ___FCKpd___9

  5. 在 Domino Directory 中打開服務器文檔。在 Internet Protocols - HTTP 附簽上,將在右側頁面中部看到 DSAPI。在該字段中添加 soaplog.dll 條目(如果該字段中已經有條目,則在添加 soaplog.dll 條目前,先新添一行)。
  6. 在 Domino 服務器上重新啓動 HTTP 任務。應看到一條消息,指明已裝入 SoapLog DSAPI。

裝入過濾器後,服務器上 Web 服務的所有 SOAP 消息請求將在 SoapLog.nsf 數據庫中創建新的日誌文檔(參見圖 12 和 13)。


圖 12. SoapLog request 附籤
SoapLog request 附籤

圖 13. SoapLog response 附籤
SoapLog response 附籤

還可以設置其他的 Notes.ini 參數以便進一步過濾日誌。有關如何操作的更多信息,請參閱 SoapLog.nsf 數據庫中的 Using This Database 文檔。





回頁首


結束語

本文簡單介紹了在 Lotus Domino V7 中創建和測試一個簡單的 Web 服務的步驟。在 Domino V7 平臺上可以很方便地創建和提供 Web 服務,使用的代碼與您爲 LotusScript 或 Java 代理編寫的代碼很相似。雖然在 Lotus Notes 中測試和調用 Web 服務並不像提供服務一樣自然,但還是有很多很好的方法可用來編寫能夠與服務進行交互的 Web 服務客戶機。

這種做法最大的優點在於您的企業中使用其他(非 Domino)Web 服務的系統仍可以方便地訪問和使用您所編寫的 Web 服務,這使得 Lotus Domino 被廣泛應用於 SOA 環境中。

本系列的下一篇文章將着重介紹如何編寫更復雜的 Web 服務,這些服務使用了複雜數據類型,可以發送和接收文件附件或生成定製錯誤。






回頁首


下載

描述 名字 大小 下載方法
示例數據庫內含代碼 DWSTest.nsf 1 MB HTTP
關於下載方法的信息 Get Adobe® Reader®


參考資料

學習

獲得產品和技術

討論


關於作者

 

Julian Robichaux 是專門研究 IBM Lotus Notes 和 Java 開發的軟件開發人員和專業程序員。他擅長於各種與開發、架構及培訓有關的項目。在業餘時間,他喜歡在 http://www.nsftools.com 上添加個人 Web 站點/博客。他的家人無法理解他爲什麼總要隨身攜帶筆記本電腦,就連他自己也不是很清楚其中的原因。

  SERVER['PHP_SELF'] . '"> Please enter the URL of your WSDL file below:<br> <input type="text" size="75" name="wsdlurl"><p> <input type="submit" value="submit" name="submit"><br /> </form> </body> </html>'; echo $htmlPage; } ?>

如果您將該頁面保存到 PHP 服務器並在瀏覽器中打開它,將提示您輸入 WSDL 文件的 URL 位置。輸入 URL 並單擊 Submit 按鈕後,您將看到一個頁面,描述了 Web 服務的每個 public 方法(參見圖 11)。


圖 11. PHP nuSOAP WSDL 文檔示例
PHP nuSOAP WSDL 文檔示例

注意:如果 Web 服務是在本地機器的數據庫中,則需要從本地安裝的 PHP 服務器上運行該頁面(再次說明,可以很方便地設置和使用 WAMP 服務器),並且需要確保本地 PHP 服務器未使用端口 80(因此不會干擾本地的 Notes HTTP 服務)。

用於 Domino SOAP 消息跟蹤的 SoapLog

可以考慮使用的另一個工具是 SoapLog DSAPI Filter。這是一個 DLL 文件和 Notes 數據庫(可以複製到服務器),並且它記錄了發送到服務器上 Web 服務的 SOAP 消息。在撰寫本文的時候,DLL 僅用於 Windows 服務器,而且還沒有免費版的 SoapLog DSAPI Filter。

可以按照以下步驟來安裝 SoapLog 工具:

  1. 下載 SoapLog 並將其解壓縮到本地工作站。
  2. 將 soaplog.dll 文件複製到 Domino 服務器上的 Notes program 目錄中。
  3. 將 SoapLog.nsf 數據庫複製到 Domino 服務器上的數據目錄中,然後根據需要調整 ACL(主要確保服務器可以寫入)。
  4. 將 SOAPLOG_DBNAME 變量添加到服務器的 Notes.ini 文件,指向 SoapLog.nsf 數據庫。例如,如果 SoapLog.nsf 數據庫位於根數據目錄中,則將下面一行代碼添加到 Notes.ini 文件:
    ___FCKpd___9

  5. 在 Domino Directory 中打開服務器文檔。在 Internet Protocols - HTTP 附簽上,將在右側頁面中部看到 DSAPI。在該字段中添加 soaplog.dll 條目(如果該字段中已經有條目,則在添加 soaplog.dll 條目前,先新添一行)。
  6. 在 Domino 服務器上重新啓動 HTTP 任務。應看到一條消息,指明已裝入 SoapLog DSAPI。

裝入過濾器後,服務器上 Web 服務的所有 SOAP 消息請求將在 SoapLog.nsf 數據庫中創建新的日誌文檔(參見圖 12 和 13)。


圖 12. SoapLog request 附籤
SoapLog request 附籤

圖 13. SoapLog response 附籤
SoapLog response 附籤

還可以設置其他的 Notes.ini 參數以便進一步過濾日誌。有關如何操作的更多信息,請參閱 SoapLog.nsf 數據庫中的 Using This Database 文檔。





回頁首


結束語

本文簡單介紹了在 Lotus Domino V7 中創建和測試一個簡單的 Web 服務的步驟。在 Domino V7 平臺上可以很方便地創建和提供 Web 服務,使用的代碼與您爲 LotusScript 或 Java 代理編寫的代碼很相似。雖然在 Lotus Notes 中測試和調用 Web 服務並不像提供服務一樣自然,但還是有很多很好的方法可用來編寫能夠與服務進行交互的 Web 服務客戶機。

這種做法最大的優點在於您的企業中使用其他(非 Domino)Web 服務的系統仍可以方便地訪問和使用您所編寫的 Web 服務,這使得 Lotus Domino 被廣泛應用於 SOA 環境中。

本系列的下一篇文章將着重介紹如何編寫更復雜的 Web 服務,這些服務使用了複雜數據類型,可以發送和接收文件附件或生成定製錯誤。






回頁首


下載

描述 名字 大小 下載方法
示例數據庫內含代碼 DWSTest.nsf 1 MB HTTP
關於下載方法的信息 Get Adobe® Reader®


參考資料

學習

獲得產品和技術

討論


關於作者

 

Julian Robichaux 是專門研究 IBM Lotus Notes 和 Java 開發的軟件開發人員和專業程序員。他擅長於各種與開發、架構及培訓有關的項目。在業餘時間,他喜歡在 http://www.nsftools.com 上添加個人 Web 站點/博客。他的家人無法理解他爲什麼總要隨身攜帶筆記本電腦,就連他自己也不是很清楚其中的原因。

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