test
作者:Duncan Mills,Oracle Corporation
2006 年 4 月
Ajax(异步 JavaScript 和 XML)与基于组件的 JavaServer Faces (JSF) 方法的结合将带来令人激动的前景:高互动组件,通过它可以构建具桌面级互动性的应用程序。
在本文中,我们将讨论如何连接现有的 Ajax 组件以使用由 Oracle 应用程序开发框架 (ADF) 抽象提供的数据。这一任务有点复杂,因为依据定义,Ajax 组件需要访问普通请求响应周期之外的 ADF 绑定。
本示例使用了来自 java.net 的一个现成 Ajax 控件,它提供了类似于 "Google Suggest" 的自动提示功能。当在域中输入文字时,将弹出一个列表,其中提供了几个点击率排名前列的匹配项。然后您可以选择一项来自动填充该域。下面是该示例应用程序运行时的屏幕截图:
该页本身提供了针对 Employees 的按例查询屏幕。姓氏域具备自动提示功能。
本文假定您熟悉 ADF 框架以及 ADF 数据绑定的几个要点,如 PageDef 文件的编辑。如果您未达到这一要求,请访问 ADF 开发人员指南,了解 ADF 数据绑定的详细信息和工作原理。
为求简便,在本例中我们将使用 ADF 业务组件作为业务服务。其中,该 Ajax 组件将连接到的方法是通过 ADF 业务组件应用模块公开的。但这一做法适用于由 ADF 模型绑定公开的任何方法,如由 EJB 会话 bean 或 web 服务公开的方法。但要注意,Ajax 组件中的每一次按键都将调用绑定的方法。始终考虑数据集是否足够小,能够缓存由 JSF 管理的 bean 而不用每次都从模型中获取。
在本例中使用标准 Oracle HR 演示模式。在 Model 项目中:
SELECT DISTINCT EMPLOYEES.LAST_NAME FROM EMPLOYEES WHERE upper( EMPLOYEES.LAST_NAME) like :searchPrefix ORDER BY EMPLOYEES.LAST_NAME ASC
将绑定变量 searchPrefix 定义为字符串,并调用这个视图对象 UniqueEmployeeNames
转换到 ViewController 项目并执行下列步骤:
到这里我们已经成功创建一个功能齐全的 Query-By-Example 页面。运行该页面并点击 Find 按钮,在 LastName 域中输入 "King" 并点击 Execute,如使用的是默认的 HR 数据集,将显示两行。
本例中要使用的 JSF 组件是开放源的,可以通过 java.net 获取。该组件可结合 JDeveloper 和 OC4J 在运行时期间正常工作,但在设计时期间不能正常工作,因为它使用一些专用的钩子连入 Sun 的 JSF 开发环境,而 JDeveloper 中没有这些钩子。为解决这一问题,我们针对本示例专门打包了一个不含这些 Sun 特定引用的组件版本。这已足够展示本文要讨论的技术,这些技术是通用的,可用于任何需要访问由 ADF 管理的数据的 Ajax 组件。
下面我们将使用自动提示组件更换现有的 LastName 域。
重要注意事项:
您会发现我们所使用的用于演示目的的 CompletionField 组件不能在可视化编辑器中正常显示,但是它可在运行时期间正常显示。这是该组件而不是 JDeveloper 的问题。下面我们要在 ADF 业务组件(或您的 EJB 会话 Bean)中创建一个方法,该方法将根据由 Ajax 组件提供的输入前缀返回域提示值列表。
import java.util.ArrayList;
import java.util.List;
...
public List<String> autocompleteFindUniqueNames(String searchString){ UniqueEmployeeNamesImpl hits = this.getUniqueEmployeeNames1(); hits.setNamedWhereClauseParam("searchPrefix",searchString.toUpperCase()+ "%"); hits.setRangeSize(5); hits.executeQuery(); ArrayList resultset = new ArrayList((int)hits.getEstimatedRowCount()); for (Row row:hits.getAllRowsInRange()){ resultset.add((String)row.getAttribute("LastName")); } return resultset; } 这一方法只是一个简单示例,它使用 Ajax 控件传递的前缀值来重新执行 UniqueEmployeeNames 查询(视图对象)。请注意,该方法从匹配行返回含 LastName 属性的字符串列表,且该查询(在本中例中)只限取前五个匹配项返回到该控件。
在通过应用程序模块的数据模型屏幕公开视图对象后,将自动创建 getUniqueEmployeeNames1()方法
下面我们要实施自动填充事件,将 Ajax 组件产生的事件与我们刚创建的服务方法关联。要完成这一工作,我们需要先用几步创建一个 DataBinding 定义(PageDef 文件)和一个保存事件代码的管理 bean。
通常,Ajax 组件将向一个 URL 发出 GET 请求,而该 URL 区别于 JSF 页以 POST 方式请求的普通 URL。因此,它需要自己的 PageDef 文件形式的绑定定义,用于通知框架 Ajax 事务所要求的绑定。
<xml version="1.0" encoding="UTF-8" > <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.36.73" id="ajaxSearchPageDef" Package="com.groundside.view.pageDefs"> </pageDefinition>
请注意, id 设置为匹配 pagedef 文件的名称, package 应该匹配实际位置 (根据您的项目修改)。
<xml version="1.0" encoding="UTF-8" > <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="10.1.3.36.73" id="ajaxPageDef" Package="com.groundside.view.pageDefs"> <bindings> <methodAction id="autocompleteFindUniqueNames" InstanceName="EmployeeServiceDataControl.dataProvider" DataControl="EmployeeServiceDataControl" MethodName="autocompleteFindUniqueNames" RequiresUpdateModel="true" Action="999" ReturnName="EmployeeServiceDataControl.methodResults.
EmployeeServiceDataControl_dataProvider_autocompleteFindUniqueNames_result"> <NamedData NDName="searchString" NDType="java.lang.String"/> </methodAction> </bindings> </pageDefinition><xml version="1.0" encoding="UTF-8" > <Application xmlns="http://xmlns.oracle.com/adfm/application" version="10.1.3.36.73" id="DataBindings" SeparateXMLFiles="false" Package="com.groundside.view" ClientType="Generic"> <pageMap> <page path="/employeeSearch.jsp" usageId="employeeSearchPageDef"/> <page path="/faces/ajax-autocomplete" usageId="ajaxPageDef"/> </pageMap> <pageDefinitionUsages> <page id="employeeSearchPageDef" path="com.groundside.view.pageDefs.employeeSearchPageDef"/> <page id="ajaxPageDef" path="com.groundside.view.pageDefs.ajaxPageDef"/> </pageDefinitionUsages> <dataControlUsages> <BC4JDataControl id="EmployeeServiceDataControl" Package="com.groundside.model" FactoryClass="oracle.adf.model.bc4j.DataControlFactoryImpl" SupportsTransactions="true" SupportsFindMode="true" SupportsRangesize="true" SupportsResetState="true" SupportsSortCollection="true" Configuration="EmployeeServiceLocal" syncMode="Immediate" xmlns="http://xmlns.oracle.com/adfm/datacontrol"/> </dataControlUsages> </Application>Ajax 组件使用的绑定信息已经配置完成,但我们需要稍稍改动 web.xml 以保证针对 Ajax 请求调用 ADF Binding Filter。
在 2-iv 步中,我们将 textfield-jsf 组件设为绑定引用 #{ajaxHandler.searchNameComplete}。现在我们要创建该管理 bean 和 searchNameComplete 方法,searchNameComplete 方法将调用应用模块 autoCompleteFindUniqueNames 方法。
<managed-bean> <managed-bean-name>ajaxHandler</managed-bean-name> <managed-bean-class>com.groundside.view.handler.AjaxHandler</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>name</property-name> <property-class>oracle.binding.BindingContainer</property-class> <value>#{bindings}</value> </managed-property> </managed-bean> 最后我们将实现一个当用户在自动填充组件键入内容时要调用的方法。与我们在 4.1-xi 中为其创建映射的 URL 类似,这一方法特定于要使用的组件。
public void emailValidator(FacesContext context,
String prefix,
CompletionResult result) { }
我们在 2-iv 步中定义的绑定将调用这一方法,通过 prefix 参数传递用户输入的字符。我们将使用它来填充组件也会传入的 CompletionResult 对象。
import com.sun.j2ee.blueprints.bpcatalog.ajax.components.CompletionResult;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import oracle.binding.BindingContainer;
import oracle.binding.OperationBinding;
01: public void searchNameComplete(FacesContext context, String prefix, CompletionResult result) { 02: if (prefix != null && prefix.length() > 0) { 03: BindingContainer bc = getBindings(); 04: if (bindings != null) { 05: OperationBinding ob =bc.getOperationBinding(" autoCompleteFindUniqueNames "); 06: Map params = ob.getParamsMap(); 07: params.put("searchString", prefix); 08: List<String> resultset = (List)ob.execute(); 09: result.addItems(resultset); 10: } 11: } 12: }
从 Ajax 事件访问 ADF 方法看起来很复杂,但可将其分解为下面几个简单的基本任务:
对于任何 Ajax 组件,以上四个任务类似。不同之处在于组件向其提交请求的 URL 和实际事件处理程序本身的实施。
您可从此处下载包含本文中所用的可正常运行的示例的整个工作区。下载这一示例,在编译和运行前先创建到 HR 模式 "hr" 的数据库连接。
drmills v1.2 2006 年 4 月 20 日
热门下载 | ||