Excluding Attributes from the 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 extended bridge request scope, you must use the following configuration in your faces-config.xml. Below you will see that any attribute namespaces as foo.bar or any attribute beginning with foo.baz(wildcard) will be excluded from the bridge request scope and only be used per that application’s request.
<application>
<application-extension>
<bridge:excluded-attributes>
<bridge:excluded-attribute>foo.bar</bridge:excludedattribute>
attribute>
<bridge:excluded-attribute>foo.baz.*</bridge:excludedattribute>
attribute>
</bridge:excluded-attributes>
</application-extension>
</application>
“From The Spec...” To support Faces, the bridge is responsible for encoding port let (action) responses in a manner that allows it (and Faces) to reestablish the request environment that existed at the end of the corresponding action phase during subsequent render requests that are identified as pertaining to that action (or event). The term used to describe the scope of this managed data is the bridge request scope.
Supporting PortletMode Changes
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 port let mode on the underlying port let actionURL or response. Once processed, it then removes this parameter from the query string. This means the following navigation rule causes one to render the \edit.jspx viewId in the port let edit mode:
<navigation-rule>
<from-view-id>/register.jspx</from-view-id>
<navigation-case>
<from-outcome>edit</from-outcome>
<to-view-id>/edit.jspx?javax.portlet.faces.PortletMode=edit</
to-view-id>
</navigation-case>
</navigation-rule>
PortletMode changes require an ActionRequest, so they cannot change modes during an Ajax or ResourceRequest.
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 port let 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>
You should always wildcard your viewId’s as shown in the above from-view-id. Developers are encouraged to use such wildcarding to ensure they execute properly in the broadest set of bridge implementations.
Clearing The View History When Changing Portlet Modes
By default, the bridge remembers the view history when you switch to a different port let 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>
General Error Handling
If you’re developing a Seam port let, you can continue to use pages.xml for all error handling.
The following configuration may be used to handle exceptions. This is also useful for handling session timeout and ViewExpiredExceptions. Pay attention to the location element. It must contain the /faces/ mapping to work properly.
<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>
Custom Ajax Error Handling
By default, error handling is sent to a standard servlet page for Ajax requests. To handle the error inside the port let, use the following javascript:
<script type=”text/javascript”>
A4J.AJAX.onError = function(req,status,message){
window.alert(“Custom onError handler “+message);
}
A4J.AJAX.onExpired = function(loc,expiredMsg){
if(window.confirm(“Custom onExpired handler “+expiredMsg+” for a
location: “+loc)){
return loc;
} else {
return false;
}
}
</script>
Also, add the following to web.xml.
<context-param>
<param-name>org.ajax4jsf.handleViewExpiredOnClient</param-name>
<param-value>true</param-value>
</context-param>
Remember to provide a link to the normal flow of your JSF application from your error page. Otherwise, the same error page will be displayed forever.
Communication Between Your Portlets
There are roughly 4 different ways to send messages, events, and parameters between port lets which are contained in different ears/wars or contained in the same war. The Portlet Container does not care if you have 2 port lets in the same war or if they are separated, because each port let has a different HttpSession.
Of course, with the Portlet 2.0 spec, the recommended way to share a parameter or event payload between 2 or more port lets are the Section 3.4.2, “Public Render Parameters” and Section 3.4.1, “Sending and Receiving Events” mechanisms. This allows you to decouple your application from surgically managing objects in the PortletSession.APPLICATION_SCOPE.
But, if these do not meet your use case or you have a different strategy, you can use one of the following methods.
Storing Components in PortletSession.APPLICATION_SCOPE
Sometimes, it makes sense to store your Seam components in the port let APPLICATION_SCOPE. By default, these objects are stored in the PORTLET_SCOPE; but with the annotation below, you can fish this class out of the PortletSession and use its values in other port lets across different Seam applications.
@PortletScope(PortletScope.ScopeType.APPLICATION_SCOPE)
Then you would pull the state full object from the session:
YourSessionClass yourSessionClass = (YourSessionClass)
getRenderRequest().getAttribute(“javax.portlet.p./default/
seamproject/seamprojectPortletWindow?textHolder”);
Using the PortletSession
If you need to access the PortletSession to simply share a parameter/value across multiple port lets, you can use the following to do so.
Object objSession = FacesContext.getCurrentInstance().
getExternalContext().
getSession(false);
try
{
if (objSession instance of 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’]}
Linking to Portlet/JSF Pages Using h:outputink
For linking to any JSF/Facelets page within your port let 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>
Redirecting to an External Page or Resource
To link to a non JSF view (i.e. jboss.org), you can use the following parameter.
<h:commandLink actionListener=”#{yourBean.yourListenr}”>
<f:param name=”javax.portlet.faces.DirectLink” value=”true”/>
navigate to the test page
</h:commandLink>
Then in your backing bean, you must call a redirect().
FacesContext.getCurrentInstance().
getExternalContext().redirect(“http://www.jboss.org”);
Using Provided EL Variables
All EL variables found in the JSR-329 (Portlet 2.0) specification are available in the JBoss Portlet Bridge. For example, you can use the following to edit the port let preferences on the UI.
<h:form>
<h:inputText id=”pref” required=”true” value=”#{mutablePortletPrefe
rencesValues[‘userName’].value}” />
<h:commandButton actionListener=”#{myBean.savePref}” value=”Save
Preferences” />
</h:form>
Then in your backing bean, you must call the PortletPreferences.store() method.
Object request = FacesContext.getCurrentInstance().
getExternalContext().getRequest();
PortletRequest portletRequest = (PortletRequest)request;
if (request instance of PortletRequest) {
try {
PortletPreferences portletPreferences = portletRequest.
getPreferences();
portletPreferences.store();
Remote Portlet Navigation Using Portlet Events
When you send events, you can also leverage the EventNavigationResult and return a JSF navigation rule. For example, by returning:
new EventNavigationResult(“fromAction”,”Outcome”);
The fromAction can be a wildcard “/*” or a nav rule defined in your faces-config.xml and outcome can be the from-outcome node defined in the faces-config.xml navigation rule.
{{ parent.title || parent.header.title}}
{{ parent.tldr }}
{{ parent.linkDescription }}
{{ parent.urlSource.name }}