随笔 - 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 阅读(473) 评论(0)  编辑 收藏 引用 所属分类: 技术文章


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理