Steps for JSF Upgradation from version 6.0 to 7.0 for portlet projects

2 comments



For the JSF up-gradation first step is to import the related jars into the “WebContent/WEB-INF/lib” directory of the portal project.
By creating a sample project in RSA V7.0 and by doing the following steps required jars can be generated and imported automatically.

1. Make sure the portlet API (JSR 168 or IBM Portlet) matches what’s in the portlet project that is being updated. In addition make sure the target run time is the desired one because different libraries are copied into the project for different target runtimes.

2. Drag and drop an Input - Rich Text Editor and a Panel - Tabbed component from the palette onto the new Faces page. In both cases respond "Yes" when prompted to add new resources. Drag and drop the “Person Link” component from the “Portlet” drawer of the palette onto the page.

3. For each existing Faces portlet project that you want to update, do the following:

In Project Explorer, expand an existing project to show the files in the WebContent/WEB-INF/lib/ folder. Locate and delete if any of the following JAR files are present in this directory:
jsf-api.jar
jsf-ibm.jar
jsf-impl.jar
jsf-wp.jar
jsf-portlet.jar
odc-jsf.jar
DocEditor.jar
rte.jar

Copy all of the JAR files from the WebContent/WEB-INF/lib directory of the sample project and paste them into your original project in the same location. Some configurations will not require all of these JAR files to be present in the project; but several new files have been added in V7.0. So copying all of them is the best general solution.

Jsf-portletbridge.jar is the most important jar for V7.0 which will be generated only in RSA 7.0 not in RAD V6.0

To update the 168 JSR portlet project form V6.0 to V7.0 manually, following steps should be done:-

  • In portlet.xml if the class name is com.ibm.faces.webapp.FacesGenericPortlet, change it to com.ibm.faces.portlet.FacesPortlet
  • If the target portlet project contains subclasses of FacesGenericPortlet, it needs to be updated to contain the subclasses of FacesPortlet. i.e. if the portlet extends FacesGenericPortlet means it should be changed to FacesPortlet. 
  • Remove the following faces context factory from faces-config.xml: com.ibm.faces.context.PortletFacesContextFactoryImpl 
  • Change variable resolver from com.ibm.faces.application.PortletVariableResolver to com.ibm.faces.portlet.PortletVariableResolver in faces-config.xml
  • For smooth migration the following steps should be done:
  • <hx:jspPanel> no longer supports the “styleClass” and “style” attributes.

<hx:jspPanel id="someID" styleClass="jspPanel"> will throw the following exception:
java.lang.NoSuchMethodError: com.ibm.faces.taglib.html_extended.JspPanelTag.setStyleClass(Ljava/lang/String;)


To fix it, remove the styleClass attribute. “jspPanel” normally does nothing.If you need the style retained, wrap the code in a div tag.
 
Use instance variable in the getter methods for backing beans to obtain the current value. Code such as the following will have unpredictable results.
tempCurrValue = (String)getSessionScope().get(“IDOfUIComponent”) 

The <h:commandLink> may have different output for the link text. In the old jsf runtime, the output would be “Text2”. In the new runtime, the output would be “Text1Text2”
<h:commandLink id="link" immediate="true" action="#{pc_someAction.doLink1Action}"
title="someTitle" value="Text1">
<h:outputText id="2" value="Text2" escape="false"></h:outputText>
</h:commandLink>

Usually this condition occurs by mistake. Remove “value=Text1” to fix the exception. Cookies can no longer be obtained with the following code

FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext=facesContext.getExternalContext();
HttpServletRequest servletRequest=(HttpServletRequest)externalContext.getRequest()
Cookie[] cookies=servletRequest.getCookies();

Cookies can only be obtained using:

portletRequest.getProperty("Cookie");

This method will return a semi-colon delimited String containing all the cookies.

A helper class like following is recommended to parse the String:
/*
* This class helps portlets read cookies
*/

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.portlet.PortletRequest;
import javax.servlet.http.Cookie;

/**
* *
* This method takes the PortletRequest request object, gets the Cookie String, and parses it into an array of Cookies, and returns the array
*
* @param PortletRequest
*
* @return Cookie[] - an array of Cookies parsed from the request header
*/

public class CookieHelper {
public static Cookie[] getCookies(PortletRequest request) {
// retrieve a semi colon delimited String that contains the cookies
String cookieString = request.getProperty("Cookie");
List cookieList = new ArrayList();
// break up the String to the key/value pairs for each cookie
StringTokenizer st = new StringTokenizer(cookieString, "; ");
while (st.hasMoreTokens()) {
String tempString = st.nextToken();
// split off the cookie name from the cookie value
String[] tempArray = tempString.split("=");
if (tempArray[0] != null && !tempArray[0].equals("")
&& tempArray[1] != null && !tempArray[1].equals("")) {
// create a cookie, [0] is the name, [1] is the value
cookieList.add(new Cookie(tempArray[0], tempArray[1]));
}
}

// convert the cookie list to an Cookie array and return it
return (Cookie[]) cookieList.toArray(new Cookie[cookieList.size()]);
} // end getCookies()
/**


This method takes the PortletRequest request object and a Cookie name, gets the Cookie String, and parses the String to get the value for the specified Cookie, and returns the value as a String
/* @param PortletRequest
* @param String - Representing the name of the cookie
*
* @return String - the value of the Cookie if found, otherwise, "" if no cookies is found
*/


public static String getCookie(PortletRequest request, String cookieName){
// retrieve a semi colon delimited String that contains the cookies
String cookieString = request.getProperty("Cookie");
String cookieValue = "";
// parse the string to get the value for the cookie
if (cookieString.indexOf(cookieName) >= 0){
int startValue = cookieName.length() + 1 + cookieString.indexOf(cookieName);
int endValue = cookieString.length();
if (cookieString.indexOf(";", startValue) > 0){
endValue = cookieString.indexOf(";", startValue);
}
cookieValue = cookieString.substring(startValue, endValue);
}
return cookieValue;
}
}

The “rendered” attribute in tags must be backed by a method that returns a Boolean value. String x = “false”; no longer works.

Request parameters that are sent to the action phase are no longer available in the render phase. If the parameters are needed in the render phase, they need to be explicitly passed in the processAction() method or the doAction() method in the bean.
ActionResponse actionResponse = (ActionResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
actionResponse.setRenderParameter(MAX_LINKS_EXCEEDED,"true"); 

Request scoped beans are no longer passed from the action phase to the render phase if they contain non-serializable instance variables. A common symptom of this is the values in text fields no longer being retained after a submit.

public class SearchView extends PageCodeBase implements Serializable {
protected transient HtmlSelectOneMenu contentType

Problems encountered during JSF upgradation:-

Issues
/Solution 

If there are dropdown in upgraded portlet and changing the value in that dropdown throws script error or portlet unavailable.

Remove the implements Serializable and transient from its page code.

Portlet becomes blank that is the values in the cookies are not retained.


Refer point number 4 related to cookies above.

The .classpath file should be updated to reflect changes to the jar files in the WEB-INF/lib directory.

2 comments:

Anonymous said...

Nice artical, one quick question... do you think we can assign the ID attribute of a tag with expression.



is this is possible with IBM JSF? if yes which combination of Portal version and JSR API allows it. Is there any way we can change the JSF version used by Portlet.

Regards,
Rajesh

Arun Khurana said...

Hi Rajesh,
You can do that but you need to make sure that ID's generated by the expression are unique otherwise you'd end up with duplicate component Id's, which wouldn't help you anyway. Also I don't think it has to do anything with JSR API. For changing the JSF version, simply replace the old version JSF jars with new one.

Post a Comment

Recent Posts

Popular Posts

© 2011-2019 Web Portal Club