InterPortlet Communication - Best Practice Matrix

I published "InterPortlet Communication - Best Practice Matrix" on IBM portal wiki.
This IPC Matrix helps to choose best practice for various scenarios of IPC.


Persisting user navigational states in WPS 7

You might have come across to situations where you would want WPS to persist user navigational states like

Portlet states:

    Normal
    Minimized
    Maximized

Portlet modes:

    config
    edit_defaults
    edit
    view
    help

Page selection:

    The last page that was active before the user logged out.


With the persistent session state feature, portal users can resume and continue a previously interrupted working session at the same state where they left the session. When the user logs out or the session times out, the portal stores the current navigational state into the database.


Resuming the session state is only possible if either the portal theme login link or WebSphere Application Server TAI based authentication is used to login to the portal.

Please have a look at detail article at Configuring user session persistance

How to know what all objects are stored in session at any point of time


You might want to know at any point of time that how many objects are stored in session along with their size. This would be most useful when you are analyzing application performance or working on performance tuning area.
This would also be useful in debugging when your application is throwing java.io.NotSerializableException.


There is a servlet called com.ibm.ws.webcontainer.httpsession.SessionInspectServlet that ships with WAS located in com.ibm.ws.webcontainer.jar. This jar is placed under <WPS_ROOT>/AppServer/plugins/.   
SessionInspectorServlet  can be used to list down what all objects are stored in session along with size of the objects.



In order to use SessionInspectServlet, you would need to enable “Serving servlets by class name”, you can set this value in the ibm-web-ext.xmi
By default this value is true, you can see sample ibm-web-ext.xmi file below and can see that serveServletsByClassnameEnabled value is true.

<?xml version="1.0" encoding="UTF-8"?>
<webappext:WebAppExtension xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:webappext="webappext.xmi" xmi:id="WebAppExtension_1320397630802" reloadInterval="3" reloadingEnabled="true" additionalClassPath="" fileServingEnabled="true" directoryBrowsingEnabled="false" serveServletsByClassnameEnabled="true">
  <webApp href="WEB-INF/web.xml#WebApp_ID"/>
</webappext:WebAppExtension>


To list down session objects stored in session, you would required to hit below URL
 
http://localhost:10039/wps/<context-root>/SessionInspector/servlet/com.ibm.ws.webcontainer.httpsession.SessionInspectServlet

here, context root would be context root of your application. You can specify this while installing your WAR through portal admin console OR you can also find out this value inside application.xml located under <WPS_ROOT>/wp_profile/installedApps/<NODE>/<EAR NAME>/META-INF/
 
You would see list of your session objects and their size as shown in the screen shot.


How to get HttpServletRequest and HttpServletResponse from portlet request

There are some scenario when you want to get httpServletRequest or httpServletReponse from portletRequest.

IBM provides an utility class which gives you what you are looking for.

Yes, there is a PortletUtil class available in the com.ibm.ws.portletcontainer.portlet package, through which you can directly get httpServletRequest, httpServletResponse, ServletContext and many  more servlet object you want.


Code to get HttpServletRequest from  portletRequest/renderRequest/actionRequest.

HttpServletRequest httpServletRequest =  PortletUtils.getHttpServletRequest(renderRequest);

There are couple of utility methods available in PortletUtil which  gives you ServletContext, ServletConfig, PortletWindow, PortletApplicationDefinition etc.

How to reset JSF Portlets to initial state

For a JSF based portlet, if you have a scenario where a user is navigating between screens and that portlet is having 2 or 3 screens, if the user went to 3rd screen and he comes back and clicked on the link it is going to 3rd screen instead of 1st screen.

To render 1st jsp from within portlet,we specify init parameter for first jsp in portlet.xml as follows

<init-param>
    <name>com.ibm.faces.portlet.page.view</name>
    <value>/jsp/html/view/HelloView.jsp</value>
</init-param>


Now in case, when you want to reset JSF Portlets to its initial view when user comes back, set "com.ibm.faces.portlet.page.view" attributed to session.


portletSession.setAttribute("com.ibm.faces.portlet.page.view", <path of jsp to render>);

Stopping Portal, WAS without userid,password in the command line

Stopping portal and WAS using command line includes user id and password as part of command. Below command holds good when security is enabled.

stopServer.sh server1 -username wasadmin -password wasadmin

This would cause a security issue as while typing command, anyone can see and come to know about userid and password.
To overcome this kind of security breach, please follow below steps which would allow you to stop portal and WAS without providing user id and password in the command line.

1) Find the file soap.client.props located under /WebSphere/AppServer/profiles/AppSrv01/properties   and change the values of userid and password for the following properties

com.ibm.SOAP.securityEnabled=true
com.ibm.SOAP.loginUserid=wasadmin
com.ibm.SOAP.loginPassword=wasadmin

the userid and password, will be the WAS admin'S userid and password.

2) Now that you are done with writing userid and password in the file. You can now run the command without specifying userid and password in the command line BUT still we have got security issue, because whoever knows path of this file, could see the userid and password in the file. 
To overcome this, we need to obfuscate the password property in the soap.client.props file. We can use PropFilePasswordEncoder.sh command to obfuscate password propery.
Use the below command to achieve this

./PropFilePasswordEncoder.sh /opt/IBM/WebSphere/AppServer/profiles/AppSrv01/properties/soap.client.props com.ibm.SOAP.loginPassword

Now, if you open the file in a text editor, you will find that password property is now obfuscated.

3) Restart he portal server.

Now onwards, you won't need to specify userid and password in the command line for stopping Portal and WAS.




Identifying list of portlets on a page

There might be some scenarios where you want to get list of all the portlets on a portal page.
Following code snipped would be helpful for you to get list of portlets on a page.


private void listPortletsOnPage(ContentModel model, RenderRequest request, RenderResponse response) {

        try {
            ContentModel model = getContentModel(request, response)
            Locator locator = model.getLocator();
            ObjectID oID = PortletURLHelper.getCurrentPage(request, response);
            ContentPage cPage = (ContentPage)locator.findByID(oID);
            PrintWriter out = response.getWriter();

            List allPortlets = getPortletsOnPage(model, cPage);

            Iterator it = allPortlets.iterator();

            while(it.hasNext()){
                PortletWindow window = (PortletWindow)it.next();
                out.print("PortletWindow " + window.getObjectID() + "
");
            }
        } catch (StateException e) {
           
            e.printStackTrace();
        } catch (NamingException e) {
           
            e.printStackTrace();
        } catch (IOException e) {
           
            e.printStackTrace();
        }

    }
       
   
    private ContentModel getContentModel(RenderRequest renderRequest, RenderResponse renderResponse) {
   
        try {
            ContentModelProvider provider = (ContentModelProvider) psh.getPortletService(ContentModelProvider.class);
            return provider.getContentModel(renderRequest, renderResponse);
        } catch (PortletServiceUnavailableException e) {
           
            e.printStackTrace();
        } catch (ModelException e) {
           
            e.printStackTrace();
        }

        return null;

    }
   
       
    public List getPortletsOnPage(final ContentModel aContentModel, final ContentPage aPage) {
        List result = Collections.EMPTY_LIST;
        final LayoutModel aLayoutModel = aContentModel.getLayoutModel(aPage);
        if (aLayoutModel != null) {
            result = new ArrayList();
            try {
                collector(aLayoutModel, aLayoutModel.getRoot(), result);
            } catch (ModelException e) {
                e.printStackTrace();
            }
        }
        return result;
    }