While Web-based technology provides a cost-effective means to deploy, administer, and access business applications, developers must design such applications to effectively meet today's demanding business needs. A big problem for typical Web applications centers on dynamic Web page generation, coupled with the inability to avoid content regeneration when user interactions force a page refresh.
As a solution, the IBM® FacesClient Components feature client-side processing coupled with a client-side data model to reduce server and network loads and user wait times. The result: richly interactive Web applications utilizing JavaScript for client-side processing and data structuring without browser or client upgrades.
In this article, we introduce the technology underlying FacesClient Components and describe how to build FacesClient Components-enabled portlet applications using the beta 1 version of the JSL (JavaScript Library) Emitter layer of the programming model. To help align the development group with the customer, we employ a scenario-based design approach to drive FacesClient Components technology development and features. To demonstrate the advantages of FacesClient Components-enabled applications compared to typical Web applications, we present the IBM® Software Group (SWG) System House Customer Loyalty (CL) scenario.
In Parts 2 and 3 of this series, we will address the challenges of using FacesClient Components in a portal environment and methods for updating the client-side data model without refreshing the portal page. Note: During the prototype's development and implementation phase, the programming model's tooling and JavaServer Faces (JSF) layers were not mature enough to support development of the prototype. In Part 4, we will describe how to use the JSF programming layer and tooling to develop the CL prototype.
The FacesClient Components advantage
Applets, Flash, and ActiveX controls provide client-side processing functionality similar to FacesClient Components. Applets and ActiveX controls, however, are not universally accepted because of development model, security, and performance issues. Applets and Flash, moreover, require client-side plugins, a requirement the JavaScript-based FacesClient Components do not need.
Developers use FacesClient Components, an on-demand JavaScript framework, to achieve server, network, and user productivity and performance goals while maintaining a small footprint. Current best practices dictate that a Web application be broken into a model, a view, and a controller (MVC). Under this structure, the server acts as the container for the model and the controller, then outputs a view interpreted by the client-side Web browser. Abstractly, one FacesClient Components benefit is the ability to distribute the elements of the model and controller to the client without requiring a special browser plugin or executable.
FacesClient Components provide the tools for the server to distribute an acceptable subset of the model to the client. It also keeps the tools separate from a client-side controller such that the Web client generates the final view for the user from those two artifacts, without any further interaction with the server. That allows for an application model more similar to the thick-client distributed applications of previous years, but with platform portability and no need for a client install. For instance, when you download a page for viewing complex stock information and statistics, you conceptually download two objects:
- The specific stock data
- The user interface (UI) widgets and bindings to that data for generating the visuals and UI
That client-side MVC lets the client refresh data, getting only updated stock information without causing a refresh of the markup. Such a model taxes the server less and also allows for richer, more responsive interactions on the client.
FacesClient Components architecture and programming model
A key FacesClient Components component is its structured data model that supports dynamic data manipulation -- meaning that data can be manipulated on the client, either by the user or through a Web service or other Web-based update mechanisms, without a page-refresh. The FacesClient Components framework also provides rich user interface controls so that manipulations of the view can occur without interaction with the server (for example, Twisty, TreeView, DataGrid, ListView, TabbedPanel, DatePicker, GraphDraw, and Dialog). Lastly, FacesClient Components provide a framework for dynamic late binding between controls and data on a page, letting developers design portal pages to automatically share data on the client side.
When designing a FacesClient Components-enabled page or portlet, you must determine the data set, model the data, and stream the data suitable for the client onto the page or portlet. You then add controls to the portlet and bind the controls with the data on the browser dynamically. When users download a FacesClient Components-enabled Web page, they receive the data set and controls embedded in the page. Web page users utilize the controls (rich user interface) to work with the data set and perform general actions such as sorting, paging, and filtering on the client-side. If a user accessed a non-FacesClient Components Web page, these operations would require several roundtrips to the server, increasing the application's response time and server and network loads.
The FacesClient Components JSL serves as the foundation of the FacesClient Components programming model, as shown in Figure 1. The JSL contains a set of UI control widgets -- data grids, tabbed panels, trees -- to dynamically bind to data models on a page. Developers use available APIs to exploit advanced FacesClient Components features. Additionally, the JSL contains JavaScript versions of the Eclipse Modeling Framework (EMF) core classes.
Figure 1. FacesClient Components programming model

The JSL Emitter-layer contains a Java-based library of helper classes used to create FacesClient Components-enabled portlet or servlet pages. Emitters write JSL code onto the portlet or servlet pages. Thus, using the Emitter layer, you can write Java code to build complex pages that use the JSL.
The programming model's JSF component layer is based on an emerging standard called JSR 127. In this layer, a JavaServer Pages (JSP) custom tag library is used for expressing a JSF interface within a JSP page. The JSL Emitter layer maps one to one with the JSP Tag Library layer. Ease of use being the primary goal, the JSF component layer lets JSP-based page developers make use of FacesClient Components with simple tags.
Visual tooling to support the JSF layer represents the last level of the FacesClient Components programming model. JSF tooling and runtime debuted in WebSphere Studio Application Developer (WSAD) 5.1.2. The next version of the JSF tooling and runtime will be presented in Rational Application Developer (RAD) 6.0.
The process for building FacesClient Components portlet applications
The FacesClient Components portlet application-building process includes three steps. When designing a FacesClient Components-enabled page or portlet:
- Determine the data set needed, then model the data
- Identify the FacesClient Components user interface components (controls) for data model presentation
- Establish the event model needed to support the user's interaction with the data model
The CL scenario prototype, discussed below, illustrates the development process and the FacesClient Components framework. Our goal is to provide a rich portal-based environment where users view, navigate, and graphically display their banking accounts and investment portfolios with minimal page refreshes and roundtrips to the server.
In step one for building FacesClient Components-enabled portlet applications, you determine the data set needed and model the data. Using FacesClient Components, you build and deploy a structured data model to a portlet's client-side GUI. With the FacesClient Components constructs, you model data on the server and route the data model and instance data to the browser where various FacesClient Components controls use it for presentation purposes. FacesClient Components include APIs that manage how portlets or pages read from and write to the data model. Additionally, FacesClient Components contain APIs for writing software that reconciles changes made to the data model on the server with the client-side representation of the data model, and vice versa.
The CL prototype is used to demonstrate the data model development process. Users access the portlets to view and navigate their banking accounts, the transactions for each account, and portfolios and positions in each portfolio. Figure 2 shows the application's UML (Universal Modeling Language) model of the data set.
Figure 2. Data model

The data model's root node, CustomerAccountData object, contains a single customer. Also, the object holds a reference to a StockData object, which acts as a placeholder to send and receive data from the Web service. Each customer object may contain zero or more banking accounts and portfolios. The banking account and portfolio objects may contain zero or more banking transactions and positions, respectively. Finally, each position object has a stock object.
FacesClient Components incorporate the infrastructure needed to convert the Java classes shown in Figure 2 into browser-based JavaScript objects. FacesClient Components mechanisms used to develop the data model and instance data build upon the EMF and Web Data Object (WDO) concepts. A FacesClient Components component creates the JavaScript version, known as Web Data Objects for JavaScript (WDO4JS), of the WDO for Java (WDO4J). Note, as described in the FacesClient Components Developer's Guide, the terms WDO and Service Data Objects (SDO) are somewhat synonymous (see Resources).
To create the WDO4JS, you first create an ECore, an EMF model that describes data structures such as the data instance used by FacesClient Components. An ECore can be emitted by a few different types of Rational tooling, the WSAD FacesClient Components tooling add-on, or manually created. Listing 1 shows an ECore sample created for the CL scenario. Note that the ECore elements correspond to the classes in the data set defined in Figure 2.
Listing 1. Sample
ECore file...
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
name="Customer"
nsURI="http:///com/ibm/odcb/wdo4jsmediators/portfolio.ecore"
nsPrefix="" >
<eClassifiers xsi:type="ecore:EClass" name="Customer">
<eAttributes name="_CustomerId" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_LastName" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>....
<eReferences name="_PortfolioAccounts" eType="#//PortfolioAccount"
upperBound="-1" containment="true" />
<eReferences name="_BankingAccounts" eType="#//BankingAccount"
upperBound="-1" containment="true" />
<eReferences name="_PlaceHolderStock" eType="#//Stock" lowerBound="1"
upperBound="1" containment="true"/>
<eAttributes name="_PlaceHolderBankingAccountNumber" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eAttributes name="_PlaceHolderPortfolioAccountNumber" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EInt"/></eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="BankingAccount">
<eAttributes name="_BankingAccountNum" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eAttributes name="_AccountType" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_Balance" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EFloat"/>.....
<eClassifiers xsi:type="ecore:EClass" name="BankingTrans">
<eAttributes name="_TransactionNumber" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//ELong"/>
<eAttributes name="_Type" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_Amount" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EFloat"/>
<eAttributes name="_DateExecuted" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_Purpose" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eReferences name="_Customer" eType="#//Customer" lowerBound="1" />
<eReferences name="_BankingAccount" eType="#//BankingAccount"
lowerBound="1" eOpposite="#//BankingAccount/_BankingTrans"/>
</eClassifiers> <eClassifiers xsi:type="ecore:EClass"
name="BankingTransCategory">
<eAttributes name="_TransCategoryID" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_Amount" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EFloat"/>
<eAttributes name="_Purpose" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eClassifiers xsi:type="ecore:EClass" name="PortfolioAccount">
<eAttributes name="_PortfolioName" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
lt;eAttributes name="_PortfolioAccountId" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
... <eClassifiers xsi:type="ecore:EClass" name="Position">
<eAttributes name="_PositionNum" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eAttributes name="_Shares" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
<eAttributes name="_Price" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EFloat"/>
... <eClassifiers xsi:type="ecore:EClass" name="Stock">
<eAttributes name="_Symbol" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_CompanyName" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString"/>
<eAttributes name="_CurrentPrice" eType="ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EDouble"/>...</ecore:EPackage>
...
|
Next, using a FacesClient Components utility called WDO4JSEMapGen, create a mapping, called an EMap, of the application Java classes to the EMF class definitions. WDO4JSEMapGen uses the ECore model and the Java classes outlined in Figure 2 to produce the project EMap.
The last thing you do now is execute the WD4JSMediator utility, which uses the ECore and EMap files to generate mediator files -- a FacesClient Components concept used at runtime to convert application classes into JavaScript code for creation of the client-side data model and data instance. Find procedures for creating an ECore and instructions for using WDO4JSEMapGen and WD4JSMediator utilities in the WebSphere FacesClient Components Developer's Guide (see Resources).
In step two of the process for building FacesClient Components-enabled portlet applications, you identify the FacesClient Components user interface components (controls) for data model presentation. The rich controls in FacesClient Components manage the graphical and textual presentation of the model (the view or look of the application data). FacesClient Components contain a rich control set such as Twisty, TreeView, DataGrid, ListView, TabbedPanel, DatePicker, GraphDraw, Web Services, and Dialog.
When used in concert with the data model, the controls create a richer user experience through client-side processing and fewer server roundtrips. FacesClient Components include an overall page runtime containing features to allow late binding of controls to the data. Utilizing the framework page runtime and late binding characteristics, you'll wire the controls to work in a coordinated fashion with each other as they react to data changes and redraw as needed without causing page refreshes or server roundtrips.
In general, for each control you define the control's main settings (for example, how many rows to display for a DataGrid, a TabbedPanel's height and width, and so on), client-side events handlers, and data model mapping parameters for each page.
The primary controls to construct the CL scenario prototype comprise:
DataGridTabbedPanelGraphDrawWebService
Figure 3 shows the prototype where DataGrid and GraphDraw are used in a portlet to display a user's banking account transactions. Utilizing the DataGrid control, a user sorts, pages, and filters the transactions on the client-side; that is, in the browser window. To sort the DataGrid's content, the user simply clicks one of the column headers. Selecting one of several expense-purpose choice options listed in the combo box, a user may filter the transactions.
Figure 3. Data model

Figure 4 shows a Web service form displayed in a TabbedPanel, a data model representation, and WebService. A CL Portfolio portlet uses the WebService control to communicate with a WebService for timely updates. In essence, the WebService control updates the data model within the portlet page without refreshing the entire page. The ability to move data elements in and out of the data model lets you create portlets that offer users a richer experience. Two groups of controls are mapped to the data model, the WebService's inputs and outputs and the WebService form's input text and output text fields.
A FacesClient Components central concept concerns the relationship between data and controls. In the instance displayed in Figure 4, each control is independently mapped to the model.
Figure 4. WebService
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
As Listing 2 below shows, you need only a few lines of code to set up the WebService. After declaring the WebService (WS), the WS attributes initialize the control:
- The customer model name binds the results of the service call.
- WSDL URL is the invoked
WebService's URL. - WS alias invokes the
WebService. - WS operation is the name of the operation invoked in the targeted
WebService.
The WebService form's input and output text fields shown in Figure 4 match up with the WS AddInputParameter and AddOutputParameter, respectively.
Listing 2. WebServices emitter
...
WebServicesEmitter WS = new WebServicesEmitter();
WS.Init("Customer",
"http://www.myWebServices.com/HomePage/WebServices/StockQuotes.asmx?WSDL",
"stockWebService", "GetStockQuotes");
String StockID = E.getExportIDByObject(customerAccount.getPlaceHolderStock());
WS.AddInputParameter (StockID, "Symbol");
WS.AddOutputParameter(StockID, "CurrentPrice", "StockQuote");
WS.AddOutputParameter(StockID, "CompanyName", "CompanyName");
WS.AddOutputParameter(StockID, "LastUpdated", "LastUpdated");
...
|
An event is an announcement or notification in reaction to a stimulus; for example, a change in state or a user clicking the mouse while viewing a document. The event handler receives control when the related event occurs. In the case of FacesClient Components, the event handler updates the data model as needed in response to the user's input. The event handlers and binders in FacesClient Components equate to the controller in an MVC model. In FacesClient Components, event handlers are rich objects that have formal interfaces and, if required, the capacity to preserve state across invocation.
In the third step for building FacesClient Components-enabled portlet applications, you'll establish the event model needed to support the user's interaction with the data model. The user interaction patterns described in the CL Scenario requirements are:
- Using portlets, each user views and navigates their banking accounts, account transactions, portfolios, and portfolio positions
- Given a data structure that encompasses all of these elements in one data model, you can create an event model that maximizes the benefits of FacesClient Components by creating seamless interactions between different parts of the application
The DataGrid and Graph controls provide efficient means of displaying each data item (for example the banking accounts, transactions, portfolios, and positions) within its own portlet. Utilizing the DataGrid and Graph GUIs in a mode where the controls share the same data model, a user could navigate, sort, page, and graph her data without causing a page refresh. As a result of sharing the same data model, the Graph automatically updates if the user updated a quantity in the DataGrid.
You can further increase the productivity of the portal user working with the banking and portfolio portlets by letting the user send information from one portlet to another. For example, when a user selects a banking account in the DataGrid of one portlet, the DataGrid and Graph of a second portlet automatically update to display the user's transactions corresponding to the selected banking account. Each FacesClient Components control has control-to-data event handlers specific to its representation of data. For instance, the DataGrid includes three supported control-to-data event handlers:
OnHighlightOnSelectOnUnselect
The OnHighlight event fires when a row in a DataGrid is highlighted. OnSelect and OnUnselect, for their part, fire when the user selects and unselects a row, respectively.
An additional control-to-control event handler is needed, however, to support the inter-portlet communication example. SelectAndActivate and SelectAndSet, featured control-to-control event handlers in FacesClient Components, create responses to a user's GUI interactions. The SelectAndActivate event, when fired, acquires an object or reference to an object selected in one control, and sets that same object as the root for another control. SelectAndSet event changes or sets a dataset's value based on a selection in a control. For example, when a user highlights a row in a portlet containing a banking account DataGrid, the account number is set and displayed in another portlet.
The portlet-to-portlet interaction and communication described in the example above represents the interaction pattern of the banking portion of the CL Scenario. Figure 5 shows a screen shot of the banking portlet-application implementation, including two portlets: eBank Accounts and eAccounts Details. The eBank Accounts portlet contains a user's bank accounts displayed within a DataGrid control. The data model for this portal page contains the user's banking accounts and transactions for each account. The DataGrid for the eBank Accounts portlet is bound to the user's banking accounts data. A user clicking on the account link in the highlighted row of the Banking Accounts DataGrid causes the account's transactions to be displayed in the eAccounts Details portlet DataGrid. As a result of the user's action, a graph showing a user's expense distribution displays in the Graph control. The transaction's rendering occurs without a browser refresh or roundtrip to the server; rather, it is the result of a client-side update. You can view the rendering as a client-side click to action. To complete a similar scenario with a non-FacesClient Components portlet application, a user would incur the cost of a roundtrip to the server and a page refresh, thus increasing the application's response time and server and network loads.
Figure 5. Bank accounts and account details

To support the client-side click to action, you must incorporate the SelectAndSet control-to-control event handler into the event model for the portal page. A user clicking on the account link in the highlighted row of the Banking Accounts' DataGrid causes the DataGrid control in the eAccounts Details portlet to redirect to the new bank account transactions listed in the page data model. Also, the Graph control in the portlet redirects to the expense purposes of the transactions. Thus, bindings to the data model for the eAccounts Details DataGrid and Graph control are dynamically changed.
This article's previous sections introduced portions of the CL prototype as a tutorial aid for use in explaining FacesClient Components. This section, for its part, addresses the entire prototype. The CL prototype is a banking account and portfolio management portlet application in which users access portlets to view and navigate their banking accounts, account transactions, portfolios, and portfolio positions. The portlet application's main components comprise the Accounts portal pages, which contain the portlets for viewing and navigating a user's banking and investment positions.
The FacesClient Components-enabled banking-account portal page shown in Figure 6 was constructed using the DataGrid control to display banking accounts and transactions for each account. The eAccount Details portlet was built with a DataGrid and Graph controls to display bank account transactions in both table and graphical form. Customers may utilize the transfer funds portlet to move funds between accounts.
Additionally, the page contains an IBM MPEG-4 Player applet so users can access a video tutorial on how to make the most of the page. The data model for the CL prototype portlet application was constructed from the data set shown in Figure 2.
With this simple yet powerful page, a user can sort, page, and filter her banking transactions on the client side. Through the interaction between the controls, a user can select a bank account in the eBank Account portlet DataGrid and cause the eAccount Detail portlet to display the transactions for the selected bank account. A customer may filter the transactions by selecting one of several expense purpose choice options listed in the combo box.
Figure 6. Banking portlet application
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
Executing a funds transfer through the eTransfer Funds portlet results in a series of prompts that lead the customer through the transfer process (see Figure 7). The component business logic that executes the transfer resides on the backend server. After completion of the backend transaction, the customer is notified that the data model on the client-side is updated. A successful funds transfer between accounts generates at least four data model changes. Each account balance is revised and a transaction is created for each account. The new transaction objects merge into the set containing the transactions for the bank accounts involved in the funds transfer. Updating the data model automatically triggers an update of all the controls bound to the modified data elements. Note that the data exchange between the FacesClient Components-enabled browser and the backend server occurs without a page refresh. We will discuss the underlying details supporting the data exchange's completion in Part 3 of this series.
Figure 7. Funds transfer

The DataGrid, Graph, and Applet controls, along with the form's input text fields, are independently mapped to the data model. The eBank Account portlet DataGrid is bound to the list of banking accounts owned by the customer. A selected banking account's transactions are bound to the eAccount Detail portlet DataGrid and Graph controls. The eBanking Help portlet Applet control is bound to the list of image URLs off the MPEG4Root.
As mentioned above, you can view FacesClient Components-enabled page design as a set of control-to-model relationships. Controls on the page share the same data model; therefore, all controls bound to a data item are automatically updated when the shared data changes.
The FacesClient Components-enabled portfolio portal page shown in Figure 8 was constructed using the DataGrid control to display the portfolio list and positions for each list. A WebService updates the current price of each position in a portfolio. The Graph control graphically displays the portfolio allocation. A three-panel Tabbed Panel control is used in the eSymbol Lookup and Trade portlet to display a symbol lookup WebService, a buy form, and a sell form.
Figure 8. Portfolio portal page
| XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width. |
The ePortfolioAccount portlet DataGrid and Graph controls are bound to the customer's portfolio list. Each portfolio's total values are calculated on the client side. FacesClient Components also lets you offload some calculations to the client side such as the total value calculation for each portfolio.
EMap provides the mechanism needed to facilitate client-side calculations. Using EMap, add JavaScript expressions for dynamic client-side calculation. The client-side calculation, referred to as a Calculated Attribute, is executed in the context of the object instance on the browser. An EMap sample file shown in Listing 3 defines the Calculated Attribute used to compute the each portfolio's total values. To do so, you must sum up the value of the positions in the portfolio. The calculatePortfolio JavaScript function aggregates the value of all the positions in the portfolios.
Listing 3. EMap sample
...
<EClassMap app_class="com.ibm.shcl.ciis.data.PortfolioAccountData"
eclass_name="PortfolioAccount"
export="PortAcct">
<EFeatureMap efeature_name="_PortfolioName"
export="PortName"
iD="true" Tget="getPortfolioName()" />
<EFeatureMap efeature_name="_PortfolioAccountId" export="PortAcctId"
iD="true" Tget="getPortfolioAccountId()" />
<EFeatureMap efeature_name="_DateOpened"
export="DateOpened"
iD="true" Tget="getDateOpened()" />
<EFeatureMap efeature_name="_Closed"
export="Closed"
iD="true" Tget="getClosed()" />
<EFeatureMap efeature_name="_Positions"
export="Positions"
iD="false" get="getPositions()" />
<EFeatureMap
efeature_name="_Customer"
export="Customer"
iD="false" get="getCustomerData()" />
<CalculateAttribute attribute_name="_calcTotal" export="Total"
iD="false" expression="calculatePortfolio(this)" type="float"/>
</EClassMap>
...
|
The ePortfolio Account Detail portlet DataGrid is bound to the positions of a selected portfolio. Each control independently maps to the shared data model. Through the interaction between the controls, a user selects a portfolio in the ePortfolio Account portlet DataGrid and causes the ePortfolio eAccount Detail portlet to display the positions for the selected portfolio. Utilizing the DataGrid control, a user sorts page positions on the client-side; that is, in the browser window. To sort the content of the positions, the user simply clicks on one of the column headers. The update link updates the prices in the data model using Web services without refreshing the entire page. ePortfolio Account and ePortfolio Account Detail portlet DataGrids automatically update as a result of sharing the same data model. Each portfolio's total value column shown in the ePortfolio Account portlet DataGrid and the value column for each position shown in the ePortfolio Account Detail portlet DataGrid are recalculated on the client side after all the stock prices update in the data model.
The eSymbol Lookup and Trade portlet provides the user with a symbol lookup capability using Web services (see Figure 4), and facilities for buying and selling stocks. Figure 8 highlights the buy stock form. The Get Quote button fetches the latest pricing information through a Web service for the stock the user plans to sell from her portfolio. The Account and Portfolio choice options are bound to the data model.
Executing a stock buy using the eSymbol Lookup and Trade portlet produces a series of prompts that lead the customer through the buy process. The component business logic that executes the stock buy resides on the backend server. After completing the backend transaction, the business logic notifies the customer and updates the data model on the client-side. At least four data model changes generate as a result of a successful stock buy:
- The balance of the bank account used for the stock purchase is revised and a transaction is created for the account.
- The new transaction object merges into the set containing the transactions for the bank accounts involved in the purchase.
- A new position object is created and spliced into the portfolio, which changes the portfolio's total value.
- Updating the data model automatically updates the controls bound to the modified data elements.
We used the FacesClient Components Programming Model's Emitter layer to construct the UIs shown in the banking and portfolio portal pages. Listing 4 shows a sample from the JSP used to construct the ePortfolio Account Detail portlet. The sample contains a DataGridEmitter code fragment that created a portfolio's position list. The useBean statements acquire the data objects. Once the JSP executes, the useBean statements create instances of the CustomerAccountData, PortfolioAccountData, PageContext, EventSelectAndActivateEmitter, and EventSelectAndSetEmitter classes. The CustomerAccountData class contains the customers', banking accounts, banking transactions, portfolios, positions, and stocks. The PortfolioAccountData class contains the customer's default startup portfolio. The EventSelectAndActivateEmitter and EventSelectAndSetEmitter classes set up the various events between the controls used in the portal page. The WDO4JSEmitter class shown in the JSP generates the model and data for the portal page. The CustomerAccountData instance data gathered from the useBean initializes the WDO4JS emitter.
Listing 4. JSP sample
...
<jsp:useBean id="firstPortfolioAccount"
class="com.ibm.shcl.ciis.data.PortfolioAccountData"
scope="request" /><jsp:useBean id="customerAccount"
class="com.ibm.shcl.ciis.data.CustomerAccountData"
scope="request" /><jsp:useBean id="ODCPCTX"
class="com.ibm.odcb.jrender.mediators.PageContext"
scope="request" />
<jsp:useBean id="accountSelectAndActivate"
class="com.ibm.odcb.jrender.emitters.EventSelectAndActivateEmitter"
scope="request" />
<jsp:useBean id="accountSelectAndSet"
class="com.ibm.odcb.jrender.emitters.EventSelectAndSetEmitter"
scope="request" />
<portletAPI:init/>
<%
PortletURLRewriter portletURLRewriter = new PortletURLRewriter(portletResponse);
InitializationEmitter Init = new InitializationEmitter(true, -1, "en", "",
portletURLRewriter,2, request.getServerName(), request.getServerPort());
Init.Export(out, ODCPCTX); WDO4JSEmitter E = new WDO4JSEmitter();
E.Init(customerAccount, customerAccount.getClass().getName(), null, true, true,
"Customer"); E.Export(out, ODCPCTX);
String customerAccountExportID = E.getExportIDByObject(customerAccount);
String portfolioAccountExportID =
E.getExportIDByObject(firstPortfolioAccount);%>......<%
// create a DataGrid to show transactions of an account
DataGridEmitter
DG = new DataGridEmitter();
DG.Init("Customer", portfolioAccountExportID, "Positions", true, 8);
DG.addColumn(new DataGridEmitterHelper("Symbol", "Symbol", true, "center",
10, false, false, false, null, null, 0, null, null));
DG.addColumn(new DataGridEmitterHelper("Shares", "Quantity", true, "center",
20, false, false, false, null, null, 2, null, null));
DG.addColumn(new DataGridEmitterHelper("Price", "Price", true, "center",
20, false, false, false, "US$", null, 2, null, null));
DG.addColumn(new DataGridEmitterHelper("Value", "Value", true, "center",
30, false, false, false, "US$", null, 2, null, null));
DG.addColumn(new DataGridEmitterHelper("PurchaseDate", "Purchase Date",
true, "center", 25, false, false, false, null,null, 0, null, null));
DG.setCssPrefix("ad");
DG.Export(out, ODCPCTX);
accountSelectAndActivate.addTargetEmitter(DG, null);%>
...
|
Portal technology provides a cost-effective means to deploy, administer, and access business applications. Use FacesClient Components and portal technology in concert to design Web-based applications that meet today's demanding business needs. With FacesClient Components, you can create richly interactive Web applications that achieve server, network, and user performance goals.
In this article, we briefly examined the FacesClient Components concept and discussed the potential use of FacesClient Components in portlet programming. We showed our CL prototype implementation and addressed how FacesClient Components makes portal pages more responsive, interactive, and attractive.
In the articles to follow, we'll look at the challenges developers face when creating FacesClient Components-enabled portlets and how to update the client-side data model without refreshing the portal page.
- Visit the WebSphere® site for software downloads, white papers, tutorials, training and much more that Web developers find handy.
- Learn more about Eclipse Modeling Framework (EMF) at http://www.eclipse.org/emf.
- Check out the Portlet Development Guide for more information on portlet messaging (developerWorks, March 2003).
- Find details on portal interfaces in the "FacesClient Components Developer's Guide" ( PDF) about WebSphere Portal V5.0 Portlet API (developerWorks, November 2004).
- Discover the advantages of using FacesClient Components to develop a rich-client, consumer self-service solution in a portal environment" (developerWorks, November 2004).
- Read a recent discussion of IBM FacesClient Components in the IBM eServer Magazine (June 2004).
- Browse for books on these and other technical topics.
- Visit the developerWorks Web Architecture zone for numerous articles covering various Web-based solutions.

Rod Henderson is an advisory software engineer in the IBM Software Group, System House, Advanced Technology Department located in Research Triangle Park, North Carolina. He received his PhD in electrical engineering from North Carolina A&T State University in 2002. Currently, he is actively involved in advanced technology projects in the areas of rich client technology, solution integration, and scenario-based software development. Contact Rod at rodhende@us.ibm.com.

Yongcheng Li is a senior software engineer for IBM in Research Triangle Park, North Carolina in the Software Group, System House, Advanced Technology group. He received a PhD in computer science from Tsinghua University in 1993. Currently, he is actively involved in advanced technology projects in the areas of rich client technology, data caching and replication, solution integration, and scenario-based software development. Send e-mail to Yongcheng at ycli@us.ibm.com.

Thomas McElroy is an advisory software engineer in the IBM Software Group's System House organization, located in Research Triangle Park, North Carolina. He has worked on Web-application technology projects for the last three years, including projects with the on-demand clients, edge-side includes, integrated solutions console, and a novel approach to a Java Database Connectivity (JDBC) caching proxy. Reach Thomas at tmcelroy@us.ibm.com.



