Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

FacesClient Components, Part 2: Use FacesClient Components in a portal environment

Detailing data models and instance data sharing and some best practice development approaches

Rod Henderson (rodhende@us.ibm.com), Advisory Software Engineer, IBM Software Group
Photo of Rod Henderson
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 Ph.D. in electrical engineering from North Carolina A&T State University in 2002. 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 (ycli@us.ibm.com), Senior Software Engineer, IBM Software Group
Yongcheng Li is a Senior Software Engineer in the IBM Software Group, System House, Advanced Technology Department located in Research Triangle Park, North Carolina. He received his Ph.D. in Computer Science from Tsinghua University in 1993. 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, Advisory Software Engineer, IBM Software Group
Photo of Thomas McElroy
Thomas McElroy is an Advisory Software Engineer in the IBM Software Group, System House, Advanced Technology Department located in Research Triangle Park, North Carolina. He has been working on Web application technology projects for the last three years, including projects with On-Demand Clients, Edge-Side Includes, Integrated Solutions Console, and a novel approach to a JDBC caching proxy. Reach Thomas at tmcelroy@us.ibm.com.

Summary:  In this second article in a series on developing and enabling portlet applications with FacesClient Components, meet the challenges of using FacesClient Components in a portal environment. Using the prototype from the first article of the series plus examples and code samples, the authors explain how data models and instance data are shared between multiple portlets on a portal page, and also describe some best practice development approaches.

View more content in this series

Date:  05 Jan 2005
Level:  Intermediate

Activity:  2705 views
Comments:  

Portlets and FacesClient Components are a winning combination. FacesClient Components can significantly enhance the user's experience with portlet applications since portals serve as a simple, unified access point to Web applications. With FacesClient Components, you can make portlets more responsive, interactive, and attractive.

Additionally, the benefits of portlet applications enabled with FacesClient Components include:

  • Lower consumption of server-side resources by offloading processing from the server to the client.
  • Fewer round trips to the server.

In this article (the second in a series), we will briefly describe the process for creating an FacesClient Components application and delineate the best practices for developers to follow when designing FacesClient Components portals. We also provide sample code that demonstrates how to implement these suggested best practices.

Create an FacesClient Components portlet application

As we noted in the first article of this series, a developer must complete several major tasks to create an FacesClient Components portlet application:

  1. Determine the dataset needed for the application and create an ECore file that contains a server-side Eclipse Modeling Framework (EMF) model of the dataset.
  2. Create a Service Data Objects (SDO) for JavaScript (SDO4JS) representation of the client data model. As described in the "FacesClient Components Developer's Guide" (see Resources), the terms Web Data Objects (WDO) and Service Data Objects (SDO) are somewhat synonymous.
  3. Generate a set of FacesClient Components mediator files in order to export the server-side model to the client browser as JavaScript.
  4. Finally, create the server-side model instance data needed to drive the application.

When a user accesses a Web page enabled with FacesClient Components, the server creates a stream of JavaScript and HTML and forwards it to the browser. As shown in Figure 1, the generated browser page may contain any or all of the following:

  • An SDO4JS set
  • The page runtime
  • A control library
  • The HTML used to lay out the page

Figure 1. Sample browser page
Sample browser page

The controls display the instance data enclosed in the SDO4JS objects. The page runtime defines the page FacesClient Components services, bindings, and event handlers. When used in concert with the data model, the controls and event handlers can create a richer experience for the user.


The portlet structure and FacesClient Components

Portals provide aggregation of content from such diverse sources as rich text, video, or XML; they also provide personalized services, such as user customization of layout and content. To accommodate the aggregation and display of this diverse content, a portal server must provide a framework that breaks the different portal components into portlets. Each portlet is responsible for accessing content from its source (for example, a Web site, database, or e-mail server) and transforming the content so it can be rendered to the client.

A portlet is developed, deployed, managed, and displayed independent of other portlets. Administrators and users create personalized portal pages by choosing and arranging portlets, resulting in Web pages that present content tailored for individuals or teams. A portlet has no control or even awareness of the order in which the output from all of the portlets on the page is written.

The developer decides the working set for the data model needed for an application and develops the data model which is then shared by the portlets in the portlet application. Within each portlet, controls may dynamically bind to the shared data model.

User productivity can increase when working with a portlet enabled with FacesClient Components. Why? Designers can wire portlets together through FacesClient Components, easily enabling users of multiple portlets to send information from one portlet to another on the client-side within the browser. FacesClient Components provides the mechanism for portlets to communicate with each other, exchanging data or messages in response to events captured by the event handlers.


Some FacesClient Components best practices

We mentioned previously that a portlet possesses "no control or even awareness of the order in which the output from all of the portlets on the page is written." When developers use FacesClient Components in a portlet application, this lack of awareness presents a challenge.

Order: Using FacesClient Components event handlers

The following scenario further highlights the issue. First, look at Figure 2. (You can also view a larger version of Figure 2.)


Figure 2. Bank accounts and account details
Bank accounts and account details

Using the banking example from the Customer Loyalty Scenario shown in Figure 2, portlet A (eBank Accounts) and portlet B (eAccount Details) are part of the same portal page. Portlet A displays information about a user's checking and savings accounts using a DataGrid control while portlet B displays information using a DataGrid about transactions that have occurred for one of the accounts over the last 30 days.

The DataGrids in each portlet share the same data model. That sharing enables a designer to wire them so when a user selects his checking account in A, the corresponding transaction details of the checking account are displayed in B without making a roundtrip to the server. To do this, the transactions portlet needs to obtain the corresponding account information when it displays the transaction details.

This is accomplished through FacesClient Components event handlers that take an object or reference in an object selected in one control and sets that same object as the root for another control. When the checking account is selected in portlet A, the action listener for the page is called, which dynamically changes the bindings for the DataGrid in portlet B from inside the browser.

As shown in Figure 1, several framework components are needed to enable a portal/Web page with FacesClient Components. If we use a JSP file to hold the generated SDO4JS set, page runtime, and control library, and include the file only in portlet A, then referencing the generated JavaScript components in portlet B will prove problematic.

As previously stated, a portlet has no control of the order in which the output from all of the portlets on the page is written. JavaScript is a linear language -- you must define objects before you use them. So, browser errors occur if portlet B is rendered before portlet A.

Order: Using FacesClient Components to generate the data model

To reap the benefits of FacesClient Components in portlet applications, portlets must share objects (for instance, the data model and data instance). If multiple portlets enabled with FacesClient Components are placed together on a page, the order in which the portlets are rendered is unknown. Therefore, a best practice for developers is to create and invoke FacesClient Components code to generate the data model on each portlet enabled with FacesClient Components regardless of the other portlets on the Web page.

This presents challenges when writing cooperating portlets that are required to share the same data and models. If two portlets use the same model name, they better refer to the exact same model structure; otherwise, the JavaScript emitted will cause errors in the browser.

Additionally, portal pages containing duplicate copies of the data model, instance data, page runtime, and control libraries will cause errors in the browser. To manage these issues, the designers of FacesClient Components incorporated fail-safe methods for developers.

Managing FacesClient Components resources

The FacesClient Components PageContext object manages FacesClient Components resources. This object is essential to the operation of the framework and it keeps an accounting of the FacesClient Components resources and ensures that the mediators are not exposed to infinite loops following a cycle in the data model/graph (for example, when a user has a banking account and the banking account points back to the user). Additionally, the object guarantees that a particular object or type is not produced more than once -- in other words, there won't be too many instances of the data model.

The PageContext maintains a single-page state and guarantees coordination between multiple FacesClient Components portlets in a Web page. By convention, put the PageContext in some request-level container to make certain it is shared across multiple elements called during the life cycle of the entire request.

Do not place the PageContext object in a session or page-level container -- it is only valid for a single request and sharing one across requests (throughout a session) has a negative effect, such as a missing data or type definition in a follow-up request. When portlet developers write cooperating portlets that share the same data models and data instance, they should use portlet APIs and FacesClient Components'sPageContext. The portlet API provides listeners which can add more functionality for a portlet.

The PortletPageListener allows a portlet to insert markup at the beginning and ending of a page. At the beginning of each page and before any service() method of any portlet on the page is called, the beginPage() method is called for each portlet residing on the page. Like the service() method, the beginPage() method for each portlet on the page is not called in a guaranteed order and can even be called in a different order for each request.

The output of beginPage() is inserted into the page-aggregation area prior to the rendering of portlets on the page. At the end of each page, after all service() methods of all portlets on the page are called, the endPage() method is called for each portlet residing on the page. Like the service() method, the endPage() method is not called in a guaranteed order and can even be called in a different order for each request. For example, the portlet can insert JavaScript to the end of the page that needs to occur after all other portlets on the page have been written.

The ODCBankAccount (shown in Listing 1) and ODCAssetAccountsDetails (shown in Listing 2) portlet examples demonstrate our use of the aforementioned portlet and FacesClient Components APIs.

ODCBankAccount and ODCAssetAccountsDetails are cooperating portlets that share the same data model and instance. Both portlet examples implement the PortletPageListener to allow insertion of key FacesClient Components page-state management, initialization, and post-processing code in the aggregation area of the portlets prior to rendering. The beginPage() method in each portlet inserts the results of a call to the ODCDemoUtility initialization method (in Listing 3).


Code examples to illustrate

The following code examples illustrate our best practices.


Listing 1. The ODCBankAccount portlet


public class ODCBankAccounts extends PortletAdapter
                        implements PortletSessionListener, PortletPageListener {
    ......

     public void login(PortletRequest request) throws PortletException {
     }

     public void logout(PortletSession session)throws PortletException {
     }

    /**
       do the appropriate processing on the data model and
       create the xhtml to send to the client
    **/
    public void doView(PortletRequest request, PortletResponse response)
                        throws PortletException, java.io.IOException {
       PortletContext context = getPortletConfig().getContext();
       context.include("resource/ODCBankAccounts.jsp", request, response);

    }

    public void beginPage(PortletRequest request, PortletResponse response)
                          throws PortletException, java.io.IOException {
      ODCDemoUtility du = new ODCDemoUtility();
      du.ODCDemoInitialization(request, response, getPortletConfig().getContext(),
                                           "resource/ODC_Banking_Init.jsp");
    }

    public void endPage(PortletRequest request, PortletResponse response)
                        throws PortletException, java.io.IOException {

     ODCDemoUtility du = new ODCDemoUtility();
     du.ODCDemoPostProcessing(request, response, getPortletConfig().getContext(),
                                                 "resource/ODC_Banking_End.jsp");
    }
}


Listing 2. The ODCAssetAccountsDetails portlet


 public class ODCAssetAccountsDetails extends PortletAdapter
                      implements PortletPageListener {

    public void login(PortletRequest request) throws PortletException {
    }

    public void logout(PortletSession session)throws PortletException {
    }

    /**
       do the appropriate processing on the data model and 
       create the xhtml to send to the client
     **/
   public void doView(PortletRequest request, PortletResponse response)
                           throws PortletException, java.io.IOException {
       PortletContext context = getPortletConfig().getContext();
       context.include("resource/ODCAssetAccountsDetails.jsp", request, response);

   }

   public void beginPage(PortletRequest request, PortletResponse response)
                   throws PortletException, java.io.IOException {
       ODCDemoUtility du = new ODCDemoUtility();
       du.ODCDemoInitialization(request, response, getPortletConfig().getContext(),
                                         "resource/ODC_Banking_Init.jsp");
   }
   
   public void endPage(PortletRequest request, PortletResponse response) 
                                    throws PortletException, java.io.IOException {
       ODCDemoUtility du = new ODCDemoUtility();
       du.ODCDemoPostProcessing(request, response, getPortletConfig().getContext(),
                                               "resource/ODC_Banking_End.jsp");
   }
}


Listing 3. The ODCDemoUtility initialization method


 public class ODCDemoUtility {
   .....
   public void ODCDemoInitialization( PortletRequest request,PortletResponse response,
                                      PortletContext context, String jspPage)
                                    throws PortletException, java.io.IOException {

      HttpServletRequest hsr = this.getHttpServletRequest(request);
      String wdo4js_prefix = (String) hsr.getAttribute("ODC_DEMO_INIT");

      // do this only once across all the portlets
      if ((wdo4js_prefix == null) || (!wdo4js_prefix.equals("true"))) {
          hsr.setAttribute("ODC_DEMO_INIT", "true");
          User portletUser = request.getUser();
          String userId = portletUser.getUserID();
          init(userId, request, response);
          context.include(jspPage, request, response);
      }
   }
   public void ODCDemoPostProcessing(PortletRequest request,PortletResponse response,
                                     PortletContext context,String jspPage)
                                    throws PortletException, java.io.IOException {
      HttpServletRequest hsr = this.getHttpServletRequest(request);
      String wdo4js_end = (String) hsr.getAttribute("ODC_DEMO_END");

      // do this only once across all the portlets
      if ((wdo4js_end == null) || (!wdo4js_end.equals("true"))) {
         hsr.setAttribute("ODC_DEMO_END", "true");
         context.include(jspPage, request, response);
      }
   }
 }

The HttpServletRequest stores name value pairs -- hsr.setAttribute("ODC_DEMO_INIT", "true") -- and the name value pairs ensure that the portlets on the Web page create only one data model and the data instance shared object.

Portlets placed on a Web page can be rendered in any order; therefore, create and invoke FacesClient Components code to generate the data model on each portlet enabled with FacesClient Components regardless of the other portlets on the Web page.

To wire events for FacesClient Components controls in multiple portlets, share the event objects. The endPage() method in each portlet inserts the results of a call to the ODCDemoUtility post-processing method. The HttpServletRequest stores name value pairs which ensure that the portlets on the Web page create only one event-shared object.

You can take two alternate approaches to enable portlets located on the same page to communicate with each other -- property broker and portlet messaging. The property broker's runtime is comprised of a generic wrapper portlet, which wraps each portlet enabled for cooperation, as well as a broker component. These components also interface with the WebSphere Portal core runtime. The purpose of the wrapper is to:

  • Intercept calls to the application portlet and interface with the broker appropriately
  • Transparently register actions supported by the portlet
  • Initiate data transfer from source to target portlets using the property broker

In the portlet messaging approach, a portlet's action listener typically sends a message and another portlet's message listener receives it. If an action occurs in one portlet, the action event is captured and processed by the portlet. As a result of the action event, the portlet sends a message to other portlets using the send() method of the PortletContext object. (Find more on these approaches in Resources.)


In conclusion

In this article, we discussed the challenges that developers face when they create portlets enabled with FacesClient Components. We also demonstrated, through sample code, how to share data models and instance data between multiple portlets on a portal page. In a following article, we'll discuss how to update the client-side data model without refreshing the portal page.



Downloads

DescriptionNameSizeDownload method
FacesClient Developer GuideFacesClient_developer_guide.pdf3.8 MB FTP |HTTP
Cooperative Portlets in WebSphere Portal V5 guideCooperativePortlets.pdf0.7 MB FTP
Source code, Cooperative Portlets guidecooperativeportletsexamples.zip311 KB FTP | HTTP

Information about download methods          Get Adobe® Reader®


Resources

About the authors

Photo of Rod Henderson

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 Ph.D. in electrical engineering from North Carolina A&T State University in 2002. 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

Yongcheng Li is a Senior Software Engineer in the IBM Software Group, System House, Advanced Technology Department located in Research Triangle Park, North Carolina. He received his Ph.D. in Computer Science from Tsinghua University in 1993. 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.

Photo of Thomas McElroy

Thomas McElroy is an Advisory Software Engineer in the IBM Software Group, System House, Advanced Technology Department located in Research Triangle Park, North Carolina. He has been working on Web application technology projects for the last three years, including projects with On-Demand Clients, Edge-Side Includes, Integrated Solutions Console, and a novel approach to a JDBC caching proxy. Reach Thomas at tmcelroy@us.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, WebSphere, Java technology
ArticleID=32428
ArticleTitle=FacesClient Components, Part 2: Use FacesClient Components in a portal environment
publish-date=01052005
author1-email=rodhende@us.ibm.com
author1-email-cc=htc@us.ibm.com
author2-email=ycli@us.ibm.com
author2-email-cc=htc@us.ibm.com
author3-email=tmcelroy@us.ibm.com
author3-email-cc=htc@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers