<init-param> <name>javax.portlet.faces.autoDispatchEvents</name> <value>true</value> </init-param>
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
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.
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)); }
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.
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 (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.
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>
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"); }
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>
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()); } } }
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