Sunday, 26 October 2014

Unboxing portlet communication in websphere portal8.0

Portlet comminication :- In this blog we will see all possible communications between portlets. There are many ways like Portlet events,Public render parameters, Publish and subscribe model.In which some approaches are provided by JSR286 and some by IBM websphere portal.


Portal Jsr286 standards itself supports two type of communications :-

Portlet session sharing :- If we have all portlets bundled in one war file then we can share data using sessions application_scope. Data available in application_scope can be shared between multiple portlets. One portlet will update the data all other portlets can pull it and use it. This data is specific to session.
Public render parameters :- Public render parameters are declared in portlet.xml and is used to share navigational state information. All portlets can pull this shared render parameters.

Other ways of communication :-

Publish/subscribe message based communication :- Portlet programmers will control the data which is being passing between portlets. Event brokers will mediate and transfer the data from publishing portlet to subscribing portlet. When one event occurs as side effect there will be action performed on subscribing portlet. Disadvantages are it requires configurations in portal administration which increases overhead. When communication is required for lot of portlets please try to use shared render parameters instead of portlet eventing.


IBM supported data exchange techniques :-  Cross-portlet-links is technique were we create urls for portlet in same page or different page then add parameters to it and send data to that portlet. This feature can be used to transfer data between ibm portlet and jsr portlets. Using PortalUrlGeneration techniques we can generate urls if needed uses PortletStateManager to generate advanced urls. Using cookies also we can transfer data between portlets. Using javascript also we can manipulate data from one portlet to other portlet by document object model.

Portlet event based communication :- Portlet event based communication uses publish/subscribe mechanism to transfer data. Advantage of events is we can transfer complex data structure throught events. By events we can trigger backend operations in other portlet irrespective of page.


Example for portlet events :- 

Step1 :- Now create a portal project and then create two portlets in it 1) PortletEventingPortlet it will publish the event 2) PortletSubscribingPortlet will subscribe the event

Step2 :- After creating portlets now we need to edit portlet.xml to add global event definition in portlet.xml

<!--Base definition of event -->
<event-definition>
<description>Pass news from one portlet to another portlet</description>
<!-- Qname for event this name folows the default namespace of portlet-app-->
<name>NewsEvent</name>
<!-- Payload type -->
<value-type>java.lang.String</value-type>

</event-definition>

Step3 :- Now you have to add supported-processing-event and supported-publishing-event tags in corresponding portlet definitions

<!--For PortletEventingPortlet-->
<supported-processing-event>
<name>NewsEvent</name>
</supported-processing-event>

<!--For PortletSubscribingPortlet-->
<supported-publishing-event>
<name>NewsEvent</name>
</supported-publishing-event>

Step4 :- Final portlet.xml should like below

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" id="com.prac.portleteventing.PortletEventingPortlet.c6a58bb494">

<portlet>
<portlet-name>PortletEventing</portlet-name>
<display-name xml:lang="en">PortletEventing</display-name>
<display-name>PortletEventing</display-name>
<portlet-class>com.prac.portleteventing.PortletEventingPortlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<resource-bundle>com.prac.portleteventing.nl.PortletEventingPortletResource</resource-bundle>
<portlet-info>
<title>PortletEventing</title>
<short-title>PortletEventing</short-title>
<keywords>PortletEventing</keywords>
</portlet-info>
<supported-publishing-event>
<name>NewsEvent</name>
</supported-publishing-event>
</portlet>

<portlet>
<portlet-name>PortletSubscribingPortlet</portlet-name>
<display-name xml:lang="en">PortletSubscribingPortlet</display-name>
<display-name>PortletSubscribingPortlet</display-name>
<portlet-class>com.ibm.portleteventing.PortletSubscribingPortlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<resource-bundle>com.ibm.portleteventing.nl.PortletSubscribingPortletResource</resource-bundle>
<portlet-info>
<title>PortletSubscribingPortlet</title>
<short-title>PortletSubscribingPortlet</short-title>
<keywords>PortletSubscribingPortlet</keywords>
</portlet-info>
<supported-processing-event>
<name>NewsEvent</name>
</supported-processing-event>
</portlet>

<default-namespace>http://PortletEventing/</default-namespace>
<!--Base definition of event -->
<event-definition>
<description>Pass news from one portlet to another portlet</description>
<name>NewsEvent</name>
<value-type>java.lang.String</value-type>
</event-definition>

</portlet-app>

Step5:-  Now we should invoke publishing in PortletEventingPortlet to do this we need to call response.setEvent(evnetName,payload);

package com.prac.portleteventing;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

import com.ibm.portleteventing.PortletSubscribingPortlet;
import com.ibm.wcp.runtime.feedback.lm.util.Logger;

/**
 * A sample portlet based on GenericPortlet
 */
public class PortletEventingPortlet extends GenericPortlet {

public static final String JSP_FOLDER    = "/_PortletEventing/jsp/";    // JSP folder name

public static final String VIEW_JSP      = "PortletEventingPortletView";         // JSP file name to be rendered on the view mode

public static final Logger logger = Logger.getLogger(PortletSubscribingPortlet.class.getName());
 
/**
* @see javax.portlet.Portlet#init()
*/
public void init() throws PortletException{
super.init();
}

/**
* Serve up the <code>view</code> mode.
* @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());

// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(getJspFilePath(request, VIEW_JSP));
rd.include(request,response);
}

/**
* Process an action request.
* @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
*/
public void processAction(ActionRequest request, ActionResponse response) throws PortletException, java.io.IOException {
//Invoke event
response.setEvent("NewsEvent", "India won the match");

}

/**
* Returns JSP file path.
* @param request Render request
* @param jspFile JSP file name
* @return JSP file path
*/
private static String getJspFilePath(RenderRequest request, String jspFile) {
String markup = request.getProperty("wps.markup");
if( markup == null )
markup = getMarkup(request.getResponseContentType());
return JSP_FOLDER + markup + "/" + jspFile + "." + getJspExtension(markup);
}

/**
* Convert MIME type to markup name.
* @param contentType MIME type
* @return Markup name
*/
private static String getMarkup(String contentType) {
if( "text/vnd.wap.wml".equals(contentType) )
return "wml";
        else
            return "html";
}

/**
* Returns the file extension for the JSP file
* @param markupName Markup name
* @return JSP extension
*/
private static String getJspExtension(String markupName) {
return "jsp";
}

}

Step6 :- In subscribing portlet we need to  have processEvent method to process event and then perform corresponding business logic.

package com.ibm.portleteventing;

import java.io.IOException;
import java.util.logging.Logger;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

/**
 * A sample portlet based on GenericPortlet
 */
public class PortletSubscribingPortlet extends GenericPortlet {

public static final String JSP_FOLDER    = "/_PortletSubscribingPortlet/jsp/";    // JSP folder name

public static final String VIEW_JSP      = "PortletSubscribingPortletView";         // JSP file name to be rendered on the view mode

    public static final Logger logger = Logger.getLogger(PortletSubscribingPortlet.class.getName());

 
/**
* @see javax.portlet.Portlet#init()
*/
public void init() throws PortletException{
super.init();
}

/**
* Serve up the <code>view</code> mode.
* @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
String message = request.getParameter("message");
if(message!=null){
request.setAttribute("message", message);
}

// Invoke the JSP to render
PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher(getJspFilePath(request, VIEW_JSP));
rd.include(request,response);
}

/**
* Process an action request.
* @see javax.portlet.Portlet#processAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
*/
public void processAction(ActionRequest request, ActionResponse response) throws PortletException, java.io.IOException {
}
/* (non-Javadoc)
* @see javax.portlet.GenericPortlet#processEvent(javax.portlet.EventRequest, javax.portlet.EventResponse)
*/
public void processEvent(EventRequest eventRequest,EventResponse eventResponse){
//Processing event
logger.info("In process event");
Event event = eventRequest.getEvent();
String message = (String) event.getValue();
logger.info("msg transfered:-" + message);
eventResponse.setRenderParameter("message", message);
}

/**
* Returns JSP file path.
* @param request Render request
* @param jspFile JSP file name
* @return JSP file path
*/
private static String getJspFilePath(RenderRequest request, String jspFile) {
String markup = request.getProperty("wps.markup");
if( markup == null )
markup = getMarkup(request.getResponseContentType());
return JSP_FOLDER + markup + "/" + jspFile + "." + getJspExtension(markup);
}

/**
* Convert MIME type to markup name.
* @param contentType MIME type
* @return Markup name
*/
private static String getMarkup(String contentType) {
if( "text/vnd.wap.wml".equals(contentType) )
return "wml";
        else
            return "html";
}

/**
* Returns the file extension for the JSP file
* @param markupName Markup name
* @return JSP extension
*/
private static String getJspExtension(String markupName) {
return "jsp";
}

}

Step 7 :- Modify the code in view jsp of publishing portlet to provide a link to invoke publishing. 

<%@page session="false" contentType="text/html" pageEncoding="ISO-8859-1" import="java.util.*,javax.portlet.*,com.prac.portleteventing.*" %>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>        
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v6.1/portlet-client-model" prefix="portlet-client-model" %>        
<portlet:defineObjects/>
<portlet-client-model:init>
      <portlet-client-model:require module="ibm.portal.xml.*"/>
      <portlet-client-model:require module="ibm.portal.portlet.*"/>   
</portlet-client-model:init> 


<DIV style="margin: 6px">

<H3 style="margin-bottom: 3px">Welcome!</H3>
Please click on below link to publish a event
<a href="<portlet:actionURL/>">Start event</a>
</DIV>

Step 8 :- Modify the code in subscribing portlet to receive the data and display it in portlet2.

<%@page session="false" contentType="text/html" pageEncoding="ISO-8859-1" import="java.util.*,javax.portlet.*,com.ibm.portleteventing.*" %>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet"%>        
<%@taglib uri="http://www.ibm.com/xmlns/prod/websphere/portal/v6.1/portlet-client-model" prefix="portlet-client-model" %>        
<portlet:defineObjects/>
<portlet-client-model:init>
      <portlet-client-model:require module="ibm.portal.xml.*"/>
      <portlet-client-model:require module="ibm.portal.portlet.*"/>   
</portlet-client-model:init> 


<DIV style="margin: 6px">

<H3 style="margin-bottom: 3px">Welcome!</H3>
This is a subscribing portlet ${message}
</DIV>

Step 9 :- Now we need to navigate to portal administration managed pages then go to edit layout and then navigate to wires section and apply wiring.


                                           Click on pencil icon edit layout and navigate to wires


                                     Select all appropriate values in drop down


Step 10 :- Final output click on link then text will be passed to second portlet and displayed in it.


Click on start event and then observe first portlet text for news



No comments:

Post a Comment

Custom single threaded java server

 package com.diffengine.csv; import java.io.*; import java.net.*; import java.util.Date; public class Server { public static void main(Str...