JBoss.orgCommunity Documentation

JBoss Portlet Bridge

Reference Guide

Release 2.0.0-SNAPSHOT


JBoss Portlet Bridge Overview
1. Getting started with JBoss Portlet Bridge
1.1. What's New in 2.0?
1.1.1. Eventing
1.1.2. Portlet Served Resources
1.1.3. Public Render Parameters
1.2. Bridge Frameworks and Extensions
1.2.1. Seam Bridgelets
1.2.2. RichFaces Bridgelets
1.3. Before you start
1.4. Maven Archetypes
1.4.1. Running the Examples (Optional)
1.5. Video Tutorials
2. Bridge Configuration
2.1. Core Setup and Configuration
2.1.1. portlet.xml
2.1.2. faces-config.xml
2.1.3. Facelets Configuration
2.1.4. JSP Only Configuration
2.1.5. JSR-329
2.2. RichFaces Setup and Configuration Options
2.2.1. web.xml
2.3. Seam Setup and Configuration Options
2.3.1. Configuration
2.4. Sending and Receiving Events
2.4.1. Configuration
2.5. Public Render Parmaeters
2.5.1. Configuration
3. Developing Portlets with the Bridge
3.1. Excluding Attributes from the Bridge Request Scope
3.2. Supporting PortletMode Changes
3.3. Navigating to a mode's last viewId
3.4. General Error Handling
3.5. Custom Ajax Error Handling
3.6. Storing Components in PortletSession.APPLICATION_SCOPE

To get an idea of the JBoss Portlet Bridge community, the developers, and for wiki information, checkout the project page.

What is the JBoss Portlet Bridge?

The JBoss Portlet Bridge (or JBPB for short) is a non-final draft implementation of the JSR-329 specification which supports the JSF 1.2 runtime within a JSR 286 portlet and with added enhancements to support other web frameworks (such as Seam and RichFaces). It allows any Java developer to get started quickly with their JSF web application running in a portal environment. The developer no longer needs to worry about the underlying portlet development, portlet concepts, or the API.

Understanding how JSF works with Portal

The portlet bridge isn't a portlet. It's the mediator between the two environments and allows JSF and Portal to be completely unaware of each other. The bridge is used to execute Faces requests on behalf of the portlet. During each request, the Faces environment is setup and handled by the bridge. Part of this implementation acts as a Faces controller much as the FacesServlet does in the direct client request world. The other part of this implementation is provided by implementating a variety of (standard) Faces extensions.

Note

This draft specification for the JSR 329 specification is not final. Any final specification that may be published will likely contain differences, some of which may be substantial. Publication of this draft specification is not intended to provide the basis for implementations of the specification. This draft specification is provided AS IS, with all faults. THERE ARE NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WARRANTIES OF CONDITION OF TITLE OR NONINFRINGEMENT. You may copy and display this draft specification provided that you include this notice and any existing copyright notice. Except for the limited copyright license granted above, there are no other licenses granted to any intellectual property owned or controlled by any of the authors or developers of this material. No other rights are granted by implication, estoppel or otherwise.

JBoss Portlet Bridge not only gives you the ability to run JSF web applications in a portlet, but also gives you the benefit of running supported JBoss frameworks like Seam and RichFaces.

The JBoss Portlet Bridge currently supports JBoss Portal, GateIn, JSF 1.2, JBoss Seam, and JBoss Richfaces. There are configurations that apply to supporting each framework. See section Chapter 2, Bridge Configuration for instructions.

The JBoss Portlet Bridge project is also actively developing extensions, and to differentiate from just another "project" that has boring ol' "extensions" we coined the term "Bridgelets" - because what would a project with Java and JSF be without having "*let" on the end of it? Not very cool in my opinion ;) With that said, in this current release we decided to bring all of our bridgelets into the impl code base since they are critical in most JSF portlet applications. Now it only takes a single line of configuration to utilize these features.

Current version and compatibilty information can be easily located on the JBPB wiki. Ensure you are using compatible versions of all integrated frameworks before you begin.

JBoss Portal and GateIn provides it's latest distribution included in JBoss Application Server. All of the guesswork has been eliminated so that you can unzip and run the Portal with a few clicks. Get the latest here (ensure you choose the Portal + JBoss AS link)

Next, all that's left is to download the JBoss Portlet Bridge distribution and cofigure your portlet to use the bridge. Or, you can run a provided archetype Section 1.4, “Maven Archetypes” and deploy the generated war in a few easy steps. This will also give you an empty project to play around with or start from scratch.

This project utilizes Maven archetypes which allow you get up and running with different flavors of the bridge quickly.


JSF 1.2 Basic, RichFaces Basic, Seam Basic, and other demos

The Maven-Cargo setup mentioned below is completely optional. It gives users who are new to the bridge or ones who may have problems running the bridge in their current setup, a completely fresh install of both JBoss AS and JBoss Portal to run against - with only a few commands. This setup only requires that the latest versions of Java and Maven be installed on your machine, and the following 3 commands will take care of the rest.

To see a step-by-step tutorial of this setup in action, follow along here:
                 Lesson 1: Getting Started With The Bridge

Each example application is configured to download the latest versions of JBoss Portal bundled with JBoss Application Server. After running the archetype Section 1.4, “Maven Archetypes” or downloading the source code for the example application that you're interested in, you can run one of the following Maven profiles to save time and get everything up and running with only 2 commands. You have 2 options for deploying the generated project using Maven. You can let the project download, run, and deploy JBoss AS and Portal automatically with the first option . Or you can use your own local install of JBoss AS and Portal to deploy this project with the second option.

JBoss Portal 2.7.2.GA + JBoss AS 4.2.3 (Bundled download)


            1. mvn install -Plocal-portal cargo:start
            2. mvn cargo:deploy -Plocal-portal
            3. visit http://localhost:8080/portal
            
For more commands, view the README.txt in each project. If you plan on using the cargo profiles to do active development, you can save alot of time by not downloading the bundle each time you do a clean install. To use a locally configured server bundled with portal, use the following command line parameters. The variable for JBOSS_HOME_DIR is related to how you zip the server directory. If you zip the files under JBOSS_HOME/* then it will only be the name of your archive. But if you zip the actual folder JBOSS_HOME then JBOSS_HOME_DIR must be defined as 'zip file name/JBOSS_HOME folder name'. So basically, just zip up your local install of JBoss AS and portal (or download the bundle from sourceforge) if you want to use this option.


            

JBoss Portal 2.7.2.GA + JBoss AS 4.2.3 (Downloaded and stored locally)


            1. mvn install cargo:start -Dlocal -Plocal-portal -DJBOSS_ZIP_HOME=/{path to zipped portal + JBoss AS}/jboss-portal-2.7.2-bundled.zip -DJBOSS_HOME_DIR=jboss-portal-2.7.2-bundled/jboss-portal-2.7.2
            2. mvn cargo:deploy -Plocal-portal
            3. visit http://localhost:8080/portal
            

The 329 specification is aimed at making the developers life as easy as possible with JSF+Portlet development. You will see below that there are minimal settings to getting any JSF web application up and running in the Portal environment.

If you are starting from scratch, we highly recommend you use the Section 1.4, “Maven Archetypes”.

The following web.xml setting is only for Facelets based applications



        <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
                 version="2.4">
            ...
            <!-- This is optional parameters for a facelets based application -->
            <context-param>
                <param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
                <param-value>org.jboss.portletbridge.application.FaceletPortletViewHandler</param-value>
            </context-param>



             <context-param>
                <param-name>javax.portlet.faces.RENDER_POLICY</param-name>
                <param-value>
                    ALWAYS_DELEGATE
                </param-value>
            </context-param>
            ...
        </web-app>

The following configuration is designated for portlets using the RichFaces library. These settings will vary based on your individual needs. See this section of the RichFaces documentation for more details.

Sometimes it is better to use the "ALL" load strategy in portlets so you do not need to worry about loading the "framework.pack.js" and "ui.pack.js" files manually in your portlet header.



            <context-param>
                <param-name>org.richfaces.LoadStyleStrategy</param-name>
                <param-value>ALL</param-value>
            </context-param>
            <context-param>
                <param-name>org.richfaces.LoadScriptStrategy</param-name>
                <param-value>ALL</param-value>
            </context-param>
            

Note

If you use the "NONE" strategy, you must include the following scripts in your portlet or portal page header. If you are using JBoss Portal, you can add this to the jboss-portlet.xml file.

The org.ajax4jsf.RESOURCE_URI_PREFIX configuration cross references the path to your scripts below. These settings are required for RichFaces using the "NONE" strategy.



    <script src="/faces/rfRes/org/ajax4jsf/framework.pack.js" type="text/javascript"></script>
    <script src="/faces/rfRes/org/richfaces/ui.pack.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="/faces/rfRes/org/richfaces/skin.xcss"/>
    

Seam automatically configures your Ajax4JSF Filter, so if you are running a Seam portlet, you do not need the following Filter config. (But you do need the RESOURCE_URI_PREFIX no matter what)



            <context-param>
                <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>
                <param-value>rfRes</param-value>
            </context-param>

            <filter>
                <display-name>Ajax4jsf Filter</display-name>
                <filter-name>ajax4jsf</filter-name>
                <filter-class>org.ajax4jsf.Filter</filter-class>
            </filter>

            <filter-mapping>
                <filter-name>ajax4jsf</filter-name>
                <servlet-name>FacesServlet</servlet-name>
                <dispatcher>FORWARD</dispatcher>
                <dispatcher>REQUEST</dispatcher>
                <dispatcher>INCLUDE</dispatcher>
            </filter-mapping>
            ...
        </web-app>
        

Just like with any portlet 2.0 event consumer and receiver, you must define them in the portlet.xml. To see a working example, checkout the Seam Booking Demo portlet. http://anonsvn.jboss.org/repos/portletbridge/tags/2.0.0.BETA/examples/seam/booking/

You must also define the following init params in your portlet.xml.



    </init-param>
      <init-param>
      <name>javax.portlet.faces.autoDispatchEvents</name>
      <value>true</value>
    </init-param>
      <init-param>
      <name>javax.portlet.faces.bridgeEventHandler</name>
      <value>org.foo.eventhandler</value>
    </init-param>

      

For now, you must dipatch the event in the JSF or Seam backing bean. Future versions on the 2.0 bridge will automate the dispatching and consuming of events.



   if (response instanceof StateAwareResponse) {
        StateAwareResponse stateResponse = (StateAwareResponse) response;
        stateResponse.setEvent(Foo.QNAME, new Bar());
    }
      

Then you must also create the event handler class by implementing the BridgeEventHandler interface to process the event payload.



   public class BookingEventHandler implements BridgeEventHandler
    {
       public EventNavigationResult handleEvent(FacesContext context, Event event)
       {
            //process event payload here
       }

    }
      

Public Render Parameters (or PRP) are one of the most powerful and simple Portlet 2.0 features. Several portlets (JSF or not) can share the same render parameters. This feature can be use to present a cohesive UI to the user across all portlets on the page (i.e. using an employee ID to display relative data).

The bridge maps a render parameter to a backing bean using settings in your faces-config.xml and portlet.xml. A clear and working example can be found in the Seam Booking Demo portlet. http://anonsvn.jboss.org/repos/portletbridge/tags/2.0.0.BETA/examples/seam/booking/

You must define the following init params in your portlet.xml.



    <init-param>
      <name>javax.portlet.faces.bridgePublicRenderParameterHandler</name>
      <value>org.foo.PRPHandler</value>
    </init-param>
    ...
    <supported-public-render-parameter>myCoolPRP</supported-public-render-parameter>
      

You must set the parameter in the JSF or Seam backing bean, if you are providing one from your portlet.



   if (response instanceof StateAwareResponse) {
        StateAwareResponse stateResponse = (StateAwareResponse) response;
        stateResponse.setRenderParameter("hotelName",selectedHotel.getName());
    }
      

Then you must also implement the BridgePublicRenderParameterHandler interface to process and updates from the received parameter.



   public void processUpdates(FacesContext context)
   {
      ELContext elContext = context.getELContext();
      BookingPRPBean bean = (BookingPRPBean) elContext.getELResolver().getValue(elContext, null, "bookingPRP");

    if(null != bean){
       //Do something with bean.getHotelName());
    } else {

    }
   }
      

This chapter demonstrates common development tasks described by the 329 specification.

By default a mode change will start in the mode's default view without any (prior) existing state. One common portlet pattern when returning to the mode one left after entering another mode (e.g.. view -> edit -> view) is to return to the last view (and state) of this origin mode. The bridge will explicitly encode the necessary information so that when returning to a prior mode it can target the appropriate view and restore the appropriate state. The session attributes maintained by the bridge are intended to be used by developers to navigate back from a mode to the last location and state of a prior mode. As such a developer needs to describe a dynamic navigation: "from view X return to the last view of mode y". This is most easily expressed via an EL expression. E.g.



         <navigation-rule>
           <from-view-id>/edit.jspx*</from-view-id>
           <navigation-case>
             <from-outcome>view</from-outcome>
             <to-view-id>#{sessionScope['javax.portlet.faces.viewIdHistory.view']}</to-view-id>
           </navigation-case>
         </navigation-rule>