JBoss Community Archive (Read Only)

Portlet Bridge 3.3

Reference Guide

Overview

Welcome to the Portlet Bridge User Guide. This document provides detailed explanation of the various parts of the project and how to use them in your own portlet project.

Configuration

Portlet Configuration

Here is an example portlet.xml to configure a JSF2 portlet:

<portlet-class>
  javax.portlet.faces.GenericFacesPortlet
</portlet-class>

<init-param>
  <name>javax.portlet.faces.defaultViewId.view</name>
  <value>/welcome.xhtml</value>
</init-param>

<init-param>
  <name>javax.portlet.faces.defaultViewId.edit</name>
  <value>/jsf/edit.xhtml</value>
</init-param>

<init-param>
  <name>javax.portlet.faces.defaultViewId.help</name>
  <value>/jsf/help.xhtml</value>
</init-param>

Only the javax.portlet.faces.defaultViewId.view init-param is mandatory. The edit and help init-param's are only required when your portlet requires the Edit and Help portlet modes.

Portlet 2.0 Schema

To have access to the latest Portlet 2.0 spec features, such as Events and Public Render Parameters, it's important to ensure that your portlet.xml contains the following schema definition:

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
  version="2.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd">

Preserving Request Parameters outside ActionRequest

By default the Portlet Bridge does not retain any Request Parameters that were received as part of an ActionRequest from the Portal. To ensure that Request Parameters from an ActionRequest are retained in the Bridge Request Scope until a RenderRequest, add the following init-param to portlet.xml:

<init-param>
  <name>javax.portlet.faces.preserveActionParams</name>
  <value>true</value>
</init-param>

Render Policy

Different JSF View Declaration Languages require different behavior from the 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 in web.xml.

If you're using Facelets:

Include the following in web.xml:

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

If you're using JSP:

Include the following in web.xml:

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

Supported Render Policies in Portlet Bridge:

  • 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 and if and only if an Exception is thrown then render 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. I.e. as if DEFAULT is set.

Disable Adding Resources to Portal Page Head

By default Portlet Bridge will add any JSF Resources for your portlet into the <head> section of the portal page the portlet is on, if the portlet container supports marking up the head of a page.

If you don't want any resources from your portlet being added to the <head> section of the portal page, simply add the following context param into web.xml of the portlet:

<context-param>
  <param-name>org.jboss.portletbridge.markupHead.enabled</param-name>
  <param-value>false</param-value>
</context-param>

Prevent Self-Closing Script Tags in Portal Page Head

There may be occasions where you may want to prevent script tags being added to the <head> of the Portal page that are self-closing, ie. <script ... />.

The Portlet Bridge is now able to alter the default behavior to convert a self-closing script tag to something like <script .... > </script> by inserting a blank comment
into the XML Document for the script element to prevent a self-closing tag. Enabling it requires you to add the following context param into web.xml:

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

Only Execute RESTORE_VIEW during Portlet Render

By default a Portlet Render Response will execute the full Faces Lifecycle before rendering the portlet content to be returned.

It's possible to disable this behavior by specifying the following context param in web.xml:

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

Disabling full execution of the Faces Lifecycle will break the functionality of some components, such as f:viewParam.

Save Bridge Request Scope after Render complete

By default, the Bridge Request Scope will no longer be retained on completion of a Render Request. This change will bring us more into line with how we feel JSF 2 portlets are developed and intended to be used, such as focusing on Ajax requests and interactions over full page refreshes.

It is possible to return to the behavior of previous Portlet Bridge versions by setting 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>

Or by setting 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>

Enable updating Bridge Request Scope after Ajax Request

The Portlet Bridge will no longer store updates to objects in the Bridge Request Scope that occurred during an Ajax request. This means that any JSF Managed Beans, or attributes set on the FacesContext, will no longer be updated after an Ajax request. Any subsequent re rendering of the portlet will show the values of these objects as they were before the Ajax request.

It is possible to revert to the previous behavior, of the data being stored in the Bridge Request Scope after an Ajax request, by setting the following context param in web.xml:

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

Disable saving Faces Messages after Ajax Request

If the above parameter is set to true, such that data is saved in the Bridge Request Scope after an Ajax request, it is possible to disable the saving of Faces Messages with the following context param in web.xml:

<context-param>
  <param-name>org.jboss.portletbridge.FACES_MESSAGES_STORED_ON_AJAX_REQUEST</param-name>
  <param-value>false</param-value>
</context-param>

Disabling the saving of Faces Messages after an Ajax request would be beneficial if your portlet has a mix of Ajax and Full Page requests, and you are not concerned with error messages resulting from an Ajax request disappearing if the portlet is refreshed.

Setting Session Id Parameter when Cookies are Disabled

To correctly generate portlet URLs when cookies are disabled by a browser, it is necessary to remove the Session ID parameter name from the URL to accurately determine which Faces view a URL should be directed at.

By default it assumes the parameter name is jsessionid, but this can be overridden by setting the following context param in web.xml:

<context-param>
  <param-name>org.jboss.portletbridge.SESSION_ID_PARAMETER_NAME</param-name>
  <param-value>mysessionparameter</param-value>
</context-param>

Revert to Full Component Namespaces

By default, the Bridge will shorten the namespace that is added as a prefix to JSF Component Ids. This change will improve both the time that portlets take to be rendered by JSF, as the ids are now shorter, and the amount of data being passed between client and server.

It is possible to return to the behavior of previous Portlet Bridge versions by setting the following initialization parameter in portlet.xml for a specific portlet:

<init-param>
  <name>org.jboss.portletbridge.COMPONENT_NAMESPACE_SHORTENED</name>
  <value>false</value>
</init-param>

Or by setting it for all portlets present within an archive by setting the following context parameter in web.xml:

<context-param>
  <param-name>org.jboss.portletbridge.COMPONENT_NAMESPACE_SHORTENED</param-name>
  <param-value>false</param-value>
</context-param>

JSF Portlet Development

Communicating between Portlets

Events

Send Event
Portlet Configuration

By default, the GenericFacesPortlet of the Bridge overrides the Event handling to dispatch all events to the Bridge. If you want to explicitly set this value, to prevent confusion, add the following to portlet.xml within its' <portlet> section:

<init-param>
  <name>javax.portlet.faces.autoDispatchEvents</name>
  <value>true</value>
</init-param>

When the entire portlet is written in JSF, this init-param must be set to true. Only set it to false when your portlet uses a mix of view technologies.

The portlet also needs to specify that it is able to publish an event to the portal by adding the below to portlet.xml within its' <portlet> section:

<supported-publishing-event>
  <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
</supported-publishing-event>

This defines an event namespace and name to use when publishing the event.

Finally the portlet application needs to specify how the event namespace and name link to an actual type within the application. For the above publishing event definition, the portlet.xml would need the following:

<event-definition>
  <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
  <value-type>org.jboss.example.booking.BookingEvent</value-type>
</event-definition>

The qname above is identical to that used earlier to create the link between a qname and class type

Event Type

To publish an event we need a type to represent the actual object that will be attached to the event. Here is an example event type:

@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;
  }
}

The type needs the @XmlRootElement annotation so that the event can be serialized into a JAXB object for publishing.

Dispatch Event

To dispatch the event to other portlets within the portal, you can do something similar to the below within a Bean method, such as a 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));
  }

Receive Event
Portlet Configuration

For a portlet to receive an event, it needs to specify the following within portlet.xml within its' <portlet> section:

<init-param>
  <name>javax.portlet.faces.bridgeEventHandler</name>
  <value>org.jboss.example.booking.BookingEventHandler</value>
</init-param>

The portlet also needs to specify that it is able to receive an event from the portal by adding the below to portlet.xml within its' <portlet> section:

<supported-processing-event>
  <qname xmlns:jbp="urn:jboss:portal:samples:event">jbp:BookingEvent</qname>
</supported-processing-event>

As when defining the portlet that can publish an event, the portlet that can receive that event needs to define the link between the qname and event type. The identical <event-definition> specified in Send Event can be used.

Event Handler

To process the Event within a portlet a handler, that was defined within portlet.xml as seen earlier, needs to be created with content similar to the following:

public class BookingEventHandler implements BridgeEventHandler {
  public EventNavigationResult handleEvent(FacesContext context, Event event) {
    // Process event payload as appropriate
  }
}

Public Render Parameters

Public Render Parameters (or PRPs) 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).

Public Render Parameters can only be used to set/retrieve a String value, and not an object as Events can.

Portlet Configuration

The portlet that sets the Public Render Parameter, and also the one receiving it, need the following defined within their portlet.xml:

<portlet>
  ...
  <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>

The portlet that will be retrieving the Public Render Parameter also needs to define a handler in the portlet.xml as below:

<init-param>
  <name>javax.portlet.faces.bridgePublicRenderParameterHandler</name>
  <value>org.jboss.example.booking.BookingPRPHandler</value>
</init-param>
Set Parameter

Setting the Public Render Parameter only needs a Bean method, most likely called as part of an Action from the UI, that sets the render parameter onto the response, as below:

Object response = FacesContext.getCurrentInstance().getExternalContext().getResponse();
if (response instanceof StateAwareResponse) {
  StateAwareResponse stateResponse = (StateAwareResponse) response;
  stateResponse.setRenderParameter("hotelName", "Name of Hotel");
}
Retrieve Parameter

The portlet(s) retrieving the parameter will need a Bean with a getter/setter for the parameter so it can be set by the Bridge, such as below:

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 Public Render Parameter you want to retrieve and which Bean you want it set on. If the above Bean is defined with a EL name of bookingPRP, then the faces-config.xml would be:

<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>

In the preceding example, the namespace associated with the "bridge" prefix is "http://jboss.org/portletbridge".

 

bookingMapPortlet:hotelName as the parameter above needs to represent the name of your portlet (within portlet.xml) and name of the render parameter concatenated with a colon. 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 their model updated. Specifying the portlet name as well restricts model updates to just that portlet.

Finally, we need the handler that was specified in the portlet.xml earlier to process the updates to the model as a result of the Public Render Parameter. Below is an example handler:

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

    if(null != bean) {
      System.out.println("******processUpdates from BookingPRPHandler: " + bean.getHotelName());
    }
  }
}

Portlet Session

It's possible to share data with other portlets, within the same portlet application, using name/value pairs within the PortletSession. Use the following code to set the name/value data:

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);
    }
  }

A portlet application is defined as being a single Web Archive. All portlets that are part of the same WAR are considered to be within the same portlet application.

Then in your JSP or Facelets page you can retrieve the value using:

#{httpSessionScope['your parameter name']}

For more information about which EL variables are provided by the Bridge, see Provided EL Variables

Resource Serving

When using resources from your JSF portlet it's important to ensure that they are accessed in a way that allows the Portlet Bridge to generate an appropriate Portal URL to the resource being requested.

Using JSF 2 tags to access resources, such as <h:outputScript>, <h:outputStylesheet>, <h:graphicImage> and <h:link> all use JSF 2 mechanisms for generating the URL, and so should generate appropriate Portal URLs.

However, in some situations it may not be possible to use any of the above tags, such as image urls within css files, importing a css file from another, etc. In these situations the correct way to reference a resource is to place it within the resources folder of your web application so that the resource can be retrieved using JSF 2 Resource Handling such as:

#{resource['/stylesheet.css']}

stylesheet.css would be present in the root of the resources folder as it does not specify a resource library

Use of #{resource} to retrieve the content is especially important for @import within css files.

Navigation

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, but once processed it then removes this parameter from the query string.

The following 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>

Linking and Redirects

Linking to Facelets page within same Portlet

When linking to any Facelets page within your portlet web application, you may use the following:

<h:outputLink value="#{facesContext.externalContext.requestContextPath}/home.xhtml">
  <f:param name="javax.portlet.faces.ViewLink" value="true"/>
    navigate to the test page
  </h:outputLink>

Redirect to External Page or Resource

To link to a non JSF View (such as jboss.org), you may use the following:

<h:commandLink actionListener="#{yourBean.yourListener}">
  <f:param name="javax.portlet.faces.DirectLink" value="true"/>
    navigate to the test page
</h:commandLink>

With a backing Bean that has the following:

public class YourBean {
  public void yourListener() {
    FacesContext.getCurrentInstance().getExternalContext().redirect("http://www.jboss.org");
  }
}

Provided EL Variables

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

EL Object Name

Description

portletConfig

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 EventResponse)

renderRequest

Object of type javax.portlet.RenderRequest (only accessible when processing a RenderRequest)

renderResponse

Object of type javax.portlet.RenderResponse (only accessible when processing a RenderResponse)

resourceRequest

Object of type javax.portlet.ResourceRequest (only accessible when processing a ResourceRequest}

resourceResponse

Object of type javax.portlet.ResourceResponse (only accessible when processing a 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.

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 needs to be added to your facelet page:

xmlns:pbr="http://jboss.org/portletbridge"

renderURL

Using the renderURL tag it's possible to generate a Portlet Render URL that would enable switching between Portlet Modes, such as this:

<pbr:renderURL var="renderUrl" portletMode="edit">
</pbr:renderURL>
<h:outputLink value="#{renderUrl}">Edit Mode</h:outputLink>

namespace

The namespace is particularly useful for prefixing JavaScript functions within a given portlet to ensure that the JavaScript function name doesn't 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>

CDI Portlet Development

Configuration

There are a couple of steps to enabling CDI for JSF2 portlets that use Portlet Bridge.

This is only required when deploying to servers that use CDI 1.0

Artifacts

First is to add the following dependency to your pom.xml to add the portlet integration library for CDI:

CDI Portlet Integration Maven Artifacts for JSF2
<dependency>
    <groupId>org.gatein</groupId>
    <artifactId>cdi-portlet-integration</artifactId>
    <version>1.0.3.Final</version>
</dependency>
Deploying to GateIn

When deploying to GateIn, the portlet integration library for CDI is automatically included for JSF2 portlets that use CDI.

So we need to ensure the dependency is marked as provided in our pom.xml:

<dependency>
    <groupId>org.gatein</groupId>
    <artifactId>cdi-portlet-integration</artifactId>
    <version>1.0.3.Final</version>
    <scope>provided</scope>
</dependency>
Disable automatic inclusion of CDI integration library

If you still want to include the CDI integration library in your application you can disable the automatic inclusion of it. This could, for example, be useful if you need to use a different version of the CDI integration library.

To do that, just specify the org.gatein.cdi.DISABLE_CDI_INTEGRATION context param in your web.xml file like this:

<context-param>
    <param-name>org.gatein.cdi.DISABLE_CDI_INTEGRATION</param-name>
    <param-value>true</param-value>
</context-param>

Portlet Filter

Add the following portlet filter definition into your portlet.xml so that Portlet Request objects are wrapped appropriately for CDI usage:

<filter>
    <filter-name>PortletCDIFilter</filter-name>
    <filter-class>org.gatein.cdi.PortletCDIFilter</filter-class>
    <lifecycle>ACTION_PHASE</lifecycle>
    <lifecycle>EVENT_PHASE</lifecycle>
    <lifecycle>RENDER_PHASE</lifecycle>
    <lifecycle>RESOURCE_PHASE</lifecycle>
</filter>

Then add to portlet.xml the activation of the above filter for each portlet that requires CDI:

<filter-mapping>
    <filter-name>PortletCDIFilter</filter-name>
    <portlet-name>[Name of your portlet as defined in portlet-name]</portlet-name>
</filter-mapping>

If you need to also wrap Portlet Response objects, then use the org.gatein.cdi.PortletCDIResponseFilter instead.

Multipart Requests

The default is now to not wrap multipart requests with any Http wrapper. If you need to have multipart requests wrapped so that they can be used with CDI, you can re-enable the wrapping by adding an init-param for org.gatein.cdi.ENABLE_MULTIPART_REQUEST_WRAPPING to the portlet filter definition in portlet.xml, such as:

<filter>
    <filter-name>PortletCDIFilter</filter-name>
    <filter-class>org.gatein.cdi.PortletCDIFilter</filter-class>

    <lifecycle>ACTION_PHASE</lifecycle>
    <lifecycle>EVENT_PHASE</lifecycle>
    <lifecycle>RENDER_PHASE</lifecycle>
    <lifecycle>RESOURCE_PHASE</lifecycle>

    <init-param>
      <name>org.gatein.cdi.ENABLE_MULTIPART_REQUEST_WRAPPING</name>
      <value>true</value>
    </init-param>
</filter>

Which CDI Scopes are available?

For CDI 1.0 the following scopes are available for use within JSF2 portlets:

  • @ApplicationScoped

  • @SessionScoped

  • @ConversationScoped

There are some possible pitfalls with CDI that are explained below.

Conversation Scope

Transient Conversations

Any beans that are defined as @ConversationScoped, but which remain transient, that store data during the ActionRequest will not have that data accessible within the bean during a subsequent RenderRequest. As the Portlet lifecycle uses separate servlet requests to represent ActionRequest and RenderRequest, it results in the conversation context being deactivated at the end of ActionRequest and all transient conversations are destroyed.

Long Running Conversations

The only difference in behavior between a JSF2 application and a JSF2 portlet is that there can be problems if a long running conversation is ended within a RenderRequest.

For example, when a long running conversation is ended during RenderRequest CDI will destroy the conversation at the end of the JSF render response phase, but the id of the conversation will still be present within the Portlet Bridge scope. As the id of the conversation is retained by the Portlet Bridge, if the user refreshes the portlet page and a RenderRequest is sent to the portlet, the previously saved conversation id will be attempted to be activated by CDI but the associated conversation context does not exist.

One work around for the above problem is to not end a long running conversation. Instead of always calling begin() on the injected conversation, only call it when isTransient() is true. This will prevent a failure in converting a transient to long running conversation.

If it's possible for your portlet to only end a long running conversation within an ActionRequest, then you won't experience the above problem.

Ajax calls

As the conversation id parameter, cid, is set as a request parameter on the url, each time we convert a conversation from long running to transient, or vice versa, we need to ensure that any urls that our portlet uses are updated. This ensures that the latest value for the conversation id parameter, or lack of one if we converted a conversation to transient, are present on any links the user clicks. Not doing so can result in problems such as:

  • Long running conversations being lost because the conversation id parameter was not present on subsequent requests to the portlet

  • A CDI container throwing ContextNotActiveException because the conversation id parameter that was present on the link is no longer present as a valid conversation for use.

In most cases its simply a matter of adding more ids to the render attribute of any ajax component that will start or end a long running conversation, so that the ids of all components that contain url links to actions using a conversation or links to pages of the portlet are included in the list to be re rendered.

Request Scope

@RequestScoped will work within a CDI and JSF2 portlet, but due to the portlet lifecycle you need to be aware that data from an ActionRequest will not be retained for use in a RenderRequest.

There are plans to implement a replacement for @RequestScoped specifically for use within portlets, but it is not currently available.

DeltaSpike Example

Using DeltaSpike within your CDI/JSF portlet is a very straightforward process. The most important thing to note about using DeltaSpike in a portlet, is to disable the client window render mode by setting ClientWindowRenderMode.NONE.

To see DeltaSpike in action in a portlet, first we need to get the JSF/CDI example application for DeltaSpike from https://github.com/apache/deltaspike/tree/master/deltaspike/examples/jsf-examples.

We then need to add the following Maven dependencies to the project:

<dependency>
    <groupId>org.jboss.portletbridge</groupId>
    <artifactId>jsf2-depchain</artifactId>
    <version>3.2.0.Final</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>org.gatein</groupId>
    <artifactId>cdi-portlet-integration</artifactId>
    <version>1.0.1.Final</version>
</dependency>

Modify SampleClientWindowConfig to return ClientWindowRenderMode.NONE instead of ClientWindowRenderMode.CLIENTWINDOW.

Finally add the portlet.xml from https://github.com/portletbridge/portletbridge/tree/master/examples/deltaspike-portlet to make it accessible as a portlet.

Tips

Excluding Attributes from Bridge Request Scope

When your application uses request attributes on a per request basis and you do not want that particular attribute to be managed in the Bridge Request Scope, you must use the following configuration in your faces-config.xml to have them excluded.

<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>

Above you will see that any attribute namespaced as foo.bar or any attribute beginning with foo.baz. will be excluded from the Bridge Request Scope and only be used per that application's request.

In the preceding example, the namespace associated with the "bridge" prefix is "http://jboss.org/portletbridge".

JSF Facelet View

When creating a JSF Facelet view document it's common to wrap the content with:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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">
...
</html>

As 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:

<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">
...
</f:view>

This results in only the relevant content of the portlet markup being returned to the page.

Although it is not relevant to a portlet, it's important to include <h:head> and <h:body> elements so that JSF can process the Facelet correctly.

Error Handling

To display error pages for specific exceptions in your JSF portlet, you need web.xml content such as:

<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 then 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

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

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-11 12:28:51 UTC, last content change 2012-12-14 16:00:18 UTC.