Globus toolkit3.0
?
本文通過樣本代碼分三個部分來介紹 Globus 軟件體系結構和編程模型:
1.??????? 該工具箱的高級體系結構
2.??????? 編程模型和工具
3.??????? 通過使用自頂向下設計方法從 Web 服務描述語言(Web Services Description Language,WSDL)開始創建簡單的“股票報價(Stock Quote)”網格服務。
?
|
?
GT3 軟件體系結構模型
要討論 Globus 工具箱中使用的軟件框架,先要了解一下服務器端框架組件。
服務器端框架
圖 1用圖示說明了服務器端的組件。
圖 1. GT3 軟件框架:服務器端體系結構組件
|
如 圖 1所示,服務器端框架的主要體系結構組件包括:
- Web 服務引擎。該引擎由 Apache AXIS 框架軟件提供,用于處理一般的 Web 服務行為、SOAP 消息處理、JAX-RPC 處理程序處理和 Web 服務配置。
- Globus 容器框架。GT3 提供了一個容器,它通過唯一的實例句柄、實例資源庫和生命周期管理(包括服務激活/鈍化和軟狀態管理)來管理有狀態的 Web 服務。
|
目前,GT3 將 Apache AXIS 用作其 Web 服務引擎,Apache AXIS 在 J2EE Web 容器中運行并提供 SOAP 消息偵聽器(AXIS servlet)。它負責 SOAP 請求/響應序列化和反序列化、JAX-RPC 處理程序調用和網格服務配置。如 圖 1 所示,GT3 容器向 AXIS 框架提供樞軸(pivot)處理程序來將請求消息傳遞給 Globus 容器。
這個容器體系結構用于管理 Web 服務的狀態性質以及這些服務的生命周期(回想一下,網格服務實例是有狀態的 Web 服務)。一旦服務工廠創建了網格服務實例,框架就為該實例創建唯一的網格服務句柄(GSH),然后向容器資源庫注冊該實例。該資源庫擁有所有有狀態的服務實例,由其它框架組件和處理程序與之連接來執行以下服務:
- 標識服務和調用方法
- 獲取/設置服務特性(如實例 GSH 和 GSR)
- 激活/鈍化服務
- 解析網格服務句柄以引用服務并持久存儲它
客戶機端框架
圖 2用圖示說明了客戶機端的組件。
下一節中的編程模型也參考該圖。
如 圖 2所示,Globus 使用標準的 JAX-RPC 客戶機端編程模型和 AXIS 客戶機端框架網格服務客戶機。除了標準的 JAX-RPC 編程模型外,Globus 還在客戶機端上提供許多助手類,以隱藏 OGSI 客戶機端編程模型的細節。本文的編程模型一節將討論這些助手類。
?
|
?
GT3 軟件編程模型
該模型包含了在 GT3 中引入的服務器端和客戶機端編程概念。
根據當前的 GT3 編程模型,服務實現了 WSDL 中為該服務定義的所有 portType。例如,如果“股票報價”服務支持由 OGSI 定義的 StockQuote portType 以及 NotificationSource portType 和 GridService portType,那么該服務實現必須實現所有這些 portType(請參閱 清單 1)。
清單 1. 服務實現該服務所需的所有 portType
| ? ? \** This is sample code **\ public class StockQuoteService implements StockPortType, ????????????????????????????? GridServicePortType, NotificationSourcePortType{ } |
?
您可以通過委派模型(如下一節中所示)實現 portType 功能,以提供可插入性和可擴展性。下一節還將討論在 GT3 中提供的用來實現 OGSI 行為的缺省框架類。
?
|
?
服務器端、基于委派的編程模型
GT3 基于委派的模型有助于為多個接口(portType)繼承定義實現模型并有助于支持更容易的代碼生成工具。這些委派框架作為服務創建/后創建(postCreate)操作的一部分創建,服務實現必要的 portType。服務負責將方法調用委派給相應的代表。這種靈活性有助于插入新的委派框架實現來獲得不同質量的服務需求。
例如,您可以開發一個可伸縮的基于發布-訂閱的通知系統,以代替缺省 GT3 框架提供的點對點通知框架。 圖 3 顯示了它的這種用法。
如 圖 3 所示,您可以繼承 ServiceSkeleton 實現(它提供缺省的網格服務行為),以通過插件通知委派框架來支持通知行為。另外,StockService 實現了 StockPortType,并通過繼承 GT3 中提供的 NotificationServiceSkeleton 實現類實現了 NotificationSourcePortType。
通常情況下,委派框架是在對服務實現執行創建/后創建調用期間創建的。如 清單 2 所示,通知服務框架類在 postCreate () 調用中創建了通知委派機制。
清單 2. 通知委派框架的創建
| ? ? \** This is sample code **\ public void preCreate(ServiceProperties properties) throws ?????????????????????????????????????????????? GridServiceException { ????????? super.preCreate(properties); ????????? // creates the notification delegation skeleton ????????? this.notificationSkeleton = new ?????????????? NotificationSourceDelegationSkeleton(this); ????????? //set this as the default notification engine ????????? setNotificationEngine(this.notificationSkeleton); } |
?
缺省情況下,該服務實現由委派框架定義的 portType,并轉發對實際委派提供程序的調用。 清單 3演示了如何在通知源“subscribe”調用中實現 portType。
清單 3. 如何將方法委派從服務移到委派程序
| ? ? \** This is sample code **\ public ServiceLocatorType ???? subscribe(NotificationSourceSubscriptionType ??????????????????????? notificationSourceSubscription) ????????????????? throws RemoteException, GridServiceFault { ???? return getNotificationEngine().subscribe ???????????????????????? (notificationSourceSubscription); } ? |
?
GT3 提供的服務器端缺省實現類
作為服務器端框架的一部分,GT3 為網格服務行為(如服務、通知和持久存儲框架)提供了許多缺省實現類。 圖 4用圖示說明了這些組件。
圖 4 演示了工廠實現的類層次結構及其與 portType 的關系。GT3 核心通過 ServiceSkeleton 類為網格服務 portType 提供缺省實現,該類形成所有網格服務的基礎類。通常,高級開發人員可以始終通過繼承或替換缺省 ServiceSkeleton 類來插入他們的缺省實現。
GT3 服務數據管理類
服務數據是在 OGSI 規范中引入的核心概念之一,它們用來聲明服務的狀態,并可以通過已知的接口(findServiceData ?setServiceData)來訪問這些狀態,而這些接口被聲明為 GridService portType 的一部分。Globus GT3 提供了一組豐富的功能來處理服務數據概念。
圖 4 還顯示了每個服務包含一個服務數據集,該數據集擁有服務數據對象。服務數據對象是服務數據值的 Java 包裝器類。這些包裝器包含服務數據的值,或者使用所提供的回調方法來獲取值。該類提供了將值轉換成 XML DOM 元素的機制(具體化方法),這對于 Query 執行程序很有用。
清單 4 顯示了如何構造一個服務數據對象,然后向服務數據集注冊它。該示例演示了如何為股票報價網格服務創建服務數據,并通過實現 ServiceDataValueCallback 接口來注冊服務數據回調方法。(下面將更詳細地討論該示例。)
清單 4. 創建服務數據以實現服務數據值回調
| ? ? \** This is sample code **\ public class StockQuoteService extends NotificationServiceSkeleton ????????????????????????????? implements StockPortType, ServiceDataValueCallback { ???????? ServiceData stockData = null; ??? StockDataElementType stockElement = null; ? ???????? public void postCreate(GridContext messageContext) throws ??????????????????????????? GridServiceException { ??????? super.postCreate(messageContext); ??????? try { ??? ??// create a service data object with a unique name ????????? stockData = this.serviceData.create("StockServiceData"); ????? ??????????????? // registering a call back ??????????????? stockData.setCallback(this); ? ????????? stockElement = new StockDataElementType(); ????????? StockDataType stockServiceData = new StockDataType(); ????? ??????????????? stockElement.setStockData(stockServiceData); ????????? stockData.setValue(stockElement); ? ????????? // add this service data object to the service data set ??????????????? this.serviceData.add(stockData); ?????? } catch (Exception e) { ?????? } ?? } ??? ? ?? // This is the service data call back method ?? public Object[] getServiceDataValues(QName qname) { ?????? Object[] ret = super.getServiceDataValues(qname); ????????? try { ?????????????? if (QNameUtils.equalsLocally(qname, stockData.getName())) { ???????????? StockDataType stockServiceData = stockElement.getStockData(); ???????????? stockServiceData.setSymbol("ibm"); ??????? ?????stockServiceData.setQuote("93.33"); ???????????? // return the changed service values ????????????? return new Object[]{stockServiceData}; ???????????? } ??????? } catch (Exception e) { ??????? } ??????? return ret; ???? } } ? |
?
現在,客戶機可以使用 findServiceData("StockServiceData") 調用來獲取服務在運行時創建的服務數據。
?
|
?
客戶機端編程模型
GT3 未在客戶機端引入任何新的編程模型,而是使用了由 JAX-RPC 和 .NET 驅動的 Web 服務編程模型。GT3 為客戶機端開發人員提供了許多助手類來處理 OGSI 行為,如網格服務句柄(GSH)、網格服務引用(GSR)和開放內容可擴展性模型。句柄解析(GSH 解析)和 GSR 解引用可以使用幫助程序來指出正確的服務實例。
由該工具箱使用的 Java 編程模型概念和 GT3 助手類提供了以下各項:
1.??????? 基于 JAX-RPC 的編程模型包括:
o??????? 基于代理的靜態客戶機。 注:工具 GWSDL2Java 或 WSDL2Java 創建了這些代理和助手類(定位器)。
o??????? 動態的、基于代理的存根
o??????? 動態調用接口(Dynamic Invocation Interface,DII)。 注:JAX-RPC 規范(請參閱 參考資料)包含了有關該編程模型的更詳細信息。
2.??????? GT3 提供了定位器類。
圖 5用圖示說明了定位器類。
圖 5演示了客戶機使用網格服務定位器類的情況。該定位器類使用 GSR 或 HandleHelper 助手類來解析端點綁定。該定位器類為 getPortType() 操作提供下列參數之一:
- 傳遞指向服務實例的 URL 端點地址。該功能與標準的 JAX-RPC 定位器類的功能相似。
- 傳遞網格服務句柄(GSH)以獲取網格服務引用(GSR)。
- 傳遞服務終止引用,它是使用工廠的 createService 調用檢索的。
|
下一節將介紹 GT3 中的常用工具。
?
|
?
用于創建客戶機端和服務器端構件的 GT3 工具
本節討論三個工具:GSDL2Java、GenerateBinding 和 GWSDL2Java。
GSDL2Java
GSDL2Java 是 AXIS 提供的 WSDL2Java 工具的特例實現。客戶機使用該工具來生成存根、綁定、服務接口、服務器端服務實現框架和客戶機定位器類。還可以針對 WSDL 文件使用該工具來完成自頂向下的設計模型。
GenerateBinding
WSDL 文件可分成抽象 portType 表示和具體綁定表示。通常,客戶機不需要關心具體綁定的生成。GT3 提供該工具為給定的 portType 生成必要的綁定信息。該工具使用的缺省值是“http”(作為傳輸綁定協議)、“document”(作為 SOAP 消息樣式)和“literal”(作為編碼方法)。這種靈活性有助于客戶機設計 portType 定義,然后使用該工具來生成必要的綁定。
GWSDL2Java
GWSDL2Java 是一種需要詳細討論的有趣工具。如前一篇文章(請參閱 參考資料)中所討論的那樣,OGSI 允許對 portType 使用多重 portType 繼承和開放內容模型。WSDL 1.1 中沒有這種靈活性。因此,開發人員可以使用 OGSI 規范提供的 GWSDL 新的名稱空間和 GWSDL portType 來創建這一多重繼承和 portType 可擴展性模型。
當 WSDL 1.2 成為標準時,框架和工具將支持這一特性。然而,為了支持當前的 WSDL1.1 工具和框架,必須將多個 OGSI GWSDL portType 轉換成基于 WSDL 1.1 的單個 portType 模型。這個工具用于將 GWSDL portType 定義轉換成相應的 WSDL 1.1 定義。 圖 6說明了這一轉換。
圖 6演示了通過使用 GWSDL2Java 工具如何將 GWSDL(通過具有多重繼承的 TopPortType portType 來標識)轉換成 WSDL 1.1 的單個 TopPortType portType 模型。
|
作為一名開發人員,您應該知道這種轉換的幾個重要方面:
- 新的 WSDL 端口類型被構造成包含 GWSDL 端口類型所具有的相同的操作,并包含擴展端口類型的所有操作。
- 所有操作消息都要用最初定義的名稱空間定義進行限定,這樣才不可能發生操作重載。
- 新 WSDL portType 的名稱與舊的 GWSDL portType 的名稱相同。
- 轉換將舊的 GWSDL portType 保持為可擴展性元素,但不包含任何操作(可能只有服務數據)。
下一節討論 GT3 軟件所需的部署和配置。
?
|
?
部署配置
為網格服務和為 AXIS Web 服務提供的部署選項是相同的。AXIS 提供了兩個特定于 Web 服務的部署描述符 server-config.wsdd 和 client-config.wsdd。這些部署描述符基于 Web 服務部署描述符(Web Services Deployment Descriptor,WSDD)模式。
下一節討論網格服務所需的基本部署信息。
?
|
?
部署和配置信息
GT3 使用 AXIS WSDD 來配置 JAX-RPC 處理程序及這些處理程序所需的靜態參數。通過設置服務名稱、消息處理樣式、樞軸處理程序、工廠和服務實例 Java 類信息來部署服務。服務注冊靜態類型映射信息,該信息是可選的,因為框架在運行時標識類型映射。
我們稍后將創建的樣本股票報價網格服務說明了這種部署。部署代碼如 清單 5所示,表 1 顯示了所使用的參數的詳細信息。
清單 5. StockQuote 網格服務的基本部署配置
| ? ? \** This is sample code **\ <service name="samples/stock/StockFactoryService" ?????????????????????????????????????????? provider="Handler" style="wrapped" > ???????? <parameter name="className" ????????????? ????????value="org.globus.ogsa.impl.samples.stock.StockFactoryImpl"/> ???????? <parameter name="persistent" value="true"/> ???????? <parameter name="schemaPath" ????????????????????? value="schema/core/factory/factory_service.wsdl"/> ???????? <parameter name="instanceSchemaPath" ????????????????????? value="schema/samples/stock/stock_service.wsdl"/> ???????????? <parameter name="handlerClass"????? ?????????????????????? value="org.globus.ogsa.handlers.RPCURIProvider“/> ???????? <parameter name="instanceLifecycle" value="persistent"/> ?</service> |
?
清單 5 顯示了該服務具有唯一的服務名稱(服務的遠程可訪問名稱)并使用“包裝的”消息樣式。它還顯示提供程序是一個處理程序。表 1 列出了這些參數。
表 1. 部署和配置參數
| 參數 | 描述 |
| className | 該類實現如股票報價工廠服務之類的服務。 |
| persistent | 如果該屬性值為真,那么它表示網格服務,該服務在容器啟動時啟動。 |
| schemaPath | 指向工廠的 WSDL 模式。 |
| instanceSchemaPath | 如果服務是由工廠創建的,那么它指向該服務的 WSDL 模式。 |
| handlerClass | 該處理程序指定在服務器端使用的分派器。AXIS 引擎分派對該分派器(樞軸處理程序)的調用。 |
| instanceClass | 要動態創建服務的服務類名。由 DynamicFactoryImpl 使用。該示例中未使用它是因為我們的服務是通過自己的工廠創建的。 |
| instanceLifecycle | 如果該特性為真,那么實例被保存到 WSDD 文件。 |
在介紹了大多數核心體系結構和編程細節之后,下一節將討論編程細節。
?
|
?
使用自頂向下方法的網格服務實現樣本
清單 6 通過使用自頂向下的設計方法來創建一個簡單的股票報價網格服務。它顯示了具有一個名為“getQuote”方法的 WSDL 文件的 StockQuote portType 定義,為了清晰起見,我刪除了一些內容。
清單 6. StockQuote 服務 portType WSDL 文件
| ? ? \** This is sample code **\ <definitions > <types> <xsd:schema > ????? <xsd:complexType name="SymbolType"> ???????? <xsd:sequence> ???????????? <xsd:element name="symbol" type="xsd:string"/> ???????? </xsd:sequence> ??? </xsd:complexType> ??? <xsd:complexType name="QuoteType"> ? ???????? <xsd:sequence> ???????????? <xsd:element name="quote" type="xsd:float"/> ???????? </xsd:sequence> ??? </xsd:complexType> ??? <xsd:element name="getQuote" type="tns:SymbolType"/> ??? <xsd:element name="getQuoteResponse" type="tns:QuoteType"/> ??? ??? <xsd:complexType name="StockDataElementType"> ????? <xsd:sequence> ??????? <xsd:element name="stockData" type="tns:StockDataType"/> ????? </xsd:sequence> ??? </xsd:complexType> ??? <xsd:complexType name="StockDataType"> ????? <xsd:sequence> ???????? <xsd:element name="symbol" type="xsd:string"/> ???????? <xsd:element name="quote" type="xsd:float"/> ????? </xsd:sequence> ??? </xsd:complexType> ? </xsd:schema> </types> ? <message name="SymbolMessage"> ?? <part name="parameter" element="tns:getQuote"/> </message> <message name="QuoteMessage"> ?? <part name="parameter" element="tns:getQuoteResponse"/> </message> ? <portType name="StockPortType"> ??? <operation name="getQuote"> ?????? <input message="tns:SymbolMessage"/> ?????? <output message="tns:QuoteMessage"/> ??? </operation> </portType> ? <gsdl:serviceDataDescription name="StockDataElement" ???????????????????????????? <element="tns:StockDataType" ???????????????????????????? <minOccurs="1" ???????????????????????????? <maxOccurs="unbounded" ???????????????????????????? <mutability="mutable"> ?? <documentation>Service Data about stock (symbol and price).<documentation> ?? </gsdl:serviceDataDescription> ? |
?
上面的代碼通過使用文檔/文字方法來構建網格服務。請注意 message、part 和 types 的定義。現在,您可以運行 GT3 工具 GenerateBinding 來生成服務和綁定 WSDL 文件。一旦創建了服務和綁定 WSDL 文件,就可以運行 GWSDL2Java 工具來生成必要的 Java 代碼。該代碼生成“StockPortType”接口,如 清單 7所示。Java 遠程接口是它的基礎接口,所以它拋出 java.rmi.RemoteException。
清單 7. StockQuote 服務生成的 StockPortType portType 接口
| ? ? \** This is sample code **\ public interface StockPortType extends java.rmi.Remote { ?public float getQuote(java.lang.String symbol) throws java.rmi.RemoteException; } |
?
一旦有了 StockPortType 接口,就可以通過實現這一接口來實現服務器端網格服務股票報價服務。下面 清單 8 中的樣本代碼演示了如何做到這一點。對于缺省網格服務行為,使用 ServiceSkeleton 類。
清單 8. StockQuote 服務實現
| ? ? \** This is sample code **\ public class StockQuoteService extends ServiceSkeleton ????????????????? implements StockPortType{ ??? public StockQuoteService() { ??????? super("Sample Stock Service"); ??? } ? public void postCreate(GridContext messageContext) throws GridServiceException { -- ?? } ??? public float getQuote (String symbol) throws ????????? java.rmi.RemoteException { ??? -- ??? } } |
?
接下來,創建網格服務工廠類,它又將創建股票服務,如 清單 9所示。
清單 9. 股票報價工廠實現
| ? ? \** This is sample code **\ public class StockFactoryImpl extends FactoryServiceSkeleton { ??? public StockFactoryImpl() { ??????? super("Sample Stock Service (Gateway to Live Service)"); ??? } ??? public Object createServiceObject(CreationType creation) { ? return new StockQuoteService(); ??? } } ? |
?
正如您所看到的那樣,股票報價服務實例創建在 createServiceObject(..) 方法調用中發生。
現在,我們已經準備好了可以部署到 AXIS 框架中的股票網格服務。為此,我們需要將部署信息添加到 server-config.wsdd 文件,如前面在部署和配置一節中描述的那樣。一旦準備好了配置,就可以用 GT3 啟動 J2EE/J2SE 容器,并且 AXIS Servlet 將等待來自客戶機的 SOAP 消息請求,如 圖 7所示。
圖 7演示了通過兩個不同的步驟創建并使用股票客戶機。
步驟 1:使用股票工廠服務客戶機創建 StockService,如 清單 10所示。
清單 10. 使用工廠定位器創建網格服務
| ? ? \** This is sample code **\ FactoryServiceGridLocator factoryService = new ?? ???????????????????FactoryServiceGridLocator(); FactoryPortType factory = factoryService.getFactoryPort(new ???????????????????? HandleType(handle)); CreationType creation = new CreationType(); ServiceTerminationReferencesType refType= ????????????????? ??factory.createService(creation); ServiceLocatorType locator = refType.getReferences(); ExtensibilityType gsr = locator.getReferences()[0]; String locationURL = null; if (gsr != null) { ??????? locationURL = AnyHelper.getAnyAsString(gsr); } else { ?????? locationURL = locator.getHandle().getValue(); } |
?
清單 10 演示了如何獲得通過工廠創建的股票服務的網格服務句柄(GSH)。該 GSH 唯一地標識由工廠創建的股票服務。
步驟 2:現在使用步驟 1 中返回的 GSH 來對股票報價服務實例調用 getStock() 方法,如 清單 11所示。
清單 11. 調用網格服務上用 GSH 標識的方法
| ? ? \** This is sample code **\ StockDefinitionServiceLocator stockService = ????????????????????????????? new StockDefinitionServiceLocator(); StockPortType stock = stockService.getStockDefinitionPort(new URL(locationURL)); ? float quote = stock.getQuote(symbol); ? |
?
更高級的客戶機可以使用 findservicedata() 調用來獲得與網格服務實例相關聯的服務數據。 清單 12 演示了如何編寫 findserviceData 操作來處理 ExtensibilityType 以及如何使用 GT3 提供的 AnyHelper 類來處理 xsd:any。
清單 12. 如何對用 GSH 標識的網格服務使用 findserviceData() 操作
| ? ? \** This is sample code **\ GridServiceLocator gridService = new GridServiceLocator(); GridServicePortType grid = gridService.getGridServicePort(new ????????????????????????????????? URL(url)); ExtensibilityType query = QueryHelper.getNameQuery("StockServiceData"); ExtensibilityType result = grid.findServiceData(query); ? Element element = AnyHelper.getAnyAsElement(result); ????????????????????????????????? "or" ServiceDataType data = (ServiceDataType)AnyHelper.getAny(result); StockDataType value = (StockDataType)AnyHelper.getSingleAny(data); |
?
至此,我們已經討論了有關 GT3 的大多數基本概念。
?
總結
以上是生活随笔為你收集整理的Globus toolkit3.0的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库分页存储过程(4)
- 下一篇: AJAX开发简略 (转)