 | 级别: 初级 Roland Barcia (barcia@us.ibm.com), IT 顾问专家, IBM Software Services for WebSphere
2004 年 5 月 01 日 这一系列由 5 部分组成。在前面的部分中,我们使用快速应用程序开发(Rapid Application Development,RAD)组件创建了 Java Server Faces 表单,并了解了 JSF 如何利用 Web Data Object(WDO)或 Service Data Object(SDO)技术来访问数据。在第 4 部分中,我们将来介绍一下 JSF 如何利用现有的 J2EE 技术。
这一系列由 5 部分组成。在前面的部分中,我们使用快速应用程序开发(Rapid Application Development,RAD)组件创建了 Java Server Faces 表单,并了解了 JSF 如何利用 Web Data Object(WDO)或 Service Data Object(SDO)技术来访问数据。在第 4 部分中,我们将来介绍一下 JSF 如何利用现有的 J2EE 技术。
引言
这一系列文章展示了 WebSphere® Studio V5.1.1 中的 Java™ Server Faces TechnologyPreview 的特征,本文是其中的第 4 部分。该系列文章包括以下几个部分:
在文章系列的
第 3 部分中,我们看到了 JSF 应用程序如何利用 Service Data Object(SDO)技术来访问数据。在本文中,我们将会看到 JSF如何利用现有的 J2EE 技术。我们将会创建一个调用现有的 EJB 应用程序的 JSF 页面,并在兼顾 JSF 的 RAD 性质的前提下运用 JavaBeanData 控制来显示 EJB 调用结果。另外,我们将会使用 Quick Edits 视图来编写 Action Handler,以便调用现有的无状态会话Bean。
要想完成这些练习,您需要
下载包含在本文中的资料。万一您还没完成第 3 部分,下载文件包含了解决方案;请按照
第3 部分所描述的方法导入该 EAR 文件。要想运行示例,您还需要按照第 3 部分所阐述的方法创建数据库;导入解决方案之后,请按照第 3部分最后一节描述的方法运行应用程序,这样就可在用于此练习的 Server Configuration 中创建 JDBC 数据源。
导入并安装 StockSystemEJB
现在我们来为
第2 部分创建的 Stock Data Page 创建下一个 JSF 结果页面。首先我们导入现有的 EJB JAR 文件,然后创建显示结果的JSF 页面。
- 要想导入 EJB JAR 文件并使它成为现有 EAR 文件的一部分,您需要执行以下的步骤:
- 在 WebSphere Studio Application Developer(以后简称为 Application Developer)中选择
File => Import。
图 1. Application Developer File 菜单
- 选择
EJB JAR file,然后单击
Next。
图 2. File Import 对话框
- 定位到
C:\JSFArticleSeries\Part4\StockSystemEJB.jar。Project 名称应该为
StockSystemEJB。选择现有的EAR 文件
StockSystemEAR。(您必须显式地选择现有的 EAR;它在缺省情况下为
StockSystemEJBEAR,这可能容易让人误解。)单击
Finish。
图 3. EJB Import
- 在弹出 Repair Server Configuration 对话框时,请单击
OK。
图 4. Repair Server Configuration
- 既然已经将 EJB JAR 文件导入现有的 EAR 之后,现在就需要让它对 WAR 文件可视。可以这样来实现:将 EJB JAR 文件添加到 WAR文件的清单中,这种方式是处理类路径的标准 J2EE 方式之一。Application Developer提供了一种完成这一操作的简单方法:在一个步骤中将 EJB JAR 同时添加到构建时和编译时类路径中。
- 右键单击 Project Navigator 视图中的
PersonalTradeJSFWeb 项目,选择
Properties。
图 5. Project Navigator
- 选择
Java JAR Dependencies。在该对话框中,选中
StockSystemEJB.jar。确保
Use EJB JAR也被选中。(对于 Version 5.1.1,Application Developer 支持会生成 EJB Client JAR)。
图 6. Java JAR Dependencies
- 单击
OK。
- 在我们的应用程序中,PersonalTradeJSF 会访问 StockFacadeEJB。StockFacadeEJB与实体 bean 相结合来访问当前股票数据。访问 EJB 时使用 EJB 引用被视为一种最佳实践。虽然 EJB JAR 提供了委托来隐藏 EJB客户端 API 的细节,但它使用了资源引用。由于委托是在 Web 应用程序的上下文里调用的,所以还需要定义引用。
- 在 Project Navigator 中,利用 PersonalTradeJSF 底下的链接打开
Web Deployment Descriptor编辑器。
图 7. 打开 Web Deployment Descriptor
- 选择该编辑器底部的
References选项卡。
图 8. References 选项卡
- 选择 References 页面中的
EJB Local选项卡。
图 9. EJB Local References
- 选择 EJB Local References 选项卡下的
Add。
图 10. 添加 EJB Local references
- 添加名为
ejb/StockFacade 的引用。
图 11. 添加 ejb/StockFacade
- 在 Details 部分单击
Browse按钮。
图 12. Details 和 WebSphere Bindings
- 选择
StockFacadeEJB 并单击
OK。
图 13. 选择 StockFacade EJB
- 会话 bean 和绑定信息都必须填写完整。
图 14. Details 和 WebSphere Bindings
- Web 应用程序会使用 EJB 本地接口来访问数据。EJB 本地接口将符号作为输入并返回一个 AccessStockQuoteVO。这是一个带有 getters 和 setters 的简单 JavaBean。
public interface StockFacadeLocal extends javax.ejb.EJBLocalObject {
public AccessStockQuoteVO getCurrentStockData(String symbol)
throws SymbolNotFoundException,
StockException,
InvalidSymbolException;
...
}
|
- EJB JAR 提供了一个简单的 Delegate 对象,它隐藏了对象的复杂性。该委托是一个单独的 Java 对象,它提供了一个类似的接口。
public class AccessQuoteDelegate
{
private StockFacadeLocal stockFacade;
public static AccessQuoteDelegate accessQuoteDelegate = null;
public static AccessQuoteDelegate getAccessQuoteDelegate() throws StockException
{
if(accessQuoteDelegate == null)
{
accessQuoteDelegate = new AccessQuoteDelegate();
}
return accessQuoteDelegate;
}
private AccessQuoteDelegate() throws StockException
{
InitialContext context;
try
{
context = new InitialContext();
StockFacadeLocalHome home = (StockFacadeLocalHome)context.lookup("java:comp/env/ejb/StockFacade");
stockFacade = home.create();
}
catch (NamingException e)
{
throw new StockException(e.getLocalizedMessage());
}
catch (CreateException e)
{
throw new StockException(e.getLocalizedMessage());
}
}
public AccessStockQuoteVO getCurrentStockData(String symbol)
throws SymbolNotFoundException, StockException, InvalidSymbolException {
return stockFacade.getCurrentStockData(symbol);
}
}
|

 |

|
创建 viewStockData.jsp
设置好 EJB对象之后,我们就可以创建 Stock Data 页面,用它来显示调用 StockFacade stockData 方法的结果。
- 首先,我们创建一个新的 JSF 页面来显示提交 Stock Data Request 的结果。
- 在 Application Developer 中,右键单击 PersonalTradeJSF 页面中的
WebContent文件夹,选择
New => Faces JSP File。
图 15. 创建新的 JSF 页面
- 在 File Name 字段中键入
viewStockData.jsp ,然后选择
Create from page template。
图 16. New Faces JSP File
- 确保选中
StockPageTemplate.jtpl。单击
Finish。
图 17. Page Template File Selection
- 现在我们使用 Visual Palette 来添加标签。
- 在 Faces Visual Palette 中选择
Output组件。
图 18. Visual Palette
- 将 Output 组件添加到页面中。将文本大小设为 18,文本值设为:
View Stock Data 。
图 19. 将 Output 添加到 JSP 中
- EJB 返回一个正规的 Java Bean。我们将作为页面数据添加该 Java Bean。
- 转到 Page Data 视图。右键单击
JSP Scripting并选择
New => JavaBean。
图 20. 创建新的 JavaBean
- 在 Add Managed Beans 对话框中选择
New。
图 21. Add Managed Beans 对话框
- 单击
Browse...按钮。
图 22. Create a Managed Bean 对话框
- 查找 AccessStockQuoteVO;它是调用 StockFacade Session Bean 时返回的数据。
图 23. Class Selection 对话框
- 在 Name 字段中键入
stockData ,在 Scope 字段中选择
request。
图 24. Create a Managed Bean 值
- 单击
OK。
图 25. Add Managed Bean 值
- 现在 stockData 对该页面已经可用了。
图 26. Page Data
- 现在我们就可以将 stockData bean 从 Page Data 视图拖到 JSP 页面中。
- 从 Page Data 视图中选择
stockData对象,将它拖到 JSP 中的 View Stock Data 组件下,如图 27 所示。
图 27. 将 Data Object 拖到 JSP 中
- 选择
Create output components。
图 28. Select drop action 对话框
- JSP 现在就包含了与 JavaBean 相匹配的 JSP 元素了。
图 29. JSP 元素
- 我们需要更新输出组件的属性,以使显示界面对用户更加友好。
- 选中 JavaBean 组件中的任何一个地方。转移到 Attributes 对话框,选择
TABLE,如图 30 所示。在 Table 选项卡中,在 Border 一项中键入
0 。
图 30. Attributes 对话框
- 选中
symbol字段标题,将首字母改为大写。
图 31. 选择字段标题
- 此外,在 Attribute 项中,对于每个字段名称 Cell 均选择
Header。
图 32. Cell 属性
- Header 必须为粗体。
图 33. Header 字段
- 修改所有其他的标题元素,如图 34 所示。
图 34. 其余的标题元素

 |

|
操作处理和导航
结果页面创建之后,我们需要为提交页面创建 Action Handler,以便与 EJB相交互。这些完成之后,我们需要收集结果以便配置恰当的导航规则。我们可以使用控制的 Quick Edit 项来将 Server Side Actions添加到应用程序中。
- 添加一个操作到 accessStock.jsp 页面中。
- 打开 accessStock.jsp 页面。
图 35. 打开 accessStock.jsp
- 选择
Submit Stock Request按钮。
图 36. JSP 中的 Submit Stock Request 按钮
- 在 Quick Edit 按钮菜单中选择 Command。
图 37. Quick Edit 菜单
- 代码提供在
下载文件中。将
C:\JSFArticleSeries\Part4\CodeSnippet1.txt 中的代码复制到 Quick Edit 窗口的编辑区中。主要的代码段是在
try 块中,但也包含了一些异常捕获和错误处理的代码:
-
try 块得到 Delegate 的一个实例,并调用business 方法(该方法也依次调用 StockFacadeEJB)。结果返回 AccessStockQuoteVO。我们将返回结果存储在 stockData名称下的请求作用域中。
viewStockData.jsp 就是通过该名称期待获得这一结果的。(符号输入是从请示作用域中获得的。)
try
{
com.deploybook.stock.delegate.AccessQuoteDelegate
accessQuote = com.deploybook.stock.delegate.AccessQuoteDelegate.getAccessQuoteDelegate();
com.deploybook.stock.vo.AccessStockQuoteVO
accessQuoteForm = accessQuote.getCurrentStockData((String)requestScope.get("symbol"));
requestScope.put("stockData",accessQuoteForm);
}
|
- 如果我们捕获到一个异常,我们就在按钮组件中添加一个错误方法。
codebehind 对象根据属性中配置的名称实例化页面中的每个组件。然后返回 failure。如果没有对失败返回值配置导航的话,它就会返回到同一个页面。我们可以添加一个链接到按钮控制的错误组件。
catch (com.deploybook.stock.exceptions.StockException e)
{
e.printStackTrace(System.err);
context.addMessage(buttonEx1,
new javax.faces.application.MessageImpl(
javax.faces.application.Message.SEVERITY_ERROR,
"Stock Not found",
"Symbol Not Found or invalid"
));
return "failure";
} catch (com.deploybook.stock.exceptions.SymbolNotFoundException e) {
e.printStackTrace(System.err);
context.addMessage(buttonEx1, new javax.faces.application.MessageImpl(
javax.faces.application.Message.SEVERITY_ERROR,
"Stock Not found",
"Symbol Not Found or invalid"
));
return "failure";
} catch (com.deploybook.trade.exception.InvalidSymbolException e) {
e.printStackTrace(System.err);
context.addMessage(buttonEx1,
new javax.faces.application.MessageImpl(
javax.faces.application.Message.SEVERITY_ERROR,
"Stock Not found",
"Symbol Not Found or invalid"
));
return "failure";
}
|
- 如果所有的执行都成功完成,那么我们返回success。然后再来配置导航。
- Quick Edit 应该包含这些代码,如图 38 所示。
图 38. 包含代码的 Quick Edit 对话框
- Java 代码会自动添加,打开
accessStock.java 即可确认是否自动添加代码。
图 39. 打开 accessStock.java
图 40. accessStock.java 代码
- 现在我们需要指定导航规则。我们并不需要第 3 部分所做的那样,让提交操作对执行结果进行硬编码,而只需指定返回导航结果的操作处理程序。
- 在依旧选中该按钮的前提下,切换到 Attribute 视图。选择
Navigation选项卡,然后单击
Add按钮。
图 41. Navigation 属性
- 选择
viewStockData.jsp作为 Page 的值。在 Alias 字段中键入
success (它也是由操作处理程序返回的)。在 ActionRef 字段中选择
cb_accessStock.buttonEx1Action。
图 42. Add Navigation Rule 对话框
- 我们并不需要为控制指定操作结果,因为操作会控制它。
图 43. 添加的 Navigation 属性
- 我们已经为按钮组件将错误存储为消息了,因此我们需要在提交页面中建立一个错误组件。
- 在 Faces Component 面板中选择
Display Error组件。
图 44. Visual Palette
- 将它拖到 JSP 页面中 Access Stock 标题和输入表单之间的地方。
图 45. 将错误组件添加到 JSP 中
- 选中输出组件,然后切换到 Attribute 视图。在
For validation errors on项的 Id 字段中选择
buttonEx1。
图 46. 输出组件属性

 |

|
测试 JSF 组件
在测试应用程序之前,我们还需要对服务器配置做两个更新。然后再来测试成功的和错误的场景。
- 我们需要创建一个验证别名,并使 CMP 支持生成的 WDO 数据源。这就可以让 EJB JAR 中的实体像 WDO 对象那样使用同一个数据源了。
- 转到 Servers 视图,方式是选中 Web 透视图底部的
Servers选项卡。双击服务器来打开 Server Configuration编辑器。
图 47. 打开 Server Configuration 编辑器
- 选择 Server Configuration 编辑器的
Security选项卡。
图 48. Server Configuration 编辑器选项卡
- 单击 JAAS Authentication Entries 旁边的
Add。
图 49. JAAS Authentication Entries
- 在 Alias 字段中键入
DBUser 。在 User ID 和 Password 字段中键入
db2admin (或者键入任何您要在创建数据库时使用的密码)。
图 50. 添加新的用户 ID 和密码
图 51. 添加的 JAAS 验证实体
- 切换至 Data source 透视图。
图 52. 选择 Data source 选项卡
- 在 Server Settings 下选择
WDO DB2 JDBC Provider,然后单击 Data source 列表中的
Edit按钮。
图 53. Server Settings
- 在 Container-managed authentication alias 字段中选择
DBUser,并选中
Use this data source in container managed persistence (CMP)的复选框。
图 54. 编辑数据源
- 单击
Save并关闭服务器编辑器。
- 现在开始运行应用程序:
- 在 Project Navigator 中右键单击
accessStock.jsp并选择
Run on Server。
图 55. 运行应用程序
- 选中
Deploy EJB beans,然后单击
Finish。
图 56. Select Tasks 对话框
- 在字段中键入
IBM 并单击
Submit Stock Request。
图 57. 用有效数据进行测试
- 返回如图 58 所示的结果。
图 58. 成功的测试结果
- 返回提交页面,并键入
IBB 作为 Enter Stock 的值。
图 59. 用无效数据进行测试
- 页面中会显示错误信息,如图 60 所示。(控制台也会显示业务异常栈踪迹。)
图 60. 测试结果失败
- 停止服务器。

 |

|
结束语
在本系列的这一部分中,我们为您显示了 JSF 如何使用 RAD性质的任何业务层代码。特别是,我们为现有的 Enterprise JavaBean 集设计了一个 JSF 前台。另外,我们还使用 Quick Edits视图来将 Action Handling 添加到我们的 JSF 应用程序中,同时也添加了错误处理。在本系列的结束篇中,我们将编写一个基于 JSF 的Web 服务客户端来显示如何在集成场景中使用 JSF。
致谢
作者真诚感谢 Beverly DeWitt 对本文所做出的贡献。
下载 | 名字 | 大小 | 下载方法 |
|---|
| JSFArticleSeriesP4.zip | 12.2 MB | HTTP |
参考资料
关于作者  | |  |
Roland Barcia Bar
是位于纽约/新泽西州 Metro 区的 IBM Software Services for WebSphere 的 IT 顾问专家。
|
对本文的评价
|  |