Chapter 28. Portlet Bridge

28.1. JBoss Portlet Bridge
28.2. Portlet application
28.3. Extensions
28.4. Examples
28.5. Render Policy Parameters
28.6. Facelets Configuration
28.7. JSP-only Configuration
28.8. RichFaces Local and Remote Portlet Support
28.9. Sending and Receiving Events
28.10. Sending Events
28.11. Receiving Events
28.12. Public Render Parameters
28.13. Saving Bridge Request Scope after Render complete
28.14. PRP portlet configuration
28.15. Application configuration
28.16. Portlet Session
28.17. Resource serving
28.18. Serving JSF Resources in a Portlet
28.19. Expression Language Reference
28.20. Expression Language Configuration
28.21. Developing Portlets with the Bridge
28.21.1. Implementing Portlet Bridge
28.21.2. Declaring Artifact Dependencies
28.21.3. Declaring Depchain Dependencies
28.21.4. Deploying Portlet Bridge Portlets
28.21.5. Disable Automatic Portlet Bridge Injection
28.21.6. Supported Portlet Tags
28.21.7. Excluding Attributes from the Bridge Request Scope
28.21.8. Prevent Resources Being Added to Portal Page Head
28.21.9. JSF Facelet View
28.21.10. Error Handling
28.21.11. Switching Portlet Modes
28.21.12. Navigating to a mode's last viewId
28.21.13. Using Wildcards to Identify the Rule Target
28.21.14. Clearing the View History when Changing Portlet Modes
28.21.15. Communication Between Portlets
28.21.16. Storing Components in PortletSession.APPLICATION_SCOPE
28.21.17. Using the PortletSession
28.21.18. Linking to a Facelets page within the Same Portlet
28.21.19. Redirecting to an External Page or Resource
28.21.20. Using Provided EL Variables
A portlet bridge is a mediator that allows non-native application frameworks to run in a portal environment, independent to the underlying portlet API, or portlet concept. This functionality provides a developer flexibility to continue writing applications in a preferred language, and allows a controlled transition to new technologies.

28.1. JBoss Portlet Bridge

The JBoss Portlet Bridge is an implementation of the JSR-329 specification. It supports the JSF 2.0 runtime within a JSR 168 or 286 portlet. Version 3.x of the bridge is compatible with JSF 2.0 and RichFaces 4.x.
JBoss Portlet Bridge allows JSF applications to run using supported JBoss frameworks such as RichFaces. Seam 3.2 support is not yet available for JSF2, however support may be included in a future release.
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 like the FacesServlet does in the direct client request environment.
The other part of this implementation is provided by implementing a variety of (standard) Faces extensions.

28.2. Portlet application

A portlet application is defined as a single web archive (WAR).
All portlets that are part of the same WAR are considered to form part of the same portlet application.

28.3. Extensions

Portlet extensions sit atop the portlet bridge framework. They extend the functionality of other JBoss portlet applications, and are critical in JSF portlet development.

28.4. Examples

Portlet Bridge provides example JSF2 portlets, which provide a good starting point for including the framework in portlets, as well as demonstrating the functionality available in Portlet Bridge.

Important

The provided examples are not officially supported by Red Hat.
JSF2 Portlet
This example provides a basic JSF2 portlet demonstrating Ajax functionality. This example provides a solid foundation for basic JSF2 functionality.
RichFaces 4 Simple
This example demonstrates a simple RichFaces 4 form with ajax submission and an extended data table showing the submitted data. This example provides a solid foundation for basic RichFaces 4 functionality.
RichFaces 4 Showcase
This example demonstrates a RichFaces 4 application, with portlet-specific changes. This example is worth deploying for advanced RichFaces 4 functionality, and shows the full spectrum of what can be achieved with RichFaces 4 and Portlet Bridge

28.5. Render Policy Parameters

Different JSF View Declaration Languages require different behavior from the JBoss Portlet Bridge when it comes to rendering views. Instructing the Bridge on which policy to use is done using the javax.portlet.faces.RENDER_POLICY <context-param> directive in web.xml.

RenderPolicy Options

ALWAYS_DELEGATE
Indicates the bridge should not render the view itself, but rather always delegate the rendering.
NEVER_DELEGATE
Indicates the bridge should always render the view itself and never delegate.
DEFAULT
Directs the bridge to first delegate the render. If an exception is thrown, the bridge renders the view based on its own logic. If the configuration parameter is not present or has an invalid value the bridge renders using default behavior as it would if DEFAULT was set.

28.6. Facelets Configuration

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

Example 28.1. Facelets web.xml Configuration

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

28.7. JSP-only Configuration

The following web.xml setting is only for JSP based applications. Download the demonstration application here.

Example 28.2. web.xml

<context-param>
<param-name>javax.portlet.faces.RENDER_POLICY</param-name>
<param-value>NEVER_DELEGATE</param-value>
</context-param>

28.8. RichFaces Local and Remote Portlet Support

Table 28.1. RichFaces Feature Support Exceptions

RichFaces Component Local Portlet Remote Portlet using WSRP Additional Comments
rich:editor Yes Yes Some issues with editor icons over WSRP may be encountered when the Consumer and Producer are on different servers because the URLs are relative and are generated through JavaScript
rich:focus Yes Untested Available since RichFaces 4.3.0.M3
rich:placeholder Yes Untested Available since RichFaces 4.3.0.M3
a4j:push Yes No Not supported for WSRP in Red Hat JBoss Portal Platform 6.2

Table 28.2. RichFaces Feature Status

RichFaces Component Supported as Local Portlet Supported as Remote Portlet using WSRP
a4j:actionListener Yes Yes
a4j:ajax Yes Yes
a4j:attachQueue Yes Yes
a4j:commandButton Yes Yes
a4j:commandLink Yes Yes
a4j:jsFunction Yes Yes
a4j:log Yes Yes
a4j:mediaOutput Yes Yes
a4j:outputPanel Yes Yes
a4j:param Yes Yes
a4j:poll Yes Yes
a4j:queue Yes Yes
a4j:region Yes Yes
a4j:repeat Yes Yes
a4j:status Yes Yes
rich:accordion Yes Yes
rich:accordionItem Yes Yes
rich:autocomplete Yes Yes
rich:calendar Yes Yes
rich:collapsiblePanel Yes Yes
rich:collapsibleSubTable Yes Yes
rich:collapsibleSubTableToggler Yes Yes
rich:column Yes Yes
rich:columnGroup Yes Yes
rich:componentControl Yes Yes
rich:contextMenu Yes Yes
rich:dataGrid Yes Yes
rich:dataTable Yes Yes
rich:dragIndicator Yes Yes
rich:dragSource Yes Yes
rich:dropDownMenu Yes Yes
rich:dataScroller Yes Yes
rich:dropTarget Yes Yes
rich:editor Yes Yes
rich:extendedDataTable Yes Yes
rich:fileUpload Yes Yes
rich:focus Yes Untested
rich:graphValidator Yes Yes
rich:hashParam Yes Yes
rich:hotKey Yes Yes
rich:inplaceInput Yes Yes
rich:inplaceSelect Yes Yes
rich:inputNumberSlider Yes Yes
rich:inputNumberSpinner Yes Yes
rich:jQuery Yes Yes
rich:list Yes Yes
rich:menuGroup Yes Yes
rich:menuItem Yes Yes
rich:menuSeparator Yes Yes
rich:message Yes Yes
rich:messages Yes Yes
rich:notify Yes Yes
rich:notifyMessage Yes No
rich:notifyMessages Yes Yes
rich:notifyStack Yes Yes
rich:orderingList Yes Yes
rich:panel Yes Yes
rich:panelMenu Yes Yes
rich:panelMenuGroup Yes Yes
rich:panelMenuItem Yes Yes
rich:inputNumberSlider Yes Yes
rich:pickList Yes Yes
rich:placeholder Yes Untested
rich:popupPanel Yes Yes
rich:progressBar Yes Yes
rich:select Yes Yes
rich:tab Yes Yes
rich:tabPanel Yes Yes
rich:toggleControl Yes Yes
rich:togglePanel Yes Yes
rich:togglePanelItem Yes Yes
rich:toolbar Yes Yes
rich:toolbarGroup Yes Yes
rich:tooltip Yes Yes
rich:tree Yes Yes
rich:treeModelAdaptor Yes Yes
rich:treeModelRecursiveAdaptor Yes Yes
rich:treeNode Yes Yes
rich:validator Yes Yes

28.9. Sending and Receiving Events

The bridge considers a portlet event a model event, which means the event is targeted to the application's data model, not its view.
Because JSF events primarily concern its view, the bridge processes the portlet events manually. Provisions are made to ensure that any model changes resulting from processing the event are updated in the view.
Because event payloads are arbitrarily complex however, the manual data processing is left primarily to the portlet application to support.

28.10. Sending Events

The following configuration uses information relating to a generic Booking Event portlet. The concepts contained within each example can be applied to other event sending scenarios.

Procedure 28.1. Sending Events

  1. Define the autoDispatchEvents <init-param> in portlet.xml to specify the GenericFacesPortlet should override event handling and dispatch all events to the bridge.

    Important

    If the application is written entirely in JSF (as opposed to a mix of view technologies), this <init-param> must be set to true.
    <init-param>
      <name>javax.portlet.faces.autoDispatchEvents</name>
      <value>true</value>
    </init-param>
  2. Define the <supported-publishing-event> in portlet.xml to enable the portlet to publish an event to the portal.
    <supported-publishing-event>
      <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
    </supported-publishing-event>
  3. Define the <event-definition> directive in portlet.xml to specify how the event namespace (<qname>) is linked to an actual type within the application.
    <event-definition>
      <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
      <value-type>org.jboss.example.booking.BookingEvent</value-type>
    </event-definition>

Example 28.3. Event type example

To publish an event, define an event type that represents the actual object that will be attached to the event.
The type requires the @XmlRootElement annotation to allow the event to be serialized into a JAXB object for publishing.

@XmlRootElement
public class BookingEvent implements Serializable {
 
  private String id;
  public static final QName QNAME = new QName("urn:jboss:portal:samples:event", "BookingEvent");
 
  public BookingEvent(String id) {
      this.id = id;
  }
 
  public String getId() {
    return id;
  }
}

Example 28.4. Dispatch event example

To dispatch an event to other portlets within the portal, one approach is to use a bean method triggered by an action.
Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
  if (response instanceof StateAwareResponse) {
    String id = "an id";
    StateAwareResponse stateResponse = (StateAwareResponse) response;
    stateResponse.setEvent(BookingEvent.QNAME, new BookingEvent(id));
  }

28.11. Receiving Events

The following configuration uses information relating to a generic Booking Event portlet. The concepts contained within each example can be applied to other event receiving scenarios.

Procedure 28.2. 

  1. Define the bridgeEventHandler <init-param> directive in portlet.xml to specify the portlet can receive an event from Portlet Bridge.
    <init-param>
      <name>javax.portlet.faces.bridgeEventHandler</name>
      <value>org.jboss.example.booking.BookingEventHandler</value>
    </init-param>
  2. Define the <supported-processing-event> directive in portal.xml to specify the portlet can also receive an event from the portal.
    <supported-processing-event>
      <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
    </supported-processing-event>
  3. Define the <event-definition> directive in the portlet that will be receiving the event.
    <event-definition>
      <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
      <value-type>org.jboss.example.booking.BookingEvent</value-type>
    </event-definition>
    			
To process a received event within a portlet, specify in the portlet code that the event handler implements the BridgeEventHandler.
public class BookingEventHandler implements BridgeEventHandler {
  public EventNavigationResult handleEvent(FacesContext context, Event event) {
    // Process event payload as appropriate
  }
}

28.12. Public Render Parameters

Public Render Parameters (or PRPs) are one of the most powerful and simple Portlet 2.0 features. Several portlets (JSF or otherwise) can share the same PRPs. This feature can be used to present a cohesive UI to the user across all portlets on the page. An example would be using an employee ID to display relative data.
The bridge automates public render parameter processing.
A public render parameter can be mapped to an object's accessor (get/set method) designed to handle a String representation of the value through a Faces ValueExpression.
Unlike Events, PRPs can only be used to set/get a string value, and not an object.
When a new public render parameter value is received in a request, the bridge sets the value by calling the ValueExpression's setValue().
The bridge maps a render parameter to a backing bean using settings in the faces-config.xml and portlet.xml files.
At the end of a request, if the current value of any mapped public render parameter does not match the current incoming value, the bridge sets the new value in an outgoing public render parameter (if feasible in the given phase).

28.13. Saving Bridge Request Scope after Render complete

By default, the Bridge Request Scope is not retained after completion of a Render Request. To save Bridge Request Scope after Render complete will enable developers to focus on Ajax requests and interactions as opposed to full page refreshes.
To return to the behavior of previous Portlet Bridge versions, you need to set the following initialization parameter in portlet.xml for a specific portlet:

  <init-param>
  <name>org.jboss.portletbridge.BRIDGE_SCOPE_PRESERVED_POST_RENDER</name>
  <value>true</value>
</init-param>



You can also set it for all portlets present within an archive by setting the following context parameter in web.xml:

  <context-param>
  <param-name>org.jboss.portletbridge.BRIDGE_SCOPE_PRESERVED_POST_RENDER</param-name>
  <param-value>true</param-value>
</context-param>



28.14. PRP portlet configuration

The following configuration uses information relating to a generic Booking Event portlet. The concepts contained within each example can be applied to other PRP portlet configuration.
PRPs must be configured in both the portlet that sends (sets) the PRP, and the portlet that retrieves (gets) the PRP.
<portlet>
<!-- Unnecessary configuration information removed for clarity -->
  <supported-public-render-parameter>hotelName</supported-public-render-parameter>
</portlet>
 
<public-render-parameter>
  <identifier>hotelName</identifier>
  <qname xmlns:j="http://jboss.org/params">j:hotelName</qname>
</public-render-parameter>
In the portlet that retrieves the PRP, a PRP handler must be specified as an <init-param> directive.
<init-param>
  
<name>javax.portlet.faces.bridgePublicRenderParameterHandler</name>
  <value>org.jboss.example.booking.BookingPRPHandler</value>
</init-param>

28.15. Application configuration

The following configuration uses information relating to a generic Booking Event portlet. The concepts contained within each example can be applied to other PRP portlet configuration.

Example 28.5. Set Parameter

To set the PRP, create a Bean method for the portlet setting the parameter that is triggered from a UI action, and sets the PRP onto the response.
Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
if (response instanceof StateAwareResponse) {
  StateAwareResponse stateResponse = (StateAwareResponse) response;
  stateResponse.setRenderParameter(&quot;hotelName&quot;, &quot;Name of Hotel&quot;);
}

Example 28.6. Retrieve parameter

The retrieving portlet requires a Bean with a getter/setter for the parameter, to enable Portlet Bridge to set the parameter.
public class BookingPRP {
  private String hotelName;
 
  public String getHotelName() {
    return hotelName;
  }
 
  public void setHotelName(String hotelName) {
    this.hotelName = hotelName;
  }
}
To set the value on the bean, the Bridge needs to be informed which PRP to retrieve and which Bean to set it on.
If the getter/setter Bean is defined with a EL name of bookingPRP, the following configuration is required in faces-config.xml.
<application>
    <application-extension>
       <bridge:public-parameter-mappings>
          <bridge:public-parameter-mapping>
             <parameter>[bookingMapPortlet]:[hotelName]</parameter>
             <model-el>#{bookingPRP.hotelName}</model-el>
           </bridge:public-parameter-mapping>
        </bridge:public-parameter-mappings>
     </application-extension>
</application>

Important

Specifying the portlet name restricts model updates to the specified portlet only. If the portlet name is omitted and only the render parameter specified, every portlet within the web application that supports that render parameter will have its model updated.
[bookingMapPortlet]
The arbitrary name of the portlet, as set in portlet.xml
[hotelName]
The arbitrary name of the render parameter.
The handler specified in the portlet.xml requires a bean to process the updates to the model, as a result of the Public Render Parameter.
public class BookingPRPHandler implements BridgePublicRenderParameterHandler {
  public void processUpdates(FacesContext context) {
    ELContext elContext = context.getELContext();
    BookingPRPBean bean = (BookingPRPBean) elContext.getELResolver().getValue(elContext, null, &quot;bookingPRP&quot;);
 
    if(null != bean) {
      System.out.println(&quot;******processUpdates from BookingPRPHandler: &quot; + bean.getHotelName());
    }
  }
}

28.16. Portlet Session

To share data with other portlets within the same portlet application, use name/value pairs within the PortletSession.

Object objSession = FacesContext.getCurrentInstance().getExternalContext().getSession(false);
  try {
    if (objSession instanceof PortletSession) {
      PortletSession portalSession = (PortletSession)objSession;
      portalSession.setAttribute("your parameter name", "parameter value", PortletSession.APPLICATION_SCOPE);
    }
  }
In the JSP or Facelets page, the value string can be retrieved using the following code.
#{httpSessionScope['your parameter name']}

28.17. Resource serving

When using resources from a JSF portlet, it is important to ensure that they are accessed in a way that allows JBoss Portlet Bridge to construct an appropriate Portal URL to the resource being requested.
The correct way to reference a resource is to locate it within the web application, in the / resources directory. This placement allows the resource to be retrieved using JSF2 resource handling.
#{resource['/stylesheet.css']}

Important

#{resource} is particularly important when using @import to retrieve content within CSS files.
In this instance, stylesheet.css would be present in the root of the /resources directory, because it does not specify a resource library. For resources that do specify a library, these must be placed in the library sub-directory.

28.18. Serving JSF Resources in a Portlet

The bridge deals with portlet served resources in one of two ways:
  • If the request is for a non-JSF resource, the bridge handles the request by acquiring a request dispatcher and forwarding the request to the named resource.
  • If the request is for a JSF resource, the bridge runs the full JSF life cycle ensuring that data is processed and the resource (markup) is rendered.

28.19. Expression Language Reference

Some examples demonstrating how to use EL and a simple bean are provided in the ResourceBean.java file of the Richfaces Portlet example.
package org.richfaces.demo.common;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import javax.faces.bean.ManagedBean;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.portlet.MimeResponse;
import javax.portlet.ResourceURL;

/**
 * @author <a href="http://community.jboss.org/people/kenfinni">Ken Finnigan</a>
 */
@ManagedBean(name = "portletRes")
public class PortletResource implements Map<String, String> {

    @Override
    public void clear() {
    }

    @Override
    public boolean containsKey(Object arg0) {
        return true;
    }

    @Override
    public boolean containsValue(Object arg0) {
        return true;
    }

    @Override
    public Set<java.util.Map.Entry<String, String>> entrySet() {
        return Collections.emptySet();
    }

    @Override
    public String get(Object resourceKey) {
        FacesContext context = FacesContext.getCurrentInstance();
        String resourceUrl = null;

        if (null != resourceKey) {
            ExternalContext extCon = context.getExternalContext();
            MimeResponse response = (MimeResponse) extCon.getResponse();
            ResourceURL resUrl = response.createResourceURL();
            resUrl.setResourceID(resourceKey.toString());
            resourceUrl = resUrl.toString();
        }
        return resourceUrl;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public Set<String> keySet() {
        return Collections.emptySet();
    }

    @Override
    public String put(String arg0, String arg1) {
        return null;
    }

    @Override
    public void putAll(Map<? extends String, ? extends String> arg0) {
    }

    @Override
    public String remove(Object arg0) {
        return null;
    }

    @Override
    public int size() {
        return 0;
    }

    @Override
    public Collection<String> values() {
        return Collections.emptySet();
    }

}

28.20. Expression Language Configuration

When you have the normal "/images", "/styles" and other resource folders in your web application, you can use the following EL expression to serve them in your JSF application.
#{resource['/img/the-path-to-my-image.png']}
Copy the ResourceBean.java code described in Section 28.19, “Expression Language Reference”, and add an entry to the faces-config.xml for the bean.
<managed-bean>
<managed-bean-name>resource</managed-bean-name>
<managed-bean-class>org.richfaces.demo.common.ResourceBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>

28.21. Developing Portlets with the Bridge

28.21.1. Implementing Portlet Bridge

Portlet Bridge supports JSF2 and RichFaces 4 portlets. There are subtle differences in the way these portlets require Portlet Bridge to be implemented.
JSF2 and RichFaces 4 portlets must be JSF2 portlets for this version of the Portlet Bridge to function as expected. There are no other specific requirements.

28.21.2. Declaring Artifact Dependencies

A JSF2 portlet can inherit the correct dependencies by configuring the Maven repository. This will include all dependencies for all Portlet Bridge JSF2 scenarios.

Procedure 28.3. Artifact Dependencies

  1. Add the following pom.xml dependencies to inherit the correct JSF2 artifacts.
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-api</artifactId>
        <version>3.1.2.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-impl</artifactId>
        <version>3.1.2.Final</version>
        <scope>runtime</scope>
    </dependency>
  2. For RichFaces 4 portlets, add the following additional dependency to inherit the additional RichFaces dependencies.
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-extension-richfaces</artifactId>
        <version>3.1.2.Final</version>
        <scope>runtime</scope>
    </dependency>

28.21.3. Declaring Depchain Dependencies

It is possible to reduce the pom.xml configuration to a single dependency, using the Portlet Bridge Depchain pom.xml configuration.

Procedure 28.4. JSF2 Depchain Dependencies

  1. Add the following dependencies to inherit the correct artifacts using the pom.xml Depchain.
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>jsf2-depchain</artifactId>
        <version>3.1.2.Final</version>
        <type>pom</type>
    </dependency>
  2. For RichFaces 4 portlets, add the following additional dependency to inherit the correct artifacts using the pom.xml Depchain.
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>jsf2-depchain</artifactId>
        <version>3.1.2.Final</version>
        <type>pom</type>
    </dependency>
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>richfaces4-depchain</artifactId>
        <version>3.1.2.Final</version>
        <type>pom</type>
    </dependency>

28.21.4. Deploying Portlet Bridge Portlets

Red Hat JBoss Portal injects Portlet Bridge functionality into all JSF2 portlets by default, therefore portlets developed for the portal do not need to include the Portlet Bridge as part of the application.
If the Portlet Bridge API is included in a JSF2 or RichFaces 4 portlet, the provided scope must be correctly declared.

Procedure 28.5. Setting the Provided Scope for JSF2 and RichFaces Portlets that use Portlet Bridge API

  1. Add the following pom.xml dependencies to declare the JSF2 provided scope.
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-api</artifactId>
        <version>3.1.2.Final</version>
        <scope>provided</scope>
    </dependency>
  2. For RichFaces 4 portlets, add the following additional dependency to declare the RichFaces 4 runtime scope.

    Note

    The RichFaces 4 extension is not included in the portal by default.
    <dependency>
        <groupId>org.jboss.portletbridge</groupId>
        <artifactId>portletbridge-extension-richfaces</artifactId>
        <version>portletbridge-extension-richfaces-[VERSION]</version>
        <scope>runtime</scope>
    </dependency>
    Where [VERSION] is the portletbridge-extension-richfaces version in $JPP_HOME/modules/org/jboss/portletbridge/api/main

28.21.5. Disable Automatic Portlet Bridge Injection

In some cases, it is appropriate to prevent the portal from injecting Portlet Bridge into the application. For example, if a different version of Portlet Bridge is required for the application.

Procedure 28.6. Disabling automatic Portlet Bridge injection

  • Add the following web.xml dependency to prevent injecting the packaged Portlet Bridge implementation into a portlet application.

    Note

    If a portlet application specifies either WAR_BUNDLES_JSF or JSF_CONFIG_NAME context parameters in the web.xml, Portlet Bridge will not be automatically injected.
    
    <context-param>
        <param-name>org.gatein.portletbridge.WAR_BUNDLES_PORTLETBRIDGE</param-name>
        <param-value>true</param-value>
    </context-param>

28.21.6. Supported Portlet Tags

Portlet Bridge supports the following tags from section PLT.26 of the Portlet 2.0 Spec (JSR 286):
  • actionURL
  • renderURL
  • resourceURL
  • namespace
  • param
  • property
When using the tag library, the following namespace must be added to the facelet page of the application.
xmlns:pbr="http://jboss.org/portletbridge"

Example 28.7. renderURL example

Generate a Portlet Render URL that enables switching between Portlet modes.
<pbr:renderURL var="renderUrl" portletMode="edit">
</pbr:renderURL>
<h:outputLink value="#{renderUrl}">Edit Mode</h:outputLink>

Example 28.8. namespace example

This portlet tag is particularly useful for prefixing JavaScript functions within a given portlet. This ensures that the JavaScript function name does not clash with a name from another portlet, or from the same portlet displayed on the same page multiple times.
An example for defining a JavaScript method is:
<script type='text/javascript'>
  function <pbr:namespace />DoSomething() {
  }
</script>

28.21.7. Excluding Attributes from the Bridge Request Scope

When your application uses request attributes on a per request basis and you do not need that particular attribute to be managed in the extended bridge request scope, you must use the following configuration in your faces-config.xml.
In the code sample below, any attribute namespaced as foo.bar, or any attribute beginning with foo.baz.(wild-card) will be excluded from the bridge request scope and only be used for that application's request.
[<application>
	<application-extension>
		<bridge:excluded-attributes>
			<bridge:excluded-attribute>foo.bar</bridge:excluded-attribute>
				<bridge:excluded-attribute>foo.baz.*</bridge:excluded-attribute>
			</bridge:excluded-attributes>
	</application-extension>
</application>

28.21.8. Prevent Resources Being Added to Portal Page Head

Portlet Bridge will add any JSF Resources for the portlet into the <head> section of the portal page the portlet is on, providing the portlet container supports marking up the head of a page.
To prevent Portlet Bridge from adding resources into the <head> section of the portal page, override the default behavior by declaring the following directive in the portlet's web.xml file.
<context-param>
  <param-name>org.jboss.portletbridge.markupHead.enabled</param-name>
  <param-value>false</param-value>
</context-param>

28.21.9. JSF Facelet View

When creating a JSF Facelet view document, it is common to see content wrapped with the following code.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets" >
<!-- Unnecessary content removed for clarity -->
</html>
Because a single portlet only reflects a potentially small portion of the HTML markup for a page, a JSF portlet returning the above markup for each portlet can be distracting, and potentially problematic.
The recommended way to wrap the content of a JSF Facelet view document for a portlet is to use the <f:view> element. Using <f:view> results in the relevant portlet markup being returned to the page as required.
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets" >
<!-- Unnecessary content removed for clarity -->
</f:view>

Note

While not specifically relevant to portlet, it is important to include <h:head> and <h:body> elements to allow JSF to process the facelet correctly.

28.21.10. Error Handling

To display error pages for specific exceptions in a JSF portlet, the following code is required in the web.xml file.
<error-page>
  <exception-type>javax.servlet.ServletException</exception-type>
  <location>/faces/error.xhtml</location>
</error-page>
<error-page>
  <exception-type>javax.faces.application.ViewExpiredException</exception-type>
  <location>/faces/error.xhtml</location>
</error-page>
The above error page definitions are appropriate for a JSF portlet that has a FacesServlet mapping such as /faces/.
If the FacesServlet mapping was **.jsf, the location would be /error, /error.jsf or /error.xhtml.
There is no requirement when using FacesServlet suffix mapping to append an extension, the name of the view is all that is required for the page to be found

Note

Remember to add a link from any error page to the normal flow of the JSF application, otherwise the same error page will be constantly displayed.

28.21.11. Switching Portlet Modes

A PortletMode represents a distinct render path within an application. There are three standard modes: view, edit, and help.
The bridge's ExternalContext.encodeActionURL recognizes the query string parameter javax.portlet.faces.PortletMode and uses this parameter's value to set the portlet mode on the underlying portlet actionURL or response. Once processed it then removes this parameter from the query string.

Example 28.9. /edit.xhtml navigation rule

This navigation rule causes one to render the /edit.xhtml viewId in the portlet edit mode.
<navigation-rule>
  <from-view-id>/register.xhtml</from-view-id>
  <navigation-case>
    <from-outcome>edit</from-outcome>
    <to-view-id>/edit.xhtml?javax.portlet.faces.PortletMode=edit</to-view-id>
  </navigation-case>
</navigation-rule>

28.21.12. Navigating to a mode's last viewId

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 a mode left after entering another mode (e.g.. view -> edit -> view) is to return to the last view (and state) of this original 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 must describe a dynamic navigation: "From view X return to the last view of mode Y".
This is most easily expressed via an EL expression. For example:

Example 28.10. /register.xhtml viewId navigation rule

This navigation rule causes one to render the /edit.xhtml viewId in the portlet edit mode.
<navigation-rule>
  <from-view-id>/edit.xhtml*</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>

28.21.13. Using Wildcards to Identify the Rule Target

When using values from session scoped attributes, or viewIds which may contain query string parameters, it may be necessary to use the wild-card syntax when identifying the rule target.
In Section 28.21.12, “Navigating to a mode's last viewId” the <to-view-id> expression returns a viewId of the form
/viewId?javax.portlet.faces.PortletMode=view&....
Without wild-carding, when a subsequent navigation occurs from this new view, the navigation rules would not resolve because there would not be an exact match.
Similarly, the edit.jspx<from-view-id> is wild-carded because there are navigation rules that target it that use a query string:
<to-view-id> /edit.jspx?javax.portlet.faces.PortletMode=edit </to-view-id>
Developers are encouraged to use this wild card method to ensure they execute properly in the broadest set of bridge implementations.

28.21.14. Clearing the View History when Changing Portlet Modes

By default the bridge remembers the view history when you switch to a different portlet mode (like "Help" or "Edit"). You can use the following parameter in your portlet.xml to use the default viewId each time you switch modes.
<init-param>
	<name>javax.portlet.faces.extension.resetModeViewId</name>
	<value>true</value>
</init-param>

28.21.15. Communication Between Portlets

There are four different ways to send messages, events, and parameters between portlets which are contained in different ears/wars or contained in the same war.
Having two portlets in the same war or having them separated does not affect the Portlet Container because each portlet has a different HttpSession.
The recommended way to share a parameter or event payload between two or more portlets with the Portlet 2.0 specification are the Section 28.12, “Public Render Parameters” and Section 28.9, “Sending and Receiving Events” mechanisms.
This allows you to decouple your application from surgically managing objects in the PortletSession.APPLICATION_SCOPE.
However, if these do not meet your use case or you have a different strategy, you can use one of the following methods.

28.21.16. Storing Components in PortletSession.APPLICATION_SCOPE

Sometimes it is beneficial to store your Seam components in the portlet APPLICATION_SCOPE.
By default, these objects are stored in the PORTLET_SCOPE but with the annotation below, this class can be pulled out of the PortletSession and its values used in other portlets across different Seam applications.
@PortletScope(PortletScope.ScopeType.APPLICATION_SCOPE)
Then you would pull the stateful object from the session:
YourSessionClass yourSessionClass = (YourSessionClass)getRenderRequest().getAttribute("javax.portlet.p./default/seamproject/seamprojectPortletWindow?textHolder");
This method is demonstrated in this video: Lesson 2: Portlet 1.0 Advanced Seam and RichFaces

28.21.17. Using the PortletSession

If you only need to access the PortletSession to share a parameter or value across multiple portlets, you can use the following:
Object objSession = FacesContext.getCurrentInstance().getExternalContext().getSession(false);
try
{
	if (objSession instanceof PortletSession)
	{
		PortletSession portalSession = (PortletSession)objSession;
		portalSession.setAttribute("your parameter name","parameter value",PortletSession.APPLICATION_SCOPE);
		...
Then, in your JSP or Facelets page, you can use:
#{httpSessionScope['your parameter name']}

28.21.18. Linking to a Facelets page within the Same Portlet

To link any JSF/Facelets page within a portlet web application, use the following code.
<h:outputLink value="#{facesContext.externalContext.requestContextPath}/home.xhtml">
	<f:param name="javax.portlet.faces.ViewLink" value="true"/>
	navigate to the test page
</h:outputLink>

28.21.19. Redirecting to an External Page or Resource

To link to a non JSF view, jboss.org for example, you can use the following code.
<h:commandLink actionListener="#{yourBean.yourListenr}">
	<f:param name="javax.portlet.faces.DirectLink" value="true"/>
	navigate to the test page
</h:commandLink>
In the backing bean, a redirect() must be called.
public class YourBean {
  public void yourListener() {
    FacesContext.getCurrentInstance().getExternalContext().redirect("http://www.jboss.org");
  }
}

28.21.20. Using Provided EL Variables

All EL variables found in the JSR-329 (Portlet 2.0) specification are available in the JBoss Portlet Bridge.

Table 28.3. 

portalConfig
Object of type javax.portlet.PortletConfig
actionRequest
Object of type
javax.portlet.ActionRequest
(only accessible when processing an ActionRequest)
actionResponse
Object of type
javax.portlet.ActionResponse
(only accessible when processing an ActionResponse)
eventRequest
Object of type
javax.portlet.EventRequest
(only accessible when processing an EventRequest)
eventResponse
Object of type
javax.portlet.EventResponse
(only accessible when processing an EventRequest)
renderRequest
Object of type
javax.portlet.RenderRequest
(only accessible when processing an RenderResponse)
renderResponse
Object of type
javax.portlet.RenderResponse
(only accessible when processing an RenderResponse)
resourceRequest
Object of type
javax.portlet.ResourceRequest
(only accessible when processing an ResourceRequest)
resourceResponse
Object of type
javax.portlet.ResourceResponse
(only accessible when processing an ResourceResponse)
portletSession
Current PortletSession object
portletSessionScope
Map of PortletSession attributes in PORTLET_SCOPE. JSP Expression returns immutable Map, but Faces Expression returns mutable Map.
httpSessionScope
Mutable Map of PortletSession attributes in APPLICATION_SCOPE
portletPreferences
Current PortletPreferences object
portletPreferencesValues
Immutable Map containing entries equivalent to PortletPreferences.getMap()
mutablePortletPreferencesValues
Mutable Map of type Map<String, javax.portlet.faces.preference.Preference>. This EL variable provides read/write access to each portlet preference.

Example 28.11. 

This code allows you to edit the portlet preferences on the UI
<h:form>
	<h:inputText id="pref" required="true" value="#{mutablePortletPreferencesValues['userName'].value}" />
	<h:commandButton actionListener="#{myBean.savePref}" value="Save Preferences" />
</h:form>
In the backing bean, call the PortletPreferences.store() method.
Object request = FacesContext.getCurrentInstance().getExternalContext().getRequest();
PortletRequest portletRequest = (PortletRequest)request;
if (request instanceof PortletRequest) {
	try {
		PortletPreferences portletPreferences = portletRequest.getPreferences();
		portletPreferences.store();