• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 181, 文章 - 2, 評論 - 85, 引用 - 0
            數據加載中……

            IBM WebSphere 開發者技術期刊: 使用 Rational Application Developer 和 WebSphere Application Server 來加速基于 XML 的 SOA 的 JSF 開發——第 4 部分

            本文是此系列文章的第 4 部分,該系列提出了加快基于 XML 的面向服務體系結構(Service Oriented Architecture,SOA)應用程序表示開發的解決方案。本文重點集中于利用 IBM ? Rational? Application Developer V6 和 IBM Websphere ? Portal 開發 portlet。Portlet 用個人化的、管理的、再次使用的內容提供了強大的呈現方式。本文通過分析預構建的保險 portlet 應用程序范例,描述了將 portlet 和 數據(在 portlet 內及 portlet 間共享)結合服務數據對象(Service Data Object)使用時的配置和架構細節。

            引言

            這個包含五部分的系列文章提出了加快基于 XML 的 SOA 應用程序表示開發的解決方案。在該系列文獻的:

            • 第 1 部分 中,我們經歷了通過使用所提供的插件集來向每個指定的 XML schema 中的服務傳遞信息的簡單 JavaServer? Faces (JSF) 應用程序的整個開發過程。
            • 第 2 部分 中,我們增強了在 第 1 部分 中開發的解決方案,使之包括創建、更新和刪除功能,包括用本地附加的變量及基本的轉換來自定義生成 Service Data Objects(SDO)。
            • 第 3 部分 中,突出了在構建基于 XML 的 SOA 應用程序時用于處理 SDO 實例的不同技術。
            • 在第 4 部分中,我們將集中在基于 XML 的 SOA 應用程序的 portlet 的開發上,會利用到貫穿于此系列的樣本保險應用程序場景。

            Portlet 提供了強大的管理和配置內容傳遞方式。它們能被開發為可再次使用、封裝的表示組件,該組件可以基于終端用戶需求進行自定義的。應用程序服務器提供者能為他們的消費者傳遞這些能再次使用的資產。然后,在管理服務器環境中,消費者根據他們自己的需求自定義、個人化并配置這些資產。為提供這些可配置的資產,服務器組件需要與這些 portlet 的內容之間松耦合。

            出現在本系列前三部分的相同體系結構非常適合 portlet 表示開發,并且說明了該體系結構能利用多種類型的呈現機制。本文將解決當利用 portlet 結合 SDO 使用時所涉及到的配置和架構問題。

            本文并不打算講解 portlet 的開發,在 參考資料中使用產品文檔或其它在線資源時可以解決此問題。本文主要解決了對基于 XML 的 SOA 使用 SDO 時,與 portlet 開發相關的問題。同時,它也勾勒了創建 portlet 的基礎,以及如何共享構件、portlet 項目類型、portlet 狀態和 portlet 之間的數據,它們是構建 SDO 驅動的 portlet 的一些基本需求。

            在接下的文章中,您將需要 IBM Rational Application Developer V6 (以下引用時為 Application Developer)和 IBM WebSphere Portal,Version 5.1 或更新版本。本文假定讀者熟悉 Rational Application Developer 的 JSF 頁面設計器。







            安裝 XSD SDO 轉換功能

            為了安裝 XSD SDO 的轉換功能,請按照第 1 部分中的詳細步驟操作。







            XSD SDO 轉換功能的內容

            XSD SDO 轉換功能包括用于從 XSD schema 中生成 SDO 包的構件,以及用于將 SDO 包實例轉換到 XML 實例文件中或從 XML 實例文件中轉換出 SDO 包實例的框架組件:

            1. 創建 SDO 包的動作
              在 XSD 資源中的這個動作從 XSD schema 中生成了 SDO 包(如圖 1 所示)。
              圖 1. 創建 SDO 包
              Create SDO Package
            2. XMLTransformServiceFactory.java
              該類提供了 API 用于將 SDO 包實例轉換到 XML 實例文件中或從 XML 實例文件中轉換出 SDO 包實例。







            場景

            本文中我們將用到的場景是在第 1 部分第 2 部分中開發的保險應用程序。在該場景中:

            • 我們假設 XYZ 保險公司有許多已注冊的代理人。
            • 每個代理人都有許多客戶,并且每個客戶都同代理人簽訂了許多策略。
            • 保險公司通過標準的 BrokerService 方案來展示代理人的服務(清單 1,圖 2),以及作為 validCodesService 模式的有效的代碼服務(清單 2,圖 3),它能檢索有效值。
            • 任何來源于代理人的通信都是符合模式定義的 XML 請求或響應。


            清單 1. BrokerService.xsd
            												
            																		
            <?xml version="1.0" encoding="UTF-8"?>
            <xsd:schema xmlns="http:///xyz.brokerservice.ecore"
            		xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            		elementFormDefault="qualified"
            		targetNamespace="http:///xyz.brokerservice.ecore">
            	<xsd:annotation>
            		<xsd:documentation xml:lang="en">
               			Broker Service Schema for xyz.com.
               			Copyright 2004 ibm.com. All rights reserved.
              		</xsd:documentation>
            	</xsd:annotation>
            	<xsd:element name="brokerService" type="brokerServiceType"/>
            	<xsd:complexType name="brokerServiceType">
            		<xsd:sequence>
            			<xsd:element minOccurs="0" name="broker" type="brokerType"/>
            			<xsd:element minOccurs="0" name="error" type="errorType"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	<xsd:complexType name="brokerType">
            		<xsd:sequence>
            			<xsd:element minOccurs="0" ref="firstName"/>
            			<xsd:element minOccurs="0" ref="lastName"/>
            			<xsd:element minOccurs="0" name="loginName" type="xsd:string"/>
            			<xsd:element minOccurs="0" name="loginPassword" type="xsd:string"/>
            			<xsd:element maxOccurs="unbounded" minOccurs="0" name="client" type="clientType"/>
            		</xsd:sequence>
            		<xsd:attribute name="brokerId" type="xsd:string" use="required"/>
            	</xsd:complexType>
            	<xsd:complexType name="clientType">
            		<xsd:sequence>
            			<xsd:element minOccurs="0" ref="firstName"/>
            			<xsd:element minOccurs="0" ref="lastName"/>
            			<xsd:element minOccurs="0" 
            					name="dateOfBirth" type="xsd:date"/>
            			<xsd:element minOccurs="0"
            					 name="currentAddress" type="addressType"/>
            			<xsd:element minOccurs="0"
            					 name="permanentAddress" type="addressType"/>
            			<xsd:element maxOccurs="unbounded" 
            					minOccurs="0" name="policy" type="policyType"/>
            			<xsd:element minOccurs="0" name="ssn"/>
            		</xsd:sequence>
            		<xsd:attribute name="clientId" 
            				type="xsd:string" use="required"/>
            		<xsd:attribute name="securityToken"
            			 type="xsd:string" use="optional"/>
            	</xsd:complexType>
            	<xsd:complexType name="addressType">
            		<xsd:sequence>
            			<xsd:element name="street" type="xsd:string"/>
            			<xsd:element name="city" type="xsd:string"/>
            			<xsd:element name="state" type="xsd:string"/>
            			<xsd:element name="zip" type="xsd:string"/>
            			<xsd:element name="country" type="xsd:string"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	<xsd:complexType name="policyType">
            		<xsd:sequence>
            			<xsd:element name="policyName" type="xsd:string"/>
            			<xsd:element name="policyStartDate" type="xsd:date"/>
            			<xsd:element name="policyEndDate" type="xsd:date"/>
            			<xsd:element name="policyAmount" type="xsd:string"/>
            			<xsd:element name="policyDescription" type="xsd:string"/>
            		</xsd:sequence>
            		<xsd:attribute name="policyId" type="xsd:string" use="required"/>
            	</xsd:complexType>
            	<xsd:complexType name="errorType">
            		<xsd:sequence>
            			<xsd:element name="errorCode" type="xsd:string"/>
            			<xsd:element name="errorDescription" type="xsd:string"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	<xsd:element name="firstName" type="xsd:string"/>
            	<xsd:element name="lastName" type="xsd:string"/>
            </xsd:schema>
            
            												
            										


            圖 2. BrokerService 方案模型
            BrokerService Schema Model

            清單 2. ValidCodesService.xsd
            												
            																		
            <?xml version="1.0" encoding="UTF-8"?>
            <xsd:schema xmlns="http:///xyz.validcodesservice.ecore"
            		xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
            		elementFormDefault="qualified" 
            		targetNamespace="http:///xyz.validcodesservice.ecore">
            	<xsd:annotation>
            		<xsd:documentation xml:lang="en">
               			Valid Codes Service Schema for xyz.com.
               			Copyright 2004 ibm.com. All rights reserved.
              		</xsd:documentation>
            	</xsd:annotation>
            	<xsd:element name="validCodesService" type="validCodesServiceType"/>
            	<xsd:complexType name="validCodesServiceType">
            		<xsd:sequence>
            			<xsd:element minOccurs="0" 
            				name="stateList" type="stateListType"/>
            			<xsd:element minOccurs="0" 
            				name="policyCodeList" type="policyCodeListType"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	
            	<xsd:complexType name="stateListType">
            		<xsd:sequence>
            			<xsd:element maxOccurs="unbounded" minOccurs="0" 
            				name="state" type="stateType"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	
            		<xsd:complexType name="stateType">
            		<xsd:sequence>
            			<xsd:element name="shortName" type="xsd:string"/>
            			<xsd:element name="fullName" type="xsd:string"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	
            		<xsd:complexType name="policyCodeListType">
            		<xsd:sequence>
            			<xsd:element maxOccurs="unbounded" minOccurs="0" 
            				name="policyCode" type="policyCodeType"/>
            		</xsd:sequence>
            	</xsd:complexType>
            			<xsd:complexType name="policyCodeType">
            		<xsd:sequence>
            			<xsd:element name="shortName" type="xsd:string"/>
            			<xsd:element name="fullName" type="xsd:string"/>
            		</xsd:sequence>
            	</xsd:complexType>
            	
            </xsd:schema>
            
            												
            										


            圖 3. ValidCodes 服務方案模型
            ValidCodes Service Schema Model






            分析解決方案

            如同前面所提及的,portlet 表示比純的 JSF Web 應用程序更加復雜。我們分析了本文所提供的解決方案,它包含一些與終端服務松耦合內容的預構建的 portlet。所提供的解決方案是一個包含 portlet (之后會描述)的項目交換文件。我們將引入包含提供 portlet 的項目交換文件,并解決在開發解決方案中涉及到的關鍵問題:

            1. 解決方案的內容
            2. 創建 Portlet
            3. 創建 Portlet 視圖
            4. 導航鏈接
            5. Portlet 狀態
            6. 分頁
            7. Dropdown 綁定
            8. 在 portlet 視圖中傳遞數據
            9. 在 portlet 間共享數據
            10. 截取 portlet 動作
            11. 運行 XYZ 保險 portlet 項目 .

            1. 解決方案內容

            將項目交換 xsd_sdo_soa_xml_sample.zip 下載文件導入到 Application Developer 工作區中。結果,下列項目將導入進來(圖 4):

            1. XYZInsuranceEAR: 企業應用程序項目,它包括作為模塊或實用程序的所有其他項目。
            2. XYZInsurancePortlet: 用所有現有的 portlet 和 JSF JSR 的 JSR 168 portlet 項目。該項目的 WebContent 文件夾包括 BrokerService.xsd 和 ValidCodesService.xsdschema, 并且在 Schema 文件夾中含有樣本數據文件。為了簡單起見,本例中 SDO 包已經創建并且是門戶項目的一部分。
            3. XYZInsuranceService: 包含實現代理人服務和有效代碼服務的 Java 類。服務裝載并發送了與服務方法請求相對應的 XML 響應。提供此基本實現來模擬服務行為。它的實現超出了文章介紹的范圍。
            4. XYZInsuranceServiceProxy: 包括用于調用代理人服務的 ServiceProxy 的基本實現。


            圖 4. 導入的項目交換范例
            導入的項目交換范例

            在導入項目交換所需要的庫中,emf.jar 同 xsdsdotransform.jar 一起被加上。這提供了所需級別的 Eclipse Modeling Framework (EMF) 和 Service Data Object (EMF-SDO) 運行庫 (圖 5)。本文所需要的 XML-SDO 轉換插件運行時版本并沒有與 WebSphere Portal V5.0.2.x or V5.1 封裝在一起。 XSD SDO 轉換功能至少需要 EMF-SDO 的 2.1 版本。您將有必要手動將支持的 JAR 添加到針對這些 WebSphere Portal 版本的項目中。您可獲得所需的 JAR,它們可在Eclipse Modeling Framework Web 站點中下載,或者在 Websphere Application Server V6.0 運行時文件夾中使用 emf.jar 文件:

            • commonj.sdo.jar
            • common.resources.jar
            • common.jar
            • xsd.resources.jar
            • xsd.jar
            • ecore.jar
            • ecore.change.jar
            • ecore.xmi.jar


            圖 5. 添加 EMF-SDO 運行時
            EMF-SDO runtime addition

            導入的 Web 項目 XYZInsurancePortlet 是 Portlet JSR 168 項目。當創建一個項目應用程序時,必須選擇 portlet 項目的類型。Application Developer 對下列內容支持創建 portlet 項目:

            • IBM portlet API 作為 "Portlet Project"
            • JSR 168 portlet API 作為 "Portlet Project (JSR 168)"

            符合 JSR 168 規范的 portlet 可以部署到任何符合 JSR 168 的門戶,并為 portlet 應用程序提供可移植性,而不是限制在WebSphere Application Server 上。選擇一個應用服務提供者來將相同的應用程序部署到多個客戶端時,跨平臺需求可能是一個關鍵的因素。

            Application Developer 支持基于 JSR 168 規范的 Faces portlet 開發。Snippets 支持普通任務,象編碼名稱空間、改變窗口模式、行最小化和最大化等等。然而,在 JSR 168 中不支持 click-to-action 合作行為和 portlet 消息。

            對于新的 portlet,當支持項目類型的功能足以滿足 portlet 的需求時,或者當 portlet 期望作為 Remote Portlets (WSRP)服務的 Web 服務公布時,考慮使用 JSR 168 portlet。 JSR 168 portlet API 的一些通用標記(例如,<namespace> 和 <actionURL>)不能用在 JSR 168 項目中的 Faces portlet JSP 文件中(當創建這些項目時請參考 Application Developer 幫助,以便了解這些項目類型間的區別)。

            Application Developer 可支持 WebSphere Portal V5.0.2.x (僅僅是 Windows?) 和 WebSphere Portal V5.1 的單元測試環境。

            導入的項目包括共享 JSF JSP 的多個 portlet, 并對 portlet 通信使用 property 代理。以下羅列的是對 portlet 的描述和它們相關的視圖。

            樣本 portlet 視圖(作為 JSF JSP )

            • BrokerSummary: 發送代理人概要請求(brokerSummaryRequest.xml),并接收包含代理人客戶和他們的策略(brokerSummaryResponse.xml)的響應。XML 響應在會話管理頁面 root wrapper bean (BrokerDetailRoot),它用來在頁面的控制面板中提供數據。
            • BrokerSummaryNew: 同 BrokerSummary 相似,當添加新的策略時展示出來。
            • BrokerDetail:發送代理人詳細請求(brokerDetailRequest.xml),并接收包含所有代理人客戶和他們的策略(brokerDetailResponse.xml)的響應。XML 響應在會話管理頁面 root wrapper bean (BrokerDetailRoot),它用來在頁面的控制面板中提供數據。
            • AddPolicy: 通過發送請求能為現存客戶添加新的策略,并且為請求變化的成功或失敗接收 XML 響應(addPolicyResponse.xml)。The XML responses are processed in a page root wrapper bean (AddPolicyRoot) that is used to process the updates along with the session managed page root wrapper bean (BrokerDetailRoot)。
            • SearchPolicy: 在下拉菜單中選擇最大的策略數量,該菜單用 validCodesService 中的靜態清單值和動態清單狀態 populated。此視圖展示了靜態和動態清單驅動下拉控制的使用。所選的值被傳遞到 SearchPolicyResult 頁面。
            • SearchPolicyResult: 對基于最大數量參數(policySearchRequest.xml)的策略查找發送請求,并用匹配策略(policySearchResult.xml)接收響應。響應在頁面根 bean 包裝器(SearchPolicyResultRoot)中運行,它運行(policySearchResult.xml)和提供結果。
            • BrokerSummaryHelp: 對 BrokerSummary portlet 提供幫助。

            樣本 portlet

            • BrokerSummaryPortlet: 主要的視圖是 BrokerSummary。通過調用服務,更新命令來更新內容。
            • BrokerDetailPortlet: 主要視圖是 BrokerDetail ,并且與 AddPolicy 鏈接。當添加一個新的策略時,BrokerSummaryPortlet 被通知更新有變化的概要內容,并且展示 BrokerSummaryNew 視圖。利用財產代理人作為 AddPolicyDataMessage,多個數據傳遞到 portlet。
            • SearchPolicyPortlet: 主要的視圖是 SearchPolicy,并且與 SearchPolicyResult 鏈接。

            2.創建 Portlet

            創建新的 JSR 168 portlet:

            1. 在 Application Developer 中,打開 New Portlet 對話框(圖 6)。
            2. 選擇 portlet Project 名稱,XYZInsurancePortlet,分配 Default 的名稱前綴BrokerSummaryPortlet,并確定新的 portlet 作為Faces portlet (JSR 168),因此 添加 Faces portlet 框架庫到此項目中(如果它們已經不存在)。
              圖 6. 創建新的 portlet
              Create a new portlet
            3. 接著,確認 Portlet 名稱,選擇默認的 Internationalization Locale,并選擇Change the code generation options 改寫默認名稱,如圖 7 所示。
              圖 7.設置 Portlet
              Portlet settings
            4. 作為上述步驟的結果,將生成圖 13-10 中展示的構件。
              圖 8. 生成的構件
              Generated artifacts

            3. 創建 Portlet 視圖

            利用 New Faces JSP File 對話框 (圖 9)為above羅列的每一個樣本 portlet 視圖創建 Faces JSP。對每一個 JSP,確保為 Model 字段指定Portlet 。這樣能保證合適的 portlet 標記符被初始化,并用于 JSF 表示中。完成時,新的 Faces JSP 將出現在項目中,如同他們在圖 10 所做的那樣。


            圖 9. 創建 Create Faces JSP
            Create Faces JSPs

            圖 10 . 創建 Faces JSP
            Create Faces JSPs

            Application Developer 利用所提供的易于使用的編輯器,為 portlet 配提供置部署的能力,正像它為 EJB 或者 Web 項目所做的那樣。您能利用編輯器修改每一個 portlet 的配置(優于修改作為源的 portlet 部署描述符),舉個例子,可改變在前面的章節中,通過為不同的模式添加初始化參數而創建的 portlet 視圖,比如視圖、編輯、幫助和配置。(圖 12)


            圖 11. 更新 portlet 部署描述符
            Update portlet deployment descriptor

            圖 12. 更新 portlet 部署描述符
            Update portlet deployment descriptor

            4. 導航鏈接

            任何多頁表示均需要從一個頁面到另外一個頁面的導航訪問,并且由 portlet 提供導航控制,這就簡化了導航的開發。可添加導航鏈接到使用鏈接控制的 portlet 內,但是,在導航鏈接控制中提供 URL 值時,需要進行特殊的考慮:在我們的場景中,鏈接 URL 定義為 "/BrokerSummary.jsp".而沒有點(.)。這與開發純的 JSF Web 應用程序頁面不同,它在導航鏈接中需要點(.)。(今后本產品的版本中此要求可能去掉)


            圖 13. 添加鏈接
            Link addition

            5. Portlet 狀態

            作為一種強大的內容傳遞機制,portlet 表示提供了一種在同一表示頁面中配置 portlet 狀態的方法。獨立 portlet 的狀態能被最大化或最小化,因此為用戶感興趣的內容提供了更人性化的視圖。為了實現它,portlet 呈現被分為兩個階段:動作階段和移交階段: As a powerful content delivery mechanism, portlet presentations provide a way to configure the state of the portlet within the same presentation page. The state of individual portlets can either be maximized or minimized, thus providing the user with a more personalized view of the content of interest. To achieve this, portlet presentation delivery is divided into two phases: an action phase and a render phase:

            • 當 portlet 表示頁面被請求時,portlet 進入 移交階段,并展示其內容。
            • 當在 portlet 上調用任何動作時,portlet 進入 動作階段,與 portlet 相對應的動作原理被調用。

            在開發 portlet 中需要特殊考慮的動作對移交階段里,可獲得什么樣的 API 有其局限性。創建請求和響應對象,并且每個階段獲得不同的內容。圖 14 中的代碼樣本展示了,對 JSR 168 portlet 項目,當 portlet 處于工作階段時,如何利用 ActionResponse 改變窗口狀態。就像在我們的場景中,如果終端用戶正瀏覽所有客戶機的策略細節并添加了新的策略時,他可能將 BrokerDetailPortlet 最大化來獲得更好的利用視圖區域的用戶體驗。BrokerDetail.jsp 頁面展示了使用 API 改變窗口狀態。


            圖 14. 改變窗口狀態的代碼片斷
            Code snippet for changing window state

            6. 分頁

            在可管理的組中表示一大組數據,提供每頁數據的子集是經常的需求。在 JSF 頁面 中提供尋呼機控制在這些數據組間的標記頁碼。在 Faces JSP 頁面同時使用尋呼機功能和 click-to-action 功能時要進行特殊的考慮。在這樣的案例中,使用簡單的尋呼機或轉到尋呼機控制器,就像圖 15 展示的那樣,而不是 高級的或 Web 類型尋呼機控制器,這些目前不能被 WebSphere Portal 支持。


            圖 15. 尋呼機控制器
            Pager controls

            7. Dropdown 綁定

            Dropdown 通常用在表示中,無論它是 portlet 或僅是 JSF Web 頁面。 Dropdown的值要么被服務調用動態尋回,要么處于用控制器的靜態定義清單中。在我們的場景中,用的是 portlet 視圖的靜態清單。SearchPolicyPortlet 提供在 Policy amount 的基礎上尋找策略的方法,并且在 SearchPolicy.jsp 的 dropdown 中提供了策略值的靜態清單,就像下圖展示的那樣:


            圖 16. 靜態清單
            Static list

            圖 17. 靜態清單 dropdown
            Static list dropdown

            8. 在 portlet 視圖間傳遞數據

            總有必要在 portlet 的視圖間從一個視圖向另一個視圖傳遞數據。可利用請求或會話傳遞數據,或者您甚至能在表格上定義隱藏變量傳遞數據。例如:

            1. 在 BrokerDetail.jsp 頁面中(圖 18),利用請求參數傳遞客戶機 Id 給 AddPolicy.jsp 頁面(圖 19)
            2. 請求變量的值在頁面 bean 根包裝器 AddPolicyRoot 中作為 selectedClientId 屬性被高速緩存起來。
            3. 表格上的隱藏變量(圖 20)用于在頁面上不同命令動作間保持其值。
            4. 通過把 getText5 變為公共的,BrokerDetail.java 頁面代碼中的 text5 屬性展現在頁面數據中。
            5. 在 SearchPolicy.jsp 頁面中,將 dropdown 中選擇的值作為請求參數傳遞到 portlet 的下一個頁面中(圖 21 和 22)。


            圖 18. 在 BrokerDetail.jsp 中利用請求參數在 portlet 視圖間傳遞數據
            Passing data within portlet views using request parameter in BrokerDetail.jsp

            圖 19. 在 AddPolicy.jsp 中尋回頁面負載上的請求參數
            Retreiving request parameter on page load in AddPolicy.jsp

            圖 20. 利用 AddPolicy.jsp 的隱藏變量超高速緩存 portlet 視圖間的數據
            Caching data within portlet views using hidden variables in AddPolicy.jsp

            圖 21. 在 SearchPolicy.jsp 中傳遞數據作為請求屬性
            Passing data as request attribute in SearchPolicy.jsp

            圖 22. 在負載上的 SearchPolicyResult.jsp 中尋回請求屬性
            Retreiving request attribute in SearchPolicyResult.jsp on load

            9. 在 portlet 間共享數據

            在前面的章節中,展示了如何在單個的 porlet 視圖中共享數據。在不同的 protlet 間共享數據的需求也逐漸提升起來。就像在我們的場景中,在 BrokerDetailPortlet 中使用 AddPolicy 視圖添加新的策略時,BrokerSummaryPortlet 中的 BrokerSummary 視圖應當為用戶更新來反應新加的策略。為 BrokerSummary 視圖服務的 bean 應當從服務中請求新的數據。為了與 BrokerSummaryPortlet 通信,需要從 BrokerDetailPortlet 傳遞消息或者參數到 BrokerSummaryPortlet,因此要在 portlet 間創建需求共享數據。

            共享數據的 portlet 被稱為 cooperative portlets。在 portlet 間共享數據能從多種途徑獲得:

            本文提供的解決方案示例了在 portlet 間利用單個屬性與多個數據屬性通信的property代理人機制:

            • 在 AddPolicy.jsp 的 doAddPolicy 動作中,無論何時在 BrokerDetailPortlet 中添加新的策略時,RefreshView、 NextView 和 WindowState 屬性作為請求屬性 (NextViewData) 傳遞給 BrokerSummaryPortlet。
            • 在 BrokerSummaryPortlet 的 brokerSummary.jsp 視圖中調用 doUpdateView 動作,并且為多個屬性分析 NextViewData 。
            • 僅僅當 RefreshView 屬性正確并且 NextView 屬性確定展示視圖的時候,才用 BrokerService 的數據更新Java bean。
            • 窗口的狀態的確定基于 WindowState 屬性。

            這些數據示例了數據傳遞時 property 代理人的配置:

            1. 啟用包含視圖的源 portlet 使之能傳遞數據。(圖 23)
              圖 23. 啟用源 portlet
              Enable source portlet
            2. 指定用于涉及數據傳遞的數據類型名稱。當現存的數據類型被創建時,您也可以選擇其清單。
            3. boundTo 屬性指定了用于指定所需傳遞數據的機制。
            4. 結果,一個 <SourcePortlet>.wsdl 文件在 webcontent\wsdl 文件夾中生成,該文件夾包含數據類型定義作為 WSDL 語法。
              圖 24. 源 portlet 規范
              Source portlet specification
            5. 確信動作名稱和標題在為源 portlet 規范產生的 WSDL 中進行了定義。當指定連線的時候(之后再描述),標題值用來確定動作。如果這些值不存在,請提供出來。
              <operation name="BrokerDetailPortletportlet">
              	<portlet:action name="UpdateView" caption="Update View" type="standard" />
              	<output>
              		<portlet:param name="NextViewData"
              			partname="NextViewData_Output" boundTo="request-attribute"
              caption="NextViewData"/> </output> </operation>

            6. 在需要傳遞參數的動作上,額外的 request-parameter com.ibm.portal.propertybroker.action 需要為被調用的動作進行定義。此處用到的名稱與在源 portlet WSDL 規范中指定的名稱相同。Property 代理人服務用參數來調用指定的動作。
              圖 25. 傳遞源參數
              Pass source parameters
            7. 在容器中可設置數據作為在源 portlet 規范中 boundTo 屬性的指定值。在本例中,數據在 RequestScope 中設置為調用動作代碼的請求屬性。
              public String doAddPolicyAction(){
              			this.getVarAddPolicyRootBean().addPolicy
              		(this.getVarBrokerDetailRootBean().getBrokerServiceRoot());
              	this.sessionScope.remove("varBrokerDetailRootBean");
              	setNextViewData();
              	return "addPolicy";
              }
              
              public void setNextViewData(){
              	//newViewOutcomeName:RefreshView:WindowState
              	String nextViewData = "newView:true:maximized";
              	this.getRequestScope().put("NextViewData", nextViewData);
              }
              

            8. 啟用包含即將收到傳遞數據的視圖的目標 portlet。
              圖 26. 啟用目標 portlet
              Enable target portlet
            9. 瀏覽在其上調用動作和傳遞指定數據的視圖。目標文件中的 boundTo 屬性可與源 portlet 已經指定的內容不同;這就定義了發送傳遞數據的容器。參數或動作的名稱也可與在源 portlet 指定的名稱不同。
              圖 27. 瀏覽動作
              Browse the action

              圖 28. 目標 portlet 規范
              Target portlet specification
            10. 為目標 portlet 規范在 webcontent\wsdl 文件夾中生成了 WSDL,該規范定義了調用的動作和收到的數據。定義portlet (之后將在中描述) 之間的連線時用到標題名稱。按照由 boundTo 屬性指定的容器,指定的 portlet 參數能從視圖調用的動作中尋回。在本例中,可以從請求作用屬性中尋回 NextViewData。
              <operation name="BrokerDetailPortletportlet">
              	<portlet:action name="UpdateView" caption="Update View" type="standard" />
              	<output>
              		<portlet:param name="NextViewData"
              			partname="NextViewData_Output" boundTo="request-attribute"
              caption="NextViewData"/> </output> </operation>

            11. 在 BrokerSummary.java 中,NextViewData 能從請求作用區域屬性那兒尋回和加工。
              public String doUpdateViewAction(){
              	return processNextViewData();
              }
              
              public String processNextViewData(){
              	String newViewOutcome="";
              	//newViewOutcomeName:RefreshView:WindowState
              	String nextViewData = (String)this.getRequestScope().get("NextViewData");
              	if(nextViewData != null && nextViewData.length() > 0){
              		String[] params = nextViewData.split(":");
              		if(params != null && params.length > 0){
              			newViewOutcome = params[0];
              			if(params.length > 1){
              				if(Boolean.getBoolean(params[1]) == true){
              					//remove the key to get updated data from service
              					this.getSessionScope().remove
              						("varBrokerSummaryRootBean");
              				}
              				if(params.length > 2){
              					//set the window state
              					setWindowState(params[2]);
              				}
              			}
              		}
              	}else{
              		this.getSessionScope().remove("varBrokerSummaryRootBean");
              		return "view";
              	}
              	return newViewOutcome;
              }
              
              public void setWindowState(String windowState) {
              	ActionResponse actionResponse = (ActionResponse)
              		getFacesContext().getExternalContext().getResponse();
              	try {
              		if(windowState == "maximized"){
              			actionResponse.setWindowState(WindowState.MAXIMIZED);
              		}
              		else if(windowState == "minimized"){
              			actionResponse.setWindowState(WindowState.MINIMIZED);
              		}
              		else if(windowState == "normal"){
              			actionResponse.setWindowState(WindowState.NORMAL);
              		}
              	}
              	catch (WindowStateException e) {
              		logException(e);
              	}
              }

            您也能使用傳遞技術到共享多個屬性的復雜數據,就像在范例中那樣,在合作的 portlet 間傳遞復雜的數據。

            10.截取 portlet 動作

            在前面的例子中,在目標 portlet 正展示的 portlet 視圖上調用動作。一旦視圖從 brokerSummary 變到 brokerSummaryNew,任何新的策略添加無法在 brokerSummaryPortlet 中更新。另一個應用程序需求可能是因為源 portlet 對目標 portlet 上正展示的視圖不了解。在這樣的案例中,目標動作代碼不能放置在視圖中。在呈現 現存的視圖之前需要再細分 portlet 類,也需要截取動作。從傳遞到 portlet 動作那兒的數據里定義的視圖名稱能設置成視圖,示例如下:

            1. 在 <TargetPortlet>.wsdl 文件中,定義動作名稱為 UpdateView。這個名稱用來截取 portlet 子集中的動作。
              <operation name="BrokerSummaryPortletportlet">
              	<portlet:action
              		name="UpdateView"
              		type="standard" caption="Update View" description="Update View Action" />
              	<input>
              		<portlet:param name="NextViewData"
              			partname="NextViewData_Input" boundTo="request-attribute" />
              	</input>
              </operation>

            2. 在為 portlet 創建的子集中,為動作名稱截取動作并檢查 com.ibm.portal.propertybroker.action 請求參數。如果動作名稱是 UpdateView,為視圖名稱更新會話參數 com.ibm.faces.portlet.page.view 作為從動作參數尋回數據的定義。
              public void processAction(ActionRequest request, ActionResponse response)
              		throws PortletException {
              
              	String actionName = (String)request.getParameter("com.ibm.portal.propertybroker.action");
              	if (actionName != null && actionName.equals("UpdateView")) {
              
              		// passed value is something like 'viewName1:true:maximized' in the parameter
              		String nextViewData= (String) request.getAttribute("NextViewData");
              				if(nextViewData != null && nextViewData.length() > 0){
              			String viewName = null;
              			int i = nextViewData.indexOf(':');
              			if (i >= 0) viewName = nextViewData.substring(0, i);
              
              			if(viewName  != null){
              				//change the portletView to be displayed
              				request.getPortletSession().setAttribute
              				("com.ibm.faces.portlet.page.view", viewName );
              			}
              					}
              	}
              

            3. 在期待 NextViewData 數據的視圖頁面代碼中,在視圖中尋回參數作為 RequestScope 參數并在目標 portlet 中展示。您可以選擇利用執行基于數據變化的原理寫普通的實用程序類,以便跨越視圖時它能得以再次利用。
              public BrokerSummaryRoot getVarBrokerSummaryRootBean() {
              	if (varBrokerSummaryRootBean == null) {
              		varBrokerSummaryRootBean = (BrokerSummaryRoot) getFacesContext()
              			.getApplication().createValueBinding(
              				"#{varBrokerSummaryRootBean}").getValue(
              				getFacesContext());
              	}
              	String nextViewData= (String) request.getAttribute("NextViewData");
              	//process data
              	return varBrokerSummaryRootBean;
              }
              

            11. 運行 XYZInsurance portlet 項目

            1. 因為 EMF 的不同運行時版本必須有 XSD SDO 轉換功能才能使用,所以部署在 WebSphere Portal V5.0.2.x 或 V5.1 上的利用轉換功能的應用程序需要用 PARENT_LAST 類加載器策略和 APPLICATION WAR 類加載器策略隔離進行設置。圖 29 展示了用于設置此類加載器配置的 WebSphere Portal 配置中的章節。如果沒有,可從全球類途徑登陸到 portal 服務器提供的 EMF 框架工作的更老點的版本。這個版本與需要 XSD SDO 轉換功能生成的 SDO 的那個不相容,因此可能引起應用程序的運行時失敗。
              圖 29. WebSphere Portal 應用程序類加載器
              WebSphere Portal application classloader configuration
            2. 為配置統一測試環境(UTE),用選擇的 Test environment 安裝選項安裝 WebSphere Portal V5.1。您工作空間安裝的運行時中的 WebSphere Portal 存根應該指向安裝的 portal 服務器 UTE 位置。結果,WebSphere Portal V5.1 測試環境將作為目標服務器運行時的選擇展示出來(圖 30)。目標為此存根的任何項目作為運行時時將被配置來使用這個測試環境。保證定好對 WebSphere Portal V5.1 服務器的 JSR 168 portlet 項目目標來使用合作 portlet。
              圖 30. 作為檢測環境的 WebSphere Portal V5.1 存根配置
              WebSphere Portal V5.1 stub configuration as test environment
            3. 因為我們的場景使用 property 代理實現 portlet 間的數據共享,因此附加的配置步驟(創建 portlet 線路,在下一步中作為示例)需要用來啟用 portlet 通信。利用 portal 服務器管理控制臺創建和配置線路。在 portal 服務器管理控制臺中啟用線路配置,確保在您在 WebSphere Portal 配置的 Portal Options 中檢查為 portal 管理和自定義啟用基礎 portlet。(圖 31)
              圖 31. Portal 選項
              Portal options
            4. 在 portlet 間為 property 代理連線 portlet,服務器啟動后每次執行下列步驟:
            5. 選擇 XYZInsurance 應用程序,右鍵點擊并選擇 Run On Server。圖 35、36 和 37 展示了出現在解決方案中的所有 portlet。
              圖 35. 簡明的 portlet
              Summary portlet

              圖 36. 詳細的 portlet
              Detail portlet

              圖 37. 尋找 portlet
              Search portlet






            結束語

            本系列文章的第 4 部分致力于分析示例應用程序場景,該場景使用基于 XML 的 SOA 松耦合的 portable JSR 168 portlet 開發。也描述了在 WebSphere Portal 的配置中涉及到的為必需的 EMF 運行時區別的問題。本文集中在 portlet 視圖和 portlet 間的共享數據上,并描述了通過 property 代理人用單個 property 在共享多個數據屬性涉及到的步驟。

            第五部分將討論為使用 XSD SDO 轉化特性的基于 XML 的 SOA 本地化 JSF 和 portlet 應用程序,并且將定位基于優選的區域顯示本地化的靜態和動態內容。








            下載

            描述 名字 大小 下載方法
            Download file 1 xsd_sdo_soa_xml_sample.zip 4.8 MB ?FTP|HTTP
            Download file 2 xsdsdotransform-feature.zip 52 KB ?FTP|HTTP

            posted on 2006-04-17 03:30 wsdfsdf 閱讀(478) 評論(0)  編輯 收藏 引用 所屬分類: 技術文章

            久久香蕉国产线看观看99| 久久久久久人妻无码| 午夜欧美精品久久久久久久| 久久精品国产亚洲AV不卡| 久久久久国产精品嫩草影院| 久久久久无码精品国产| 99久久99久久精品国产片| 亚洲精品白浆高清久久久久久| 久久综合亚洲色一区二区三区| 久久青青草原精品国产| 国产—久久香蕉国产线看观看 | 欧美综合天天夜夜久久| 久久se精品一区精品二区| 热久久国产欧美一区二区精品| 亚洲国产精品无码久久| 77777亚洲午夜久久多喷| 久久久WWW免费人成精品| 无码人妻久久一区二区三区 | 97久久精品午夜一区二区| 国产精品久久成人影院| 中文字幕无码久久久| 久久久久免费精品国产| 精品久久久久久久国产潘金莲 | 人妻无码中文久久久久专区| 久久久久亚洲AV成人网| 久久久久久国产精品免费无码| 久久av高潮av无码av喷吹| 久久久久四虎国产精品| 国产精品久久久久久福利69堂| 久久久噜噜噜久久中文字幕色伊伊| 久久国产精品-国产精品| 久久婷婷国产综合精品| 狠狠综合久久综合88亚洲| 久久中文字幕人妻丝袜| 中文字幕乱码人妻无码久久| 亚洲七七久久精品中文国产| 久久精品中文字幕第23页| 久久精品国产一区二区| 欧美激情精品久久久久久| 久久强奷乱码老熟女| 亚洲国产综合久久天堂|