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