This may be used in scenario when the user needs to reach the default JSF view when a portal page is rendered.
In a step-by-step fashion the solution is the following:
set up an extension class to be used by the portlet
public class ClearStateFacesPortlet extends GenericFacesPortlet {
}
and use it when creating the portlet
<portlet-class>com.oracle.jsf.ClearState.ClearStateFacesPortlet</portlet-class>
set up the portlet to clear its state
add the following init parameter in portlet.xml file:
<init-param>
<name>com.oracle.jsf.CLEAR_STATE_ENABLED</name>
<value>true</value>
</init-param>
This parameter tells the portlet to clear the current state and set up the inital view. This enables the developer to put more portlets on the same portal page some of them having the state cleared out and some keeping their current state.
set up a event to be received by the portlet
Add the following code to the portlet.xml file in order to define the event:
<event-definition>
<qname xmlns:x="http://oracle.com/clearStateEvent">x:clear.state</qname>
<value-type>java.lang.String</value-type>
</event-definition>
Also add the code to the same file for the portlet in order to receive the event:
<portlet>
............
<supported-processing-event>
<qname
xmlns:x="http://oracle.com/clearStateEvent">x:clear.state</qname>
</supported-processing-event>
<portlet>
set up event processing method for the portlet
@ProcessEvent(qname = "{http://oracle.com/clearStateEvent}clear.state")
public void processClearStateEvent(EventRequest eRequest, EventResponse eResponse)
throws PortletException, IOException {
Event event = eRequest.getEvent();
String eventValue = (String) event.getValue();
String sIsClearStateEnabled = getInitParameter(ClearStatePortletConstants.CLEAR_STATE_PORTLET_PARAM_NAME);
if (!sIsClearStateEnabled.equalsIgnoreCase("true")) {
eResponse.setRenderParameters(eRequest);
return;
}
String sReceivedPortletID = null;
String sReceivedURLValue = null;
try {
StringTokenizer st = new StringTokenizer(eventValue, "@");
sReceivedPortletID = st.nextToken();
sReceivedURLValue = st.nextToken();
} catch (Exception e) {
eResponse.setRenderParameters(eRequest);
return;
}
if (!sReceivedPortletID.equals(eRequest.getWindowID())) {
eResponse.setRenderParameters(eRequest);
return;
}
if (!sReceivedURLValue.equalsIgnoreCase("true")) {
eResponse.setRenderParameters(eRequest);
return;
}
eResponse.setRenderParameter(
ClearStatePortletConstants.CLEAR_STATE_RENDER_PARAM_NAME + "."
+ eRequest.getWindowID(), eventValue);
}
The above function will be called whenever the specified event is fired
set up doView() method that will perform the 'magic'
@Override
protected void doView(RenderRequest request, RenderResponse response)
throws PortletException, java.io.IOException {
if (request.getParameter(ClearStatePortletConstants.CLEAR_STATE_RENDER_PARAM_NAME + "." + request.getWindowID()) != null) {
request.setAttribute("javax.portlet.faces.viewId", getInitParameter(ClearStatePortletConstants.JSF_DEFAULT_VIEW_PARAMETER));
}
super.doView(request, response);
}
When the portlet is going to be rendered after the event was processed the JSF implementation will know what JSF view will render.
set up page links to activate the 'magic'
In order to trigger the event two solutions are possible:
- use portlet backing file (weblogic specific)
@Override
public boolean handlePostbackData(HttpServletRequest request,
HttpServletResponse response) {
String urlParameterValue = null;
String queryString = request.getQueryString();
int firstIndex = queryString.indexOf(ClearStatePortletConstants.CLEAR_STATE_URL_PARAM_NAME);
int secondIndex;
if (firstIndex != -1) {
firstIndex = firstIndex + ClearStatePortletConstants.CLEAR_STATE_URL_PARAM_NAME.length() + 1;
secondIndex = queryString.indexOf("&", firstIndex);
if (secondIndex == -1)
secondIndex = queryString.length();
urlParameterValue = queryString.substring(firstIndex, secondIndex);
if (urlParameterValue.equalsIgnoreCase("true")) {
PortletBackingContext.getPortletBackingContext(request).fireCustomEvent(new QName("http://oracle.com/clearStateEvent","clear.state"), PortletBackingContext.getPortletBackingContext(request).getInstanceLabel()+"@"+urlParameterValue);
}
}
return super.handlePostbackData(request, response);
}
- use JSF managed beans
//get the URL parameter and check its value and if it is true call the below function with the eventPayload=<portlet_instance_ID>@true
public void sendEvent(String eventPayload)
{
FacesContext fc = FacesContext.getCurrentInstance();
Object obj = fc.getExternalContext().getResponse();
if (obj instanceof ActionResponse){
ActionResponse ar = (ActionResponse) obj;
ar.setEvent(new QName("http://oracle.com/clearStateEvent","clear.state"),eventPayload );
}
}
both above solutions are possible only if the URL contains the parameter named as in ClearStatePortletConstants.CLEAR_STATE_URL_PARAM_NAME. In order to have all portal pages having this URL parameter you can edit the default URL template in the file beehive-url-template-config.xml as following:
<url-template>
<name>default</name>
<value>
http://{url:domain}:{url:port}/{url:path}?{url:queryString}{url:currentPage}&com.oracle.jsf.CLEAR_STATE=true
</value>
</url-template>
All of this will work if the JSR 329 bridge implementation used by WLP 103.2 is informed to let event processing for the portlet container as per following parameter set up in web.xml file:
<context-param>
<param-name>javax.portlet.faces.autoDispatchEvents</param-name>
<param-value>false</param-value>
</context-param>
The constants used in this example are the followings:
public class ClearStatePortletConstants {
public static final String CLEAR_STATE_URL_PARAM_NAME = "com.oracle.jsf.CLEAR_STATE";
public static final String CLEAR_STATE_RENDER_PARAM_NAME = "com.oracle.jsf.render.CLEAR_STATE";
public static final String CLEAR_STATE_PORTLET_PARAM_NAME = "com.oracle.jsf.CLEAR_STATE_ENABLED";
public static final String CLEAR_STATE_PORTLET_PARAM_DEFAULT_VALUE = "false";
public static final String JSF_DEFAULT_VIEW_PARAMETER = "javax.portlet.faces.defaultViewId.view";
}