Friday, April 25, 2014

Portlet Life Cycle, Generic Portlet - A brief study



Life Cycle : 
  •  Instantiation of Portlet
  •  Initializattion of Portlet through public void init(PortletConfig)
  •  Portlet serves action and render request.   
    • Render or Process Action : render method is called by the container in response to render request and  also after the execution of  processAction.
    • processAction method is called in case of action request.
  •  Destroy of Portlet : public void destroy(){} method is called before destroy of portlet instance.



Creating portlets using Portlet interface and GenericPortlet class 
       
In servlets there is only one lifecycle interface, the Servlet interface. In portlets the lifecycle contract exists between portlet container and the portlet through javax.portlet.Portlet, javax.portlet.EventPortlet and  javax.portlet.ResourceServingPortlet interfaces, which define the lifecycle methods of a portlet. It is mandatory for portlets to implement the Portlet interface, and  it’s optional to implement EventPortlet and ResourceServingPortlet interfaces. The


Portlet interface 
   
The Portlet interface is at the heart of Java portlet technology and it is mandatory for portlets to implement it, directly or indirectly. The
Portlet interface methods are invoked by the portlet container to manage the lifecycle of a portlet instance. In this section we discuss the lifecycle methods defined by the
Portlet interface and how some of the lifecycle methods relate to the Portlet URLs (or portlet request types).
           
The lifecycle methods defined by the Portlet lifecycle interface are init,  processAction, render and destroy.
Portlet 2.0 introduced optional lifecycle interfaces, EventPortlet and ResourceServingPortlet.


javax.portlet.GenericPortlet

The GenericPortlet class provides a default implementation for the Portlet interface.
It provides an abstract class to be subclassed to create portlets. A subclass of GenericPortlet should either use one of the following annotations:
  • @ProcessAction
  • @ProcessEvent
  • @RenderMode
or override at least one method, usually one of the following:
  • processAction, to handle action requests
  • doView, to handle render requests when in VIEW mode
  • doEdit, to handle render requests when in EDIT mode
  • doHelp, to handle render request when in HELP mode
  • init and destroy, to manage resources that are held for the life of the servlet
Normally there is no need to override the render or the doDispatch methods. Render handles render requests setting the title of the portlet in the response and invoking doDispatch. doDispatch dispatches the request to one of the doView, doEdit or doHelp method depending on the portlet mode indicated in the request.
Portlets typically run on multithreaded servers, so please note that a portlet must handle concurrent requests and be careful to synchronize access to shared resources. Shared resources include in-memory data such as instance or class variables and external objects such as files, database connections, and network connections.

public abstract class GenericPortlet implements Portlet, PortletConfig, EventPortlet, ResourceServingPortlet {…
       }



A convenience method which can be overridden so that there's no need to call super.init(config)

public void init(PortletConfig config) throws PortletException {
              this.config = config;
              cacheAnnotatedMethods();
              this.init();
       }

Called by the portlet container to allow the portlet to process an action request. This method is called if the client request was originated by a URL created (by the portlet) with the RenderResponse.createActionURL() method.

public void processAction(ActionRequest request, ActionResponse response) throws PortletException, java.io.IOException { String action = request.getParameter(ActionRequest.ACTION_NAME); try { // check if action is cached Method actionMethod = processActionHandlingMethodsMap.get(action); if (actionMethod != null) { actionMethod.invoke(this, request, response); return; } } catch (Exception e) { throw new PortletException(e); } // if no action processing method was found throw exc throw new PortletException("processAction method not implemented"); }
The default implementation of this method sets the headers using the doHeaders method, sets the title using the getTitle method and invokes the doDispatch method.
It also evaluates the RENDER_PART request attribute and if set calls the doHeaders, getNextPossiblePortletModes and getTitle methods for the RENDER_HEADERS part and the doDispatch method for the RENDER_MARKUP part.
If the RENDER_PART request attribute is not set all of the above methods will be called.

public void render(RenderRequest request, RenderResponse response)
                     throws PortletException, java.io.IOException {
              Object renderPartAttrValue = request
                           .getAttribute(RenderRequest.RENDER_PART);
              if (renderPartAttrValue != null) {
                     // streaming portal calling
                     if (renderPartAttrValue.equals(RenderRequest.RENDER_HEADERS)) {
                           doHeaders(request, response);
                           Collection<PortletMode> nextModes = getNextPossiblePortletModes(request);
                           if (nextModes != null)
                                  response.setNextPossiblePortletModes(nextModes);
                           response.setTitle(getTitle(request));
                     } else if (renderPartAttrValue.equals(RenderRequest.RENDER_MARKUP)) {
                           doDispatch(request, response);
                     } else {
                           throw new PortletException(
                                         "Unknown value of the 'javax.portlet.render_part' request attribute");
                     }
              } else {
                     // buffered portal calling
                     doHeaders(request, response);
                     Collection<PortletMode> nextModes = getNextPossiblePortletModes(request);
                     if (nextModes != null)
                           response.setNextPossiblePortletModes(nextModes);
                     response.setTitle(getTitle(request));
                     doDispatch(request, response);
              }
       }

The default implementation of this method routes the render request to:
  1. method annotated with @RenderMode</name> and the name of the portlet mode
  2. a set of helper methods depending on the current portlet mode the portlet is currently in. These methods are:
    • doView for handling view requests
    • doEdit for handling edit requests
    • doHelp for handling help requests
  3. If the window state of this portlet is minimized, this method does not invoke any of the portlet mode rendering methods.
    For handling custom portlet modes the portlet should either use the @RenderMode annotation or override this method. Note that the annotated methods needs to be public in order to be allowed to be called by GenericPortlet.    
protected void doDispatch(RenderRequest request, RenderResponse response)
                     throws PortletException, java.io.IOException {
              WindowState state = request.getWindowState();

              if (!state.equals(WindowState.MINIMIZED)) {
                     PortletMode mode = request.getPortletMode();
                     // first look if there are methods annotated for
                     // handling the rendering of this mode
                     try {
                           // check if mode is cached
                           Method renderMethod = renderModeHandlingMethodsMap.get(mode
                                         .toString());
                           if (renderMethod != null) {
                                  renderMethod.invoke(this, request, response);
                                  return;
                           }
                     } catch (Exception e) {
                           throw new PortletException(e);
                     }

                     // if not, try the default doXYZ methods
                     if (mode.equals(PortletMode.VIEW)) {
                           doView(request, response);
                     } else if (mode.equals(PortletMode.EDIT)) {
                           doEdit(request, response);
                     } else if (mode.equals(PortletMode.HELP)) {
                           doHelp(request, response);
                     } else {
                           throw new PortletException("unknown portlet mode: " + mode);
                     }
              }
       }

Default resource serving.
The default implemention of this method is to call a RequestDispatcher.foward with the ResourceID of the ResourceRequest.
If no ResourceID is set on the resource URL the default implementation does nothing.
public void serveResource(ResourceRequest request, ResourceResponse response)
                     throws PortletException, IOException {
              if (request.getResourceID() != null) {
                     PortletRequestDispatcher rd = getPortletConfig()
                                  .getPortletContext().getRequestDispatcher(
                                                request.getResourceID());
                     if (rd != null)
                           rd.forward(request, response);
              }
       }


The default implementation tries to dispatch to a method annotated with @ProcessEvent</name> that matches the event name or, if no such method is found just sets the current render parameters on the response.
Note that the annotated methods needs to be public in order to be allowed to be called by 
GenericPortlet.


public void processEvent(EventRequest request, EventResponse response) throws PortletException, IOException {
              String eventName = request.getEvent().getQName().toString();

              try {
                     // check for exact match
                     Method eventMethod = processEventHandlingMethodsMap.get(eventName);
                     if (eventMethod != null) {
                           eventMethod.invoke(this, request, response);
                           return;
                     } else {
                           // Search for the longest possible matching wildcard annotation
                           int endPos = eventName.indexOf('}');
                           int dotPos = eventName.lastIndexOf('.');
                           while (dotPos > endPos) {
                                  String wildcardLookup = eventName.substring(0, dotPos + 1);
                                  eventMethod = processEventHandlingMethodsMap.get(wildcardLookup);
                                  if (eventMethod != null) {
                                         eventMethod.invoke(this, request, response);
                                         return;
                                  }
                                  if (dotPos == 0) {
                                         break;
                                  }
                                  dotPos = eventName.lastIndexOf('.', dotPos - 1);
                           }
                     }
              } catch (Exception e) {
                     throw new PortletException(e);
              }

              // if no event processing method was found just keep render params
              response.setRenderParameters(request);
       }


Follow below link for more detail:


Hope It will be helpful.



No comments:

Post a Comment