Tuesday, April 19, 2016

JSR 286 Lifecycle Explained

Though age old, thought of writing this post just to have a placeholder to detail the basic JSR 286 Portlet flow.

Following flow chart explains the basic flow of JSR 286 based portlet:


JSR 286 based portlet's flow

By overriding the major methods of GenericPortlet class and adding loggers on each method entry, we can easily view the flow of the portlets lifecycle.
  • After deploying the portlet, when it is being invoked for the first time (by visiting a page on which it is added) init method is called.
[2/18/16 17:10:55:925 IST] 000001c5 SystemOut     O JSR286LCCheck init method called
[2/18/16 17:10:55:926 IST] 000001c5 SystemOut     O JSR286LCCheck render method called, mode to be displayed is : view
[2/18/16 17:10:55:926 IST] 000001c5 SystemOut     O JSR286LCCheck doDispatch method called
[2/18/16 17:10:55:926 IST] 000001c5 SystemOut     O JSR286LCCheck doView method called

  • For all other subsequent calls, init is not invoked. On page refresh:
[2/18/16 17:13:23:309 IST] 00000145 SystemOut     O JSR286LCCheck render method called, mode to be displayed is : view
[2/18/16 17:13:23:310 IST] 00000145 SystemOut     O JSR286LCCheck doDispatch method called
[2/18/16 17:13:23:310 IST] 00000145 SystemOut     O JSR286LCCheck doView method called

  • On Form submit processAction is invoked and flowing is the flow: (Changed the portlet mode here to Edit mode). doDispatch redirects to the requested mode method:
[2/18/16 17:12:03:436 IST] 00000044 SystemOut     O JSR286LCCheck processAction method called
[2/18/16 17:12:03:741 IST] 00000044 SystemOut     O JSR286LCCheck render method called, mode to be displayed is : edit
[2/18/16 17:12:03:741 IST] 00000044 SystemOut     O JSR286LCCheck doDispatch method called
[2/18/16 17:12:03:741 IST] 00000044 SystemOut     O JSR286LCCheck doEdit method called


Once the mode is changed, it remains in the same mode till session is over or the mode is changed explicitly.
  • When serveResource is called, then only serveResource is called. It acts as an independent method.
[2/18/16 17:12:40:239 IST] 00000145 SystemOut     O JSR286LCCheck serveResource method
  • When the application is stopped, destroy method is called. Destroy will only be called if the portlet has been initialized / invoked. If the portlet has not been initialized, the destroy method will not be called.
[2/18/16 17:14:13:292 IST] 00000048 ApplicationMg A   WSVR0217I: Stopping application: PA_JSR286LCCheck
[2/18/16 17:14:13:301 IST] 00000048 ServletWrappe I com.ibm.ws.webcontainer.servlet.ServletWrapper doDestroy SRVE0253I: [PA_JSR286LCCheck] [/wps/PA_JSR286LCCheck] [/_JSR286LCCheck/jsp/html/JSR286LCCheckPortletView.jsp]: Destroy successful.
[2/18/16 17:14:13:302 IST] 00000048 ServletWrappe I com.ibm.ws.webcontainer.servlet.ServletWrapper doDestroy SRVE0253I: [PA_JSR286LCCheck] [/wps/PA_JSR286LCCheck] [/_JSR286LCCheck/jsp/html/JSR286LCCheckPortletEdit.jsp]: Destroy successful.
[2/18/16 17:14:13:302 IST] 00000048 SystemOut     O JSR286LCCheck destroy called
[2/18/16 17:14:13:302 IST] 00000048 ServletWrappe I com.ibm.ws.webcontainer.servlet.ServletWrapper doDestroy SRVE0253I: [PA_JSR286LCCheck] [/wps/PA_JSR286LCCheck] [JSR286LCCheck]: Destroy successful.
[2/18/16 17:14:13:584 IST] 00000048 ApplicationMg A   WSVR0220I: Application stopped: PA_JSR286LCCheck


Tuesday, April 12, 2016

Annotated serveResource in JSR 286 portlet


I wonder why serveResource method was left out while providing annotated methods in JSR 286.
It is a frequent requirement now-a-days to implement multiple AJAX calls while developing JSR 286 based portlets.
There are many different design patterns through which this can be achieved, but still thought of giving a try to annotate serveResource method.

What I did was creating a base portlet class which will be extended by the other portlet classes, but this is not required and can be directly done in the requisite portlet class.

Firstly, created an annotation interface ResourceMapping, this defines the annotation of @ResourceMapping with name as a variable.



package in.blogspot.wpwizard.portlets;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
public @interface ResourceMapping {
 String name();
}

Then in BasePortlet class added a private method to cache the annotated resource methods during the portlet initialization.
Then in the overridden serveResource method checked value of parameter javax.portlet.serveResource which should denote the name of the annotated methods name parameter.



package in.blogspot.wpwizard.portlets;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;



public abstract class BasePortlet extends GenericPortlet {
 private transient Map<String, Method> serveResourceHandlingMethodsMap = new HashMap<String, Method>();


 @Override
 public void init() throws PortletException {
  super.init();

  try {
   cacheAnnotatedResourceMethods(); //cache annotated resource serving methods on init
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 @Override
 public void destroy() {
  super.destroy();
 }

 /**
  * In order to annotate the serveResource use <code>@ResourceMapping</code> 
  * and provide the variable name of parameter <code>javax.portlet.resource</code> in <code>resourceURL</code> 
  * 
  */
 public void serveResource(ResourceRequest request, ResourceResponse response)
   throws PortletException, IOException {
  try {
   String resource = request.getParameter("javax.portlet.serveResource");
   Method resourceMethod = serveResourceHandlingMethodsMap.get(resource);
   if (resourceMethod != null) {
    resourceMethod.invoke(this, request, response);
    return;
   }
  } catch (Exception e) {
   throw new PortletException(e);
  }

 }


 @Override
 protected void doView(RenderRequest request, RenderResponse response)
   throws PortletException, IOException {

 }


 private void cacheAnnotatedResourceMethods() {
  // cache all annotated resource serving methods
  for (Method method : this.getClass().getMethods()) {
   Annotation[] annotations = method.getAnnotations();
   if (annotations != null) {
    for (Annotation annotation : annotations) {
     Class<? extends Annotation> annotationType = annotation.annotationType();
     if (ResourceMapping.class.equals(annotationType)) {
      String name = ((ResourceMapping) annotation).name();
      if (name != null && name.length() > 0)
       serveResourceHandlingMethodsMap.put(name, method);
     } 
    }
   }
  }
 }

}

In the individual portlet class of MyPortlet added the annotated methods for serving resource.



package in.blogspot.wpwizard.portlets;

import java.io.IOException;
import java.io.PrintWriter;

import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;


public class MyPortlet extends BasePortlet {
  
 public void init() throws PortletException{
  super.init();
 }

 public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
  
  response.setContentType(request.getResponseContentType());
  PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/jsp/view.jsp");
  rd.include(request,response);
 }

 @ResourceMapping(name="getCountry")
 public void getCountry(ResourceRequest request, ResourceResponse response)throws PortletException, IOException{
  System.out.println("entered getCountry");
  PrintWriter out = response.getWriter();
  out.print("return country list");
  
 }
 
 @ResourceMapping(name="getState")
 public void getState(ResourceRequest request, ResourceResponse response)throws PortletException, IOException{
  System.out.println("entered getState");
  PrintWriter out = response.getWriter();
  out.print("return state list");
  
 }

}

In the JSP added the following tags to form an URL to these annotated method. The value passed in the param with name javax.portlet.serveResource should match the annotation name variable of the method. (As we do in the processAction annotation)



<portlet:resourceURL var="getCountryURL">
 <portlet:param name="javax.portlet.serveResource" value="getCountry" />
</portlet:resourceURL>
<portlet:resourceURL var="getStateURL">
 <portlet:param name="javax.portlet.serveResource" value="getState" />
</portlet:resourceURL>

Voila it works !!


Tuesday, February 9, 2016

Adding additional attributes in Edit User Profile Page of WebSphere Portal

Many a times we face a need to have additional / custom attributes to be added in Directory Server (LDAP) to store user specific data.

Considering that this additional / custom attribute has been added to the VMM of Portal. We might have a need to see the value stored in that attribute for a particular user. This attribute will not appear directly in the edit user profile page.

Following are the steps to make such attribute available in the Edit User Profile page:

  • In Portal Administration > Manage Pages search for Edit My Profile page



  • Click on Edit Page Layout
  • In Profile Management Portlet Click Configure

  • A list of all the available attributes will appear which are added in the VMM.
  • Select the required attribute and click ok.
  • Voila!! Now this attribute will start appearing in the Edit User Profile Page.



Another way of doing this is:

  • Navigate to Administration > Portlets
  • search for Profile Management portlet
  • click configure and add attribute name to the coma separate list of wps.portlets.displayed_user_attributes parameter


As per my observation, if we add an attribute of type Boolean using any of the above two ways, it will not get added to the Edit User Profile page.

If we have to add a Boolean attribute then adding it as a new preference in the configure mode of Profile Management portlet will do the trick.


Saturday, October 11, 2014

IBM WebSphere Portal login without LDAP (Custom TAI)

Recently we had a requirement where we had to authenticate a user against a third party via REST call. The user base was in millions and use of LDAP or database as a repository for Portal was ruled out. Also the user credentials were stored centrally in that third party application's repository and were not supposed to be shared with any other application.

Thus enters Trust Association Interceptor (TAI), the less known awesome feature of IBM WebSphere Application Server. TAI provides us a mechanism to customize the authenticate process.
But with TAI also we still need a repository against which TAI will create the user principal and allow us to create user session.
So, the next challenge was how can we customize the authentication process further where we don't need a user repository.
Here comes a feature provided by WebSphere Portal only (not available in WAS) which is primarily used for integration with OpenID providers like Facebook or Google. This feature is called "transient user" which after enabling it creates an in-session temporary user account in Portal's memory. This user account is valid only for that session and when the session expires the user account is also removed. But still it serves the purpose of authenticating third party users and giving them access to your protected resources or pages without having their user account in Portal's local repository.

Refer following link for details about transient user and how to enable it:
https://www.ibm.com/support/knowledgecenter/en/SSYJ99_8.0.0/security/openid_trans_users.html


Tuesday, May 15, 2012

Installing and using SVN Plugin in RAD

It is a general practice to keep project's codebase in SVN. For this purpose it is necessary to integrate IDE in this case RAD (Rational Application Developer) with SVN (in this case CollabNet).

If RAD is directly connected with internet and without any corporate policy restrictions of downloads, then the SVN plugin for RAD can be directly downloaded from RAD.
Else the SVN plugin can be manually downloaded from http://subclipse.tigris.org/servlets/ProjectDocumentList?folderID=2240

Installing SVN plugin in RAD


  1. Download site-1.0.6.zip from the above mentioned link
  2. Unzip the file
  3. In RAD, go to Help > Install New Software


   
   4. Click on Add > Local (Provide the path till the unzipped site-1.0.6 folder)
   5.  Provide Name for the Location. Click OK
   6. Select the Subclipse Plugin checkbox and Click Next


   7.  Follow the instructions as per the Wizard and it will install the plugin
   8.  Restart the RAD
   9. In RAD Go to Window > Open Perspective > Others and a New “SVN Repository Exploring”     Perspective will be available. Select that perspective and click Ok.


   10. In the left pane click on can like icon "Add New Repository"
   11. Provide the URL and User and Password for the SVN
  12. RAD is now configured with SVN

Adding a portlet project in SVN


  1. Right click the requisite project in Project Explorer and go to Team > Share Project

      2. Select the SVN repository type
      3. Select the Appropriate Repository location and click Finish
      4. Provide the Comments for SVN when prompted by the Wizard
      5. Portlet Project has now been added into SVN


Import Portlet project from SVN

  1.        Go to File > Import
  2.        Select “Project from SVN”
  3.        Provide the exact SVN location till the Project
  4.        Click finish

Commit and Update

       Right click on the project go to Team > Commit / Update

Tuesday, May 8, 2012

Simple shell script for WebSphere Portal startup tasks

A simple shell script for WebSphere Portal start, stop, restart and status tasks. Well, it can be customized for websphere application server startup as well. Just need to change the serverName to server1.

Configurable parameters:

wasHome, serverName, userName, password


Usage : server.sh {start|stop|restart|status}

Download Here

Cheers ;)

Sunday, May 6, 2012

Implementing Remote WCM Search Collection in WebSphere Portal


Implementation of search collections is different in clustered environment than standalone environment.
Standalone WCM search collection implementation is very straight forward and can be done by following steps mentioned in this link:
http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Indexing_web_content_wcm7

But for clustered environment, IBM documentation suggests to implement Remote Search collection.
As per the documentation provided here:
http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Configuring_Portal_Search_in_a_cluster_on_Windows_wp7

An instance of WAS node is required which should not be part of Portal Cluster.

Having a separate WAS node or instance depends upon your requirement. If the portal or WCM search is used very extensively in the Portal then somethings it is better to have a new instance of WAS installed for Remote Search.
But if you have a very limited use of Search, then you can create a new "default" profile of WAS on any one of the cluster member machines. This can be achieved by either using Profile Management tool or ./manageprofiles.sh

Once you have successfully created a new WAS profile, start the profile and then follow the steps mentioned in following link on to perform tasks  on newly created profile and cluster primary node:
http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Preparing_for_remote_search_service_wp7

Once these steps are complete follow the steps mentioned in following link to configure remote search service:
http://www-10.lotus.com/ldd/portalwiki.nsf/dx/Configuring_a_remote_search_service_wp7