蔡淵 方連航 陳華軍 楊航
【摘要】介紹了一種IEC 61968標準接口的WebServices自動化測試方法。對IEC 61968標準接口的WebServices實現進行了介紹,使用Apache CXF作為WebServices的實現中間件,采用CXF中的攔截器來實現可定制的WebServices輸入和輸出展示,可對WebServices的請求和響應消息體進行編輯和查看,從而實現對IEC 61968 WebServices接口的自動化測試。
【關鍵詞】IEC61968CX;WebServices攔截器
1.引言
隨首電力信息化系統的發展,各開發商為不同的業務部門開發了相應的業務信息化系統,由于各開發商所使用的技術不同、開發周期不同,沒有采用統一的技術,從而導致各業務系統相互獨立,業務系統間形成數據的壁壘,數據只能在各業務系統內流轉,從而產生“數據孤島”問題,嚴重阻礙了信息化建設的開展,容易形成重復建設的情況,降低了數據作為“資產”的價值。
“信息孤島”現象不是一個個案,在電力行業乃至信息化行業內普遍存在,為了解決電力行業內的“信息孤島”問題,國際電力標準委員會制定了IEC 61970/IEC 61968系列標準。IEC 61970標準中定義了公共信息模型(Common Information Model,CIM[1])和組件接口規范(Component Interface Specification,CIS[2]),為各應用系統間的交互提供了語義和語法上的依據。IEC 61970定義的CIS接口采用CORBA(Common Object Request Broker Architecture,CORBA[3])技術,技術門檻較高,且采用緊耦合的方式,適合以高性能進行大量數據的傳輸,對于一些通知消息類的小數據量傳輸來說,其結構過于龐大,不利于開發商的快速實現,為此IEC 61968標準在IEC 61970 CIM/CIS標準的基礎之上,擴展了配電管理部分的CIM模型,并定義了業務系統信息交換模型(Information Exchange Model,IEM[4])和另一種松耦合方式的消息傳遞標準,以當前流行的WebServices技術進行實現。
本文對IEC 61968標準定義的WebServices標準接口進行了介紹,同時描述了一個采用Apache CXF[5]實現的IEC 61968標準接口的測試方法,采用JAVA編程語言,以CXF中攔截器的方式實現對WebServices輸入輸出的攔截,并對輸入輸出XML[6]內容進行查看和編輯,可以為不同的要求配置不同的WebServices輸入內容,從而實現IEC 61968標準接口的自動化測試。
2.IEC 61968 WebServices接口
IEC 61968接口可以通過多種技術方式進行實現,如WebServices、JMS等,本文對WebServices實現方式進行了說明。
IEC 61968標準定義了一個通用的接口,并以WSDL[7]的方式對接口進行了規范化定義,其中WebServices服務名稱為:Service,該服務只包含三個方法:
PublishEvent:事件發布方法,用于事件通知。PublishEvent方法的輸入參數為EventMessage,返回值為ResponseMessage。
Request:請求方法,用于查詢或更新操作。Request方法的輸入參數為RequestMessage,返回值為ResponseMessage。
Response:響應方法,用于對通知消息的確認,或是對數據處理結果的反饋。Response方法的輸入參數為ResponseMessage,返回值為ResponseMessage。
3.IEC 61968消息結構
3.1 消息頭結構
IEC 61968 Header(消息頭)包含了一些消息基本描述與控制信息。請求、響應、事件消息都有消息頭結構。消息頭只有Verb(動詞)和Noun(名詞)兩個必須的字段,其他的字段都是可選的,消息頭包括以下元素:
Verb(動詞):描述要進行的動作,用來標識要采取的動作類型,如create(創建)、close(關閉)、cancel(取消);created(已創建)、closed(已關閉)、changed(已更改)。IEC 61968標準規范了一個動詞列表,動詞取值只能從動詞列表中選擇。
Noun(名詞):用來標識Payload(消息有效內容)的類型,描述消息的主題。
Revision(修訂):消息修訂版本號。
ReplayDetection(重發檢測):這是一個復雜元素,包含一個timestamp(時標)和一個nonce(隨機數)用于防止重發攻擊。時標由源系統生成表示消息創建的時間;隨機數是一個序列號或隨機生成的字符串(例如UUID),由源系統生成,并且在一天內不允許重復。
Context(上下文):表示消息上下文,如PRODUCTION(生產)、TESTING(測試)、STUDY(研究)、TRAINING(培訓)等。
Timestamp(時標):一個遵循ISO-8601的字符串,表示消息發送的時間。
Source(來源):消息產生的來源,系統或組織的名稱,如EMS、GIS。
AsyncReplyFlag(異步應答標志):表示應答消息是否異步發送。
ReplyAddress(應答地址):異步應答發送消息的目標地址。
AckRequired(確認請求):表示請求的消息是否需要一個回傳的確認消息。
User(用戶):一個復雜結構表示用戶以及相關的組織,包含一個UserID(用戶標識)Organization(組織標識)。
MessageID(消息ID):消息的唯一標識,兩個消息不允許有相同的MessageID。
CorrelationID(關聯ID):該字段用于將消息連接在一起。該字段可以在請求中提供,因此客戶端可以關聯對應的應答消息。服務器段會將應答消息的CorrelationID設置為源消息的CorrelationID取值。
Comment(注釋):任何描述性的文字。
Property(性質):復合類型允許客戶以鍵/值對的方式擴展傳輸的信息,包含一個Name(名稱)和Value(取值)。
other(其他):其他的客戶擴展,由開發商自行定義擴展。
IEC 61968標準規范了一個動詞列表,Verb(動詞)只能為下表的取值。
表1 IEC 61968推薦動詞表
請求動詞 回復動詞 事件動詞 使用場景
Get Reply 無 查詢
Create Reply Created 事務
Change Reply Changed 事務
Cancel Reply Canceled 事務
Close Reply Closed 事務
Delete Reply Deleted 事務
Execute Reply Executed 事務
Request(請求動詞)的使用方法如下:
Get用于查詢消息名詞中指定類型的對象。
Create用于創建消息名詞中指定類型的對象。
Delete用于刪除對象,為了維持修訂歷史,有時目錄系統并不是真正刪除對象。
Close和Cancel用于與業務處理相關的動作,如關閉一個工作訂單或取消了控制請求。
Change用于更改對象,但需注意,當通過業務規則進行表示時會模棱兩可,尤其是在復雜數據集的情況下(復雜數據集一般具有N:1的關系)。
Execute用于使用操作集進行傳輸的復雜事務,可能包含一個以上的動詞。
每個Request(請求)都使用Reply(回復動詞)進行回復。Event(事件動詞)常常是請求的結果,一個Create可導致一個Created事件的產生。事件中使用的動詞為相應請求動詞的“過去式”。
消息頭的定義如圖1所示:
圖1 消息頭定義
3.2 消息請求結構
IEC 61968Request(消息請求)結構只用于請求消息中,用于存放請求消息的請求參數,請求結構中的元素都不是必須的,在實際應用中可以根據實際情況進行選用。消息請求結構包括的元素描述如下:
StartTime(起始時間):當一個請求需要起始時間作為過濾條件時使用。
EndTime(結束時間):當一個請求需要結束時間作為過濾條件時使用。
Option(配置):名值對方式,在查詢請求時可作為過濾條件,可用于規定超時時間或規范化響應模式等,在具體實現時作為自定義的擴展。
ID(標識):在查詢請求時,可以作為過濾條件標識一個或多個對象,可以在“close”、“delete”、“cancel”事務中標識特定的對象。每個ID都有一組屬性,“kind”用于說明標識的類型,如名稱、UUID、事務ID或其他類型,UUID默認采用對象的mRID屬性取值;如果取值為名稱,“idType”和“idAuthority”需要提供。
Other:其他的自定義擴展。
消息請求的定義如圖2所示:
圖2 消息請求定義
3.3 消息回復結構
Reply(消息回復)作為對其他消息的響應,包括的元素描述如下:
Result(結果):消息回復的結果,取值為以下之一:
OK:沒有錯誤,返回所有的結果,“Error”元素不需要。
PARTIAL:部分,返回部分結果,有一個或多個“Error”元素。
FAILED:錯誤,沒有返回結果,有一個或多個“Error”元素。
Error(錯誤):錯誤描述。
ID(標識):錯誤對象ID。
Other(其他):其他的自定義擴展。
OperationId(操作ID):操作ID,與請求的操作相同,用于描述是對哪個請求的回復。
消息回復的定義如圖3所示:
圖3 消息回復定義
Error元素描述處理的錯誤信息,其元素描述如下:
code(錯誤代碼):用來描述錯誤的類型。
level(嚴重級別):分為:INFORM(信息)、WARNING(警告的)、FATAL(嚴重的)、CATASTROPHIC(災難的)。
reason(錯誤原因):一般為人可讀的錯誤名。
detail(詳細信息):自由格式描述錯誤具體的信息。
xpath(出錯路徑):XPath表達式標識具體的出錯的XML元素,
stackTrace(異常堆棧):軟件產生的異常堆棧。
Location(異常位置):軟件產生異常的位置。
ID(事務ID):對應的事務ID。
relationID(關聯ID):出錯的關聯對象,用于描述兩個對象間的關聯出錯。
opertionId(操作ID):與請求的操作相同,用于描述是對哪個請求的回復。
3.4 消息有效內容結構
Payload(消息有效內容)可以看作是CIM模型的一個子集,通過定義包含在該消息中的IEC TC57 CIM模型的類和屬性實現。并不是所有的消息都需要有效內容,例如get,close,cancel,reply操作等只需要消息頭,有效內容可以為空。
有些類型的消息必須提供有效內容,如果帶有動詞create或change的請求消息,以及一些響應消息和一些事件消息。
有效內容一般包含遵循一個已定義了XSD[8]的XML文檔。
有些情況也會有例外,例如:一些XML有效內容沒有XML Schemas,如RDF文件或動態查詢結果,還可能是非XML格式,如CSV和PDF。
還有些情況,有效內容很大,必須進行壓縮,否則將浪費大量帶寬。為了適應多種格式選項,有效內容提供了以下的格式(圖4):
圖4 消息有效內容定義
在消息有效內容中,我們可以通過使用XML的“any”結構,來包含任何類型的XML文件。另外,它也提供了松耦合選項,也能使用由XSD定義的特殊復雜類型。
一些情況下可能需要zip格式、Base64+編碼的字符串,此時可在消息中使用“compressed”標簽。下列情況需要使用壓縮方式:
一個遵循XML Schema的有效內容,超出了預定義的大小(如,1MB)。這種情況很常見。
具有非XML格式的有效內容,如PDF,Excel表格,CSV文件,或二進制圖片。
使用XML格式但沒有XML Schema的有效內容,超出了預定義的大小(如,1MB)。如作為一個SQL XML查詢結果生成的動態XML。
當有效內容采用Base64編碼的壓縮方式時,它作為一個string存儲于compressed消息元素內。另外,為了支持二進制格式數據的高效傳輸,數據采用Base64編碼,但不壓縮。如果XML格式不能滿足性能的要求,可以對數據進行分類,通過壓縮方式來實現“高速”傳輸。
Format標簽可以用于標識特定的數據格式,比如XML、RDF、SVG、BINARY、PDF、DOC、CSV等。該標簽是可選字段,它一般只用于當有效內容的存儲使用compressed消息元素時。
4.Apache CXF
Apache CXF是一個開源的WebServices框架,大大簡化了WebServices的創建,并可以在多種傳輸協議上運行。采用CXF構建WebServices服務非常方便,通過CXF的工具將WSDL生成為相應的JAVA編碼后,只需要編寫少量代碼就可以實現WebServices服務的調用和發布。作為WebServices客戶端,對其他WebServices服務進行調用時,相應的主要代碼如下:首先構建代理工廠JaxWsProxyFactoryBean對象,設置要調用的服務類型Operations和服務地址,創建相應的客戶端對象client,構建相應的參數,調用相應的服務方法。作為WebServices服務端,對外提供WebServices服務供其他客戶端調用時,相應的主要代碼如下:首先要實現對應的WebServices接口方法,通過Endpoint.publish,設置發布的地址和實現的對象即可。
5.CXF攔截器
通過Apache CXF實現WebServices的服務調用和服務發布非常簡單,這些作用客戶端應用進行服務調用和實現WebServices服務器發布很有用,但作為測試來講,只能看到高層的JAVA對象是不夠的,必須能夠查看底層的消息并可以對消息進行隨意的編輯才能實現測試的目的,這可以通過CXF的攔截器來實現。
CXF的攔截器是CXF功能最主要的擴展點。通過自定義的攔截器,可以改變請求和響應的一些消息處理,其中最基本的原理還是一個動態代理。當服務被調用時,一個攔截器鏈表被創建并調用。每一個攔截器都有機會做他們想要處理的消息,包括:讀取,轉化,處理頭部,驗證消息,等。攔截器可以用于CXF的客戶端和服務端。當一個CXF客戶端調用一個CXF服務端的時候,客戶端有一個傳出(Out)的攔截器鏈,服務端有一個傳入(In)的攔截器鏈。當服務端發送響應給客戶端時,服務端有一個傳出(Out)的攔截器鏈,客戶端有一個傳入(In)的攔截器鏈。此外,在調用出錯的情況下,一個CXF服務將創建單獨的對外輸出錯誤處理鏈,客戶端將創建一個傳入(In)的錯誤處理鏈。
創建代理工廠后分別向攔截器鏈表中添加相應的攔截器,其中MessageInInterceptor和MessageOutInterceptor分別對應客戶端的傳入攔截器和傳出攔截器。發布服務器后分別向攔截器鏈表中添加相應的攔截器,其中MessageInInterceptor和MessageOutInterceptor分別對應服務端的傳入攔截器和傳出攔截器。代碼的主要思想是將原始的消息內容XML展示出來,對其進行修改后,將修改后的內容放到消息流中,替換原來的消息內容,在發送消息時發送的就是修改后的消息內容。測試軟件的界面如圖5所示:
圖5 測試軟件界面
6.結束語
測試工具的開發平臺是Eclipse 3.6.2,采用Eclipse RCP技術開發圖形化界面,使用JAVA開發語言。這種針對IEC 61968WebServices標準接口測試方法,可針對不同的應用場景修改相應的測試消息內容,具有很好的通用性,測試效率高。此種測試方法沒有考慮IEC 61868 對Payload定義XSD限制的情況,未對Payload的內容進一步的處理,可在此基礎上對其進行改進以適應更廣泛的測試要求。
參考文獻
[1]IEC 61970-301 Energy management system application program interface(EMS-API):Part 301 Common Information Model(CIM)Base[S].2004.
[2]IEC 61970-401 Energy management system application program interface(EMS-API):Part 401 Component interface specification(CIS)f ramework[S].2005.
[3]OMG.CORBA/IIOP2.3 Specification[S].1998.
[4]IEC 61968-1 Application integration at electric utilities-System interfaces for distribution management-Part 1:Interface architecture and general requirements[C].2003.
[5]CXF,http://cxf.apache.org.
[6]W3C.Extensible Markup Language(XML)1.0(Fifth Edition).2008.
[7]W3C.Web Services Description Language(WSDL)1.1.2001.
[8]W3C.XML Schema Part 0:Primer Second Edition.2004.