最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

使用 JSF、Ajax 和 Seam 开发 Portlets(3/3)

  • 2008-12-19
  • 本文字数:5242 字

    阅读完需:约 17 分钟

在这个系列文章的第一篇第二篇中,我解释了什么是portlet bridge?以及如何在一个基本的JSF 和基于RichFaces(Ajax)的portlet 中安装和使用它,和当前能支持运行JBoss Portlet Bridge 的portal 服务器的主要区别。最后这篇文章将集中讲述Seam portlet 的开发,和最新发布的 JBoss Portlet Bridge Beta 4 版本的所有特性和优势。对于不太熟悉 portlets 的读者来说,仔细阅读前面两篇文章会有助于更好的理解本文。

现在让我们先从 Seam portlet 的开发入手。

安装 Seam Portlet

开发工具:

要仿照本文示例进行开发,就需要下载最新版本的 Maven(我用的是 2.0.9 版本)。
安装 Maven 2.0.9+
在机器上设置Maven binaries 的path 环境变量

创建项目:

不同的 Maven 原型(archetype)对应可以产生不同种类的 bridge。直接从命令行运行如下代码,可创建你的 Seam portlet 项目:

复制代码
mvn archetype:generate
-DarchetypeGroupId=org.jboss.portletbridge.archetypes
-DarchetypeArtifactId=seam-basic -DarchetypeVersion=1.0.0.B4
-DgroupId=org.my.project -DartifactId=seamproject
-DarchetypeRepository=http://repository.jboss.org/maven2/ -Dversion=1.0.0.B4

该特定原型是模块化的,这意味着通过其产生的项目将由几个子项目构成。这样做的好处是源码、资源和配置之间的界限更加清晰,维护也更方便。上述命令将产生三个目录,其中,‘web’目录中包含标记文件、图片和 WEB-INF xml 配置文件;‘ejb’目录中包含所有 Seam EJB3 源码,以及任何跟持久化和 ejb 部署相关的 xml 配置文件信息;最后是‘ear’目录,它主要用来集合项目信息构建 ear 文件。

如果你是用上面提到的原型(archetype)命令创建的项目,那么现在你就会有一个‘seamproject’目录。现在到该目录下并运行如下命令:

mvn install 这个命令将会帮助你下载本地 Maven 库中缺少的任何组件,并编译和构建 ear 文件。

运行和部署 portlet:

既然你已经有一个可部署的 ear 文件,那么再利用下面的命令就可以轻松的将 portlet 部署到最新版本的 JBoss Portal 上(已绑定到 JBoss 应用服务器)了。如果你已经自己下载或创建了本地安装包,就可在 bridge 文档中找到使用自定义配置的说明了。

现在转到{seamproject}/ear 目录下运行如下命令:

复制代码
mvn cargo:start -Premote-portal-Dportal-2.7.0.B1

该命令将花上一段时间(视你的网络情况而定)来下载最新版本的 JBoss Application Server 和 JBoss Portal(软件均位于 SourceForge.net 网站上)。在继续下一步骤之前你应该能看到与上文画面相似的日志记录。* 注意:你也许还会看到日志记录中不断滚屏的 WSRP 信息,不用担心,这同样是证明你已准备就绪的标志。

现在来部署你的 Seam 项目 ear 文件。新打开一个终端窗口,转到目录{seamproject}/ear 下,运行如下命令:

复制代码
mvn cargo:deploy-Premote-portal -Dportal-2.7.0.B1

当你在服务器日志中看到 ear 文件已部署成功时,访问链接 http://localhost:8080/portal/portal/default/seamproject ,会看到如下页面:

现在我们已经准备好一个要开发 Seam portlet 了。当然,应用程序到底怎么写是由开发人员来决定的事情。但是这会帮你摆脱那些琐碎的配置问题,轻松的开始工作。

配置

将 JSF portlet 转换为一个典型的 Seam 应用,只需要少量的配置工作即可完成。下面的配置文件代码省略了前面文章(第一部分第二部分)已经提到过的配置信息。如果想了解详细内容,请参照bridge 文档的配置部分

web.xml
------------------

下面的这段配置通常是任何 Seam 应用中都会有的内容,并且不会因为 portlet 环境而有所不同:

复制代码
<listener>
<listener-class>
org.jboss.seam.servlet.SeamListener
</listener-class>
</listener>
<servlet>
<servlet-name>Seam Resource Servlet</servlet-name>
<servlet-class>
org.jboss.seam.servlet.SeamResourceServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Seam Resource Servlet</servlet-name>
<url-pattern>/seam/resource/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>Seam Filter</filter-name>
<filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Seam Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
<dispatcher>INCLUDE</dspatcher>
</filter-mapping>

配置 ExceptionHandler 上下文参数,可允许 bridge 应用现成的异常处理器去解决基于 Seam 的异常。如果愿意的话,你也完全可以应用自己的实现:

复制代码
<context-param>
<param-name>org.jboss.portletbridge.ExceptionHandler</param-name>
<param-value>
org.jboss.portletbridge.SeamExceptionHandlerImpl
</param-value>
</context-param>

Bridgelet 是针对 portlet bridge 扩展(extension)的名称。portlet bridge 社区一直在积极的开发一些扩展以增强或集中 JBoss Portal、Seam 和 Richfaces 三者的特性,例如,PortalIdentity(SSO)seam 组件可允许你把 jar 文件放在你的 classpath 上,这样你立刻就会有一个可用于 Seam 和 Portal 之间的 SSO 了。你也可以在 Maven pom 中将这个扩展配置成一个依赖(象下面将看到的那样)。

如果你对 Bridgelet 有什么建议,或者有意参与 JBoss Portlet Bridge 的开发工作,那么我们期待你积极加入我们的论坛并提交 Jira tasks

Seam 应用和 JBoss Portal 之间的单点登录问题

开发人员可以把 Seam Booking Demo 用做一个开发和测试的 portlet 参考程序。如果想了解和实践 SSO Bridgelet,你可以从此地址 http://anonsvn.jboss.org/repos/portletbridge/tags/1.0.0.B4/examples/seam/booking/ 下载源代码,然后运行与此篇文章上面刚刚讲过的完全相同的 maven 部署命令(或者是下面将要讲到的简短版本)来部署和运行该程序。

简短版本是:
转到{SeamBooking}根目录下,运行如下命令:
mvn install

然后再转到{SeamBooking}/ear 目录下,运行:
mvn cargo:start -Premote-portal-Dportal-2.7.0.B1

现在再来部署你的 Seam 项目 ear 文件。新打开一个终端窗口,在{SeamBooking}/ear 目录下运行如下命令:
mvn cargo:deploy-Premote-portal -Dportal-2.7.0.B1

一旦你部署完成并运行 demo 后,就可以访问链接 http://localhost:8080/portal/portal/default/SeamBooking 继续下面的步骤了。点击“注册新用户(Register New User)",新建一个用户并用其登录系统:

登录之后你将会看到酒店搜索页面,还有与当前登录角色对应的所有功能。但是,如果你看向屏幕右上角,你会发现登录到 Seam 应用和你的 JBoss Portal 用户 / 管理员账户一点关系都没有:

这就是我们需要 SSO Bridgelet 的理由,它允许通过 Seam 身份认证模块来验证 JBoss Portal 用户名。现在让我们来尝试一下:
令服务器依然保持运行状态,在进行部署的那个终端窗口中,返回到上一级目录,也就是{SeamBooking}/ 根目录下运行如下命令:
mvn install -Psso

接下来再转到{SeamBooking}/ear 目录下运行如下命令:
mvn cargo:deploy-Premote-portal -Dportal-2.7.0.B1

通过上述命令我们将 SSO jar 包嵌入进了应用,并重新部署了一次 ear 文件。

现在,让我们回到 http://localhost:8080/portal/portal/default/SeamBooking 上的 portlet。这次我们登录到 portal 而不是 Seam 应用。点击页面右上方的 portal login 进行登录,用户名和密码都是‘admin’。

如果这是一个现实中的应用,我们会对 UI 做一点调整,把 Seam 应用的登录表单隐藏起来。同时因为 SSO 的存在,我们可以调整网站其它基于角色的内容。但是,正如我前面所说,这是从最原始状态的 Seam booking demo 出发做最小改动能达到的效果,只是一个参考。

登录到 JBoss Portal 后,在你的 Seam 和 Portal UI 上你将会看到如下内容:

在解决了 Portal 和你的 Seam 应用之间的身份认证问题后,应用的创建就变得容易些了。如果你的 Seam portlet 是基于 Maven 创建的,那么还需要你做的就只有在 pom.xml 文件中添加如下代码了:

复制代码
<dependency>
<groupId>org.jboss.portletbridge.extensions.seam</groupId>
<artifactId>PortalIdentity</artifactId>
<version>1.0.0.B4</version>
</dependency>

或者你也可以把 PoralIdentity.jar 文件放到应用程序 WEB-INF/lib 目录下就行了,不再需要做别的配置了。

JBoss Portlet Bridge Beta4 概述

既然这是本系列文章的最后一篇,那么在最后一部分我将介绍 9 月 11 日刚刚发布的 JBoss Portlet Bridge Beta 4 版本的新特性。

支持 PortletMode 变化

一个 PortletMode 代表了应用中一个不同的展现路径(render path),有三种标准的模式:view、edit 和 help。bridge 的 ExternalContext.encodeActionURL 可以辨认查询字符串参数 javax.portlet.faces.PortletMode,并用这个参数值在底层 portlet actionURL 或响应上设置 portlet 模式。 一旦处理完就要把这个参数从查询字符串中去掉。下述导航规则将会在 portlet 的 edit 模式下呈现 viewId 为\edit.jspx 的页面:

复制代码
<navigation-rule>
<from-view-id>/register.jspx</from-view-id>
<navigation-case>
<from-outcome>edit</from-outcome>
<to-view-id>/edit.jspx?javax.portlet.faces.PortletMode=edit</to-view-id>
</navigation-case>
</navigation-rule>

导航至一个模式的最终 viewId

缺省地,一个模式的改变将从模式的默认视图(不带状态)开始。对于一个普通的 portlet 模式,在其返回到进入另一模式之前的那个模式时(例如:view->edit->view),它将会跳转到这个模式(离开之前)的最终视图(和状态)。bridge 能够对必要信息进行清楚的编码,以便有需要返回到前一个模式时,它可以定位到适当的视图,并恢复到应有的状态。开发人员可以使用由 bridge 维护的 session 属性,以便从一个模式导航回其前一个模式的最终位置和状态。同样,开发人员需要描述一个动态导航:“从视图 X 返回到模式 Y 的最终视图”。这可以用由 EL 表达式简单地表示如下:

复制代码
<navigation-rule>
<from-view-id>/edit.jspx*</from-view-id>
<navigation-case>
<from-outcome>view</from-outcome>
<to-view-id>#{sessionScope['javax.portlet.faces.viewIdHistory.view']}</to-view-id>
</navigation-case>
</navigation-rule>

Portlet 开发人员需要注意的问题

根据 bridge 实现,当用到这些 session 范围的属性值、或者任何可能包含查询字符串参数的 viewIds 时,最好在验证规则目标(rule target)时使用通配符语法。例如,上面的<to-view-id>表达式返回的是一个表单的 viewId(/viewId?javax.portlet.faces.PortletMode=view&....)。其不含通配符,因此当该新视图发生页面跳转时,导航规则就无法解析了,因为它找不到任何可与之完全匹配的对象。

而上面的edit.jspx <from-view-id>包含了通配符,导航规则就可用查询串(<to-view-id> /edit.jspx?javax.portlet.faces.PortletMode=edit </to-view-id>)来和它匹配。强烈建议开发人员都使用这种通配符以确保程序可以在各种 bridge 实现中正常执行。

处理 Portlet 中的 Ajax 错误

默认的,错误是由处理 Ajax 请求的标准 servlet 页面来解决。要在 portlet 内部处理错误,就要用到下面的 JavaScript 代码:

复制代码
<script type="text/javascript">
A4J.AJAX.onError = function(req,status,message){
window.alert("Custom onError handler "+message);
}
A4J.AJAX.onExpired = function(loc,expiredMsg){
if(window.confirm("Custom onExpired handler "+expiredMsg+" for a location: "+loc)){
return loc;
} else {
return false;
}
}
</script>

结论

正如前面所说,portlet bridge 社区从项目早期测试阶段就已经开始发布补丁和其它形式的帮助来促进其发展。虽然项目的核心是 JSR-301 规范,然而整合 Seam、 Richfaces、Portal 和 Bridgelets 以及其它辅助性的加强功能是具有无限潜能和意义的。已经有些开发人员为项目的发展贡献了他们的力量,在此我们对所有这些提供过补丁、增强构件以及在论坛上积极回答问题的人们表示衷心的感谢。

最后,这是一个基于社区的项目,提供帮助和反馈的开发人员越多,我们的新产品发布的越快,其功能也就更强,代码也更完善。预计 GA 版本会在 09 年初发布。

论坛上提供反馈非常有用,我们也很欢迎。如果你想要了解更多关于JBoss Portlet Bridge 项目的信息可以访问我们的项目和文档页面

相关阅读

使用JSF、Ajax 和Seam 开发Portlets(1/3)使用JSF、Ajax 和Seam 开发Portlets(2/3)


志愿参与InfoQ 中文站内容建设,请邮件至 editors@cn.infoq.com 。也欢迎大家到 InfoQ 中文站用户讨论组参与我们的线上讨论。

2008-12-19 00:301662
用户头像

发布了 127 篇内容, 共 42.0 次阅读, 收获喜欢 5 次。

关注

评论

发布
暂无评论
发现更多内容

iOS中的继承

NewBoy

前端 移动端 iOS 知识体系 7月月更

分布式事务(Seata)原理 详解篇,建议收藏

牧小农

Cgroup cpu,cpuacct子系统

总想做点什么

图解网络:什么是 DNS 域名系统?

wljslmz

网络协议 DNS 网络技术 7月月更 域名系统

电商系统微服务拆分

地下地上

架构师实战营

《看完就懂系列》谈谈数据埋点的原理与实现

南极一块修炼千年的大冰块

7月月更

架构实战营模块六作业

融冰

动态注册广播流程学习

北洋

Andriod 7月月更

kafka 生产者分区策略演进

布兰特

kafka

小程序视图容器

小恺

7月月更

小程序电商业务微服务设计与基础设施选型

Geek_e8bfe4

SkyWalking原理浅析

技术小生

APM Skywalking 性能监控 7月月更

架构实战营|模块6

KDA

#架构实战营

有赞们的逻辑变了吗?

科技新知

Python 入门指南之错误和异常

海拥(haiyong.site)

7月月更

【玩转 RT-Thread】线程管理原理

攻城狮杰森

7月月更 RT-Thread

源码阅读

ES_her0

7月月更

聊聊消息中心的设计与实现逻辑

Java 架构

Python绘制精美可视化数据分析图表(一)-Matplotlib

迷彩

Python 可视化 matplotlib 7月月更

批量处理数据神器——Java数组与引用

未见花闻

7月月更

电商系统微服务拆分(架构实战营 模块六作业)

Gor

不习惯的Vue3起步二 の alias别名、ref和reactive

空城机

Vue3 7月月更

Java基础:集合框架之Collection(List,Set)

百思不得小赵

集合 Java’ 7月月更

【刷题记录】6. Z 字形变换

WangNing

7月月更

读书笔记之《深入理解Java虚拟机:JVM高级特性与最佳实践》

蔡农曰

Java JVM 后端开发 后端技术

Mac M1 投屏软件scrcpy

IT蜗壳-Tango

7月月更

拆分电商系统为微服务

Pengfei

DDD实战(11):冲刺1代码TDD实现之道

深清秋

DDD 软件架构设计 生鲜电商系统 7月月更

【C 语言】进阶指针 Three

謓泽

7月月更

spring 循环依赖

急需上岸的小谢

7月月更

架构实战营模块 6 作业

Naoki

架构实战营

使用JSF、Ajax和Seam开发Portlets(3/3)_Java_Wesley Hales_InfoQ精选文章