二、建立一个JSF Portlet
在这部分,我们将使用Oracle数据库作为数据源建立一个JSF应用程序,然后将这个JSF程序转换为portlet。这个JSF应用程序由一个使用SQL查询动态产生的DataTable组成。
在这部分,我们将使用Oracle数据库作为数据源建立一个JSF应用程序,然后将这个JSF程序转换为portlet。这个JSF应用程序由一个使用SQL查询动态产生的DataTable组成。
首先,在JDeveloper中选择File->New建立一个JDeveloper工程,然后使用在New Gallery wizard中的General->Application。指定一个工程名后,选择WebCenter应用程序作为应用程序模板。在建立完WebCenter工程后,所有的数据和资源都会在如图1的Applications Navigator中显示出来。这个应用程序由用于建立portlet的Portlets工程和用于建立JSF视图页的ViewController工程组成,portlets可以在这个工程中被嵌入。

图1 . WebCenter工程效果图
在这里我们将使用WebCenter框架中的JSF-Portlet桥来编写JSF应用程序,这就意味着JSF应用程序将是基于JSR168 portlets的。我们可以选择Tools->Project项来加入JSF-Portlet桥所需的库。我们还需要加入ADF Faces运行时库和Oracle JDBC库。
接下来,我们将使用如下的步骤在WebCenter框架中实现和发布JSF应用程序:
1. 在" Applications Navigator"中选择Portlets工程,并选择File->New
2. 在新Gallery模板中,选择Categories 中的Web Tier->JSF,然后选择JSF JSP项,单击OK。
3. 当JSF JSP模板启动后,单击Next,选择J2EE1.4作为Web应用程序的版本,然后再次单击Next。
4. 指定input.jsp作为文件名后,单击Next。
5. 在一个新的管制Bean中选择Automatically Expose UI Components,并指定PortletBean作为类名,然后单击Next。
6. 选择默认的tag库,JSF Core1.0和JSF HTML 1.0,然后单击Next。
7. 选择默认的HTML选择,然后单击Next。
8. 单击Finish按钮后,在Portlets工程中建立一个JSF页(也就是input.jsp)和一个faces-config.xml发布文件。
下面我们来建立一个portlet。一个portlet需要一个portlet.xml文件,因此,我们按如下步骤在Portlets工程中加入一个portlet.xml文件。
8. 单击Finish按钮后,在Portlets工程中建立一个JSF页(也就是input.jsp)和一个faces-config.xml发布文件。
下面我们来建立一个portlet。一个portlet需要一个portlet.xml文件,因此,我们按如下步骤在Portlets工程中加入一个portlet.xml文件。
1. 选择File->New
2. 在New Gallery wizard中,从Catagories菜单中选择Filter By->All Technologies and select General->Deployment Descriptors
3. 选择portlet.xml,并单击OK
图2显示了我们的JSF portlet应用程序的目录结构。

现在,我们准备在应用程序中加入JSF组件。在Component Palette中,选择JSF HTML,并将以下内容加入到input.jsp页中:
图2显示了我们的JSF portlet应用程序的目录结构。

图2 JSF Portlet应用程序的目录结构
现在,我们准备在应用程序中加入JSF组件。在Component Palette中,选择JSF HTML,并将以下内容加入到input.jsp页中:
1. 一个输出标签
2. 一个输入文本字段
3. 一个命令按钮
4.一个数据表
在JSF页中的文本字段指定一个SQL查询。当一个用户单击建立数据表命令时,PortletBean.java类中的commandButton_action方法被调用,然后一个数据表被动态地创建。PortletBean.java中的部分代码如下:package portlet.backing; ... ... public class PortletBean { .... .... public String commandButton_action() { ResultSet rs = null; try { InitialContext initialContext = new InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource)initialContext.lookup("java:comp/env/jdbc/OracleDBConnectionDS"); java.sql.Connection connection = ds.getConnection(); Statement stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs = stmt.executeQuery((String)inputText1.getValue()); dataTable1.setBorder(5); dataTable1.setCellpadding("1"); dataTable1.setVar("catalog"); HtmlOutputText headerComponent1 = new HtmlOutputText(); headerComponent1.setId("headerComponent1"); headerComponent1.setValue("CatalogId"); column1.setHeader(headerComponent1); HtmlOutputText headerComponent2 = new HtmlOutputText(); headerComponent2.setId("headerComponent2"); headerComponent2.setValue("Journal"); column2.setHeader(headerComponent2); HtmlOutputText headerComponent3 = new HtmlOutputText(); headerComponent3.setId("headerComponent3"); headerComponent3.setValue("Publisher"); column3.setHeader(headerComponent3); HtmlOutputText headerComponent4 = new HtmlOutputText(); headerComponent4.setId("headerComponent4"); headerComponent4.setValue("Edition"); column4.setHeader(headerComponent4); HtmlOutputText headerComponent5 = new HtmlOutputText(); headerComponent5.setId("headerComponent5"); headerComponent5.setValue("Title"); column5.setHeader(headerComponent5); HtmlOutputText headerComponent6 = new HtmlOutputText(); headerComponent6.setId("headerComponent6"); headerComponent6.setValue("Author"); column6.setHeader(headerComponent6); HtmlOutputText column1Text = new HtmlOutputText(); column1Text.setId("htmlOutputText1"); ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.ID}"); column1Text.setValueBinding("value", vb); column1.getChildren().add(column1Text); HtmlOutputText column2Text = new HtmlOutputText(); column2Text.setId("htmlOutputText2"); vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.JOURNAL}"); column2Text.setValueBinding("value", vb); column2.getChildren().add(column2Text); HtmlOutputText column3Text = new HtmlOutputText(); column3Text.setId("htmlOutputText3"); vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.PUBLISHER}"); column3Text.setValueBinding("value", vb); column3.getChildren().add(column3Text); HtmlOutputText column4Text = new HtmlOutputText(); column4Text.setId("htmlOutputText4"); vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.EDITION}"); column4Text.setValueBinding("value", vb); column4.getChildren().add(column4Text); HtmlOutputText column5Text = new HtmlOutputText(); column5Text.setId("htmlOutputText5"); vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.TITLE}"); column5Text.setValueBinding("value", vb); column5.getChildren().add(column5Text); HtmlOutputText column6Text = new HtmlOutputText(); column6Text.setId("htmlOutputText6"); vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{catalog.AUTHOR}"); column6Text.setValueBinding("value", vb); column6.getChildren().add(column6Text); ResultSetDataModel dataModel = new ResultSetDataModel(); dataModel.setWrappedData(rs); dataTable1.setValue(dataModel); } catch (SQLException e) { System.out.println(e.getMessage()); } catch (javax.naming.NamingException e) { System.out.println(e.getMessage()); } return null; } }
在输入文本框中被指定的SQL查询在commandButton_action方法中运行,并为数据表产生一个结果集。下面将显示input.jsp的全部代码:
<%@ page contentType="text/html;charset=windows-1252"%> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> <f:view> <h:form id="form1"> <h:outputLabel value="SQL" binding="#{backing_input.outputLabel1}" id="outputLabel1"/> <h:inputText id="inputText1" binding="#{backing_input.inputText1}"/> <h:commandButton id="commandButton1" value="Create Data Table" binding="#{backing_input.commandButton1}" action="#{backing_input.commandButton_action}"/> <h:dataTable id="dataTable1" rows="5" binding="#{backing_input.dataTable1}"> <h:column id="column1" binding="#{backing_input.column1}"/> <h:column id="column2" binding="#{backing_input.column2}"/> <h:column id="column3" binding="#{backing_input.column3}"/> <h:column id="column4" binding="#{backing_input.column4}"/> <h:column id="column5" binding="#{backing_input.column5}"/> <h:column id="column6" binding="#{backing_input.column6}"/> </h:dataTable> </h:form> </f:view>
接下来我们应为每一个动态JSP组件指定一个ID。如果我们不这么做,JSF框架将在portlet标记中产生重复的ID,当portlet运行时会产生以下错误:
编辑web.xml和portlet.xml文件,在web.xml中加入以下context-param结点:
按着如下步骤编辑portlet.xml文件:
Duplicate component ID … found in view.
An internal error has occurred in method getMarkup()编辑web.xml和portlet.xml文件,在web.xml中加入以下context-param结点:
<context-param> <param-name>javax.faces.application.CONFIG_FILES</param-name> <param-value>/WEB-INF/faces-config.xml,/WEB-INF/portlet.xml</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param>
在web.xml中加入以下ADF Faces filter过滤器:
<filter>
<filter-name>adfFaces</filter-name>
<filter-class>oracle.adf.view.faces.webapp.AdfFacesFilter</filter-class>
</filter>
按着如下步骤编辑portlet.xml文件:
1. 使用<portlet></portlet>结点指定一个portlet。
2. 指定一个portlet类oracle.portlet.server.bridges.jsf.FacesPortlet
3. 为默认页指定一个结点<init-param/>,当portlet运行时这个页被显示。代码如下:
<init-param>
<name>DefaultPage.view</name>
<value>/input.jsp</value>
</init-param>
4. 为BridgeLifecycleListeners listener类指定一个<init-param/>结点,代码如下:
<init-param>
<name>BridgeLifecycleListeners</name>
<value>
oracle.portlet.server.bridges.jsf.adf.ADFFacesBridgeLifecycleListener
</value>
</init-param>
下面将显示portlet.xml文件的完整内容:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <portlet-app version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"> <portlet> <portlet-name>DataTablePortlet</portlet-name> <display-name>DataTable Portlet</display-name> <portlet-class>oracle.portlet.server.bridges.jsf.FacesPortlet</portlet-class> <init-param> <name>DefaultPage.view</name> <value>/input.jsp</value> </init-param> <init-param> <name>BridgeLifecycleListeners</name> <value> oracle.portlet.server.bridges.jsf.adf.ADFFacesBridgeLifecycleListener </value> </init-param> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <supported-locale>en</supported-locale> <portlet-info> <title>DataTable Portlet</title> <short-title>datatable</short-title> </portlet-info> </portlet> </portlet-app>