Inter Portlet Communications IPC JSR168

This article demonstrates the steps performed to implement JSR 168 compliant cooperative portlets using IBM Rational Application Developer V6.0 and WebSphere Portal Server V5.1. The article illustrates passing multiple values from source portlet to target portlet without defining complex data type inside WSDL file.

The term cooperative portlets refers to the capability of portlets on a page to interact with each other by sharing information. One or more cooperative portlets on a portal page can automatically react to changes from a source portlet triggered by an action or event in the source portlet. Portlets that are targets of the event can react so that users are not required to make repetitive changes or actions in other portlets on the page. Cooperation between source and target portlets is facilitated by a WebSphere Portal runtime entity called the property broker. Portlets on a page can cooperate in this way even if they were developed independently, without the programmer's awareness of the existence of the other cooperative portlets.

JSR 168 is a specification from the Java Community Process for portlet development. IBM WebSphere Portal V5.1 provides support for the JSR 168 API. With an IBM extension, WebSphere Portal V5.1 supports cooperative portlets for JSR 168 portlets, in which one JSR 168 portlet can communicate with another JSR 168 portlet.

To develop and deploy the sample application, we used the following IBM products:

  1. Rational Application Developer for Rational Software Development Platform V6.0
  2. WebSphere Portal V5.1.x
Introducing the DemoPortlets scenario
In the DemoPortlets scenario we are going to create two JSR 168 portlets. The DemoPortlet1 will pass the multiple values to the DemoPortlet2 without defining complex data type inside WSDL file.

DEMOPORTLET1:
Gets the input from the user in three fields and then passed these input values to the target portlet. This portlet is our source portlet. (See Figure 1.)

DEMOPORTLET2:
Act as a target portlet and retrieve those three entered values from DemoPortlet1 and display them on the page. (See Figure 2.)

Create Portlet Project (JsR 168)
Start the IBM Rational Application Developer (IRAD).

  1. With the IRAD workbench started, switch to the Web perspective by clicking Window > Open Perspective >Web.
  2. Click New > Other
  3. Select Portlet Project (JSR 168) from the list. This launches the New Portlet Project (JSR 168) wizard (See Figures 3 and 4.)
  4. Enter DemoPortlets as the Name.
  5. Clear the Create a portlet checkbox. You will create your portlets separately in order to have better control over portlet naming conventions.
  6. Click the Show Advanced button.
  7. Select WebSphere Portal v5.1 Unit Test Environment in the Target Server list.
  8. Accept defaults for the other fields.
  9. Click Finish
Create DemoPortlet1 (JSR 168)
  1. Select the DemoPortlets project in the Project Navigator view.
  2. Right-click to bring up the context menu, and click New > Portlet. This launches the New Portlet wizard
  3. Enter DemoPortlet1 as the Default Name prefix, click Next (See Figure 5.)
  4. Accept default values and click Finish.
Create Portlet2 (JSR 168)
As a same way create DemoPortlet2 portlet.

Enabling the DemoPortlet1 as a source
JSR 168 portlets can cooperate with each other by exchanging properties via the property broker. A WSDL file describes publish (or send) to the property broker.

DESCRIBING THE SOURCE WITH WSDL
To enable our DemoPortlet1 portlet as a property source, simply right-click the portlet in the Project Explorer view to display the Enable Source (See Figure 6.)

Once the Enable Cooperative Source wizard launches enter the illustrated values: (See Figure 7.)

  • A name for the Data type
  • The Namespace for the new data type
  • What you want your parameter Bound to

The term parameter refers to how the value will be transferred from the source portlet to the target portlet. The choices are:

  1. None: This setting implies that you will not specify the way the value will be passed, so the default behavior for portlet
  2. Render Parameter: Supports only strings. The string value will be bound to the RenderRequest object. The render phase and retrieved during the render phase of the portlet lifecycle. It cannot be retrieved during the action phase.
  3. Request Parameter: Supports only strings. The string value will be bound to the ActionRequest object, and can stage of the portlet lifecycle. The parameter value will be meaningless at the conclusion of request processing (that invocation).
  4. Request Attribute: Supports any JavaBean type. The bean will be bound to the ActionRequest object. Lifecycle Request Parameter.
  5. Session: Supports any JavaBean type. The bean will be bound to the session object and will persist for the duration and the portal server.
The Enable Cooperative Source wizard generates a WSDL file that describes the portlet to the property broker tagged with a distinctive icon to indicate that it is a property source. The WSDL file contains the following sections:
  • Types: This section describes data types (using XML schema) that can be emitted by the source portlet.
  • Messages: This section describes messages that can be produced or consumed by the portlet.
  • Port Type: This section describes the abstract interface of the portlet as seen by the property broker.
  • Binding: This section describes how the abstract interface (port type) is implemented.
To define the second attribute, right-click the portlet again and select Cooperative->Enable Source Define the following values: (See Figure 8.)

For the third attribute, perform the same step, as mentioned above, and provide following values: (See Figure 9.)

Source WSDL
Once we done with the wizard, the WSDL file should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="DemoPortlet1portlet_Service"
targetNamespace="http://demoportlets"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:portlet="http://www.ibm.com/wps/c2a"
xmlns:tns="http://demoportlets"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types>
<xsd:schema targetNamespace="http://demoportlets">
<xsd:simpleType name="IDDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="NameDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="StateDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</types>
<message name="IDDatatype_Response">
<part name="IDDatatype_Output" type="tns:IDDatatype" />
<part name="NameDatatype_Output" type="tns:NameDatatype" />
<part name="StateDatatype_Output" type="tns:StateDatatype" />
</message>
<portType name="DemoPortlet1portlet_Service">
<operation name="DemoPortlet1portlet">
<output message="tns:IDDatatype_Response" />
</operation>
</portType>
<binding name="DemoPortlet1portlet_Binding"
type="tns:DemoPortlet1portlet_Service">
<portlet:binding />
<operation name="DemoPortlet1portlet">
<portlet:action name="MyAction" actionNameParameter="ACTION_NAME" type="standard"
caption="output.data" description="Output.Data" />
<output>
<portlet:param name="FormID" partname="IDDatatype_Output" boundTo="request-attribute"
caption="output.ID" />
<portlet:param name="FormName" partname="NameDatatype_Output"
boundTo="request-attribute" caption="output.NAME" />
<portlet:param name="FormState" partname="StateDatatype_Output"
boundTo="request-attribute" caption="output.STATE" />
</output>
</operation>
</binding>
</definitions>

Note: Make sure the captions and description are defined for and attributes. However, these fields are optional but very useful while creating wires.


Enabling DemoPortlet2 as Target
GENERATING THE WSDL
You will use the Enable Cooperative Target wizard to generate the WSDL. To launch the wizard, simply select the portlet and click Cooperative > Enable Target (this step is nearly identical to enabling cooperative source).(See Figure 10.)

Once the Enable Cooperative Target wizard launches enter the illustrated values:(See Figure 11.)

  • Data type: Use the exact same name that you used when you enabled the source portlet.
  • Namespace: Again, the namespace that you enter here should be the same one you used for the source.
  • Action: Use the exact same name that you used when you enabled the source portlet.
  • Parameter: Use the exact same name that you used when you enabled the source portlet.
  • Bound to: Choose None from the list.
  • Label and Description: These fields are optional, but should be filled in; as they will help you create the wires
In order to define the remaining two attributes for the same target portlet, DO NOT use the wizard. We have to define them inside the WSDL file directly. Open the DemoPortlet2portlet.wsdl file and make the modifications according to the WSDL Source.

WSDL CODE

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="DemoPortlet2portlet_Service"
targetNamespace="http://demoportlets"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:portlet="http://www.ibm.com/wps/c2a"
xmlns:tns="http://demoportlets"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<types>
<xsd:schema targetNamespace="http://demoportlets">
<xsd:simpleType name="IDDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<xsd:schema targetNamespace="http://demoportlets">
<xsd:simpleType name="NameDatatype">
<xsd:restriction base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<xsd:schema targetNamespace="http://
demoportlets">
<xsd:simpleType name="StateDatatype">
<xsd:restriction
base="xsd:string"></xsd:restriction>
</xsd:simpleType>
</xsd:schema>
</types>
<message name="IDDatatype_Request">
<part name="IDDatatype_Input" type="tns:IDDatatype" />
<part name="NameDatatype_Input" type="tns:NameDatatype" />
<part name="StateDatatype_Input" type="tns:StateDatatype" />
</message>
<portType name="DemoPortlet2portlet_Service">
<operation name="DemoPortlet2portlet">
<input message="tns:IDDatatype_Request" />
</operation>
</portType>
<binding name="DemoPortlet2portlet_Binding" type="tns:DemoPortlet2portlet_Service">
<portlet:binding />
<operation name="DemoPortlet2portlet">
<portlet:action name="MyAction" actionNameParameter="ACTION_NAME" type="standard"
caption="input.Data" description="Input Data from Source Portlet" />
<input>
<portlet:param name="FormID" partname="IDDatatype_Input" caption="input.ID" />
<portlet:param name="FormName" partname="NameDatatype_Input" caption="input.NAME" />
<portlet:param name="FormState" partname="StateDatatype_Input" caption="input.STATE" />
</input>
</operation>
</binding>
</definitions>

Note: Make sure the captions and description are defined for and attributes. However, these fields are optional but very useful while creating wires.The IRAD generates the DemoPortlet1portlet.wsdl and DemoPortlet2portlet.wsdl file. (See Figure 12.)


Java Class Modifications:
After defining the attributes and the portlet action in the WSDL file, the following code need to be written:

1. Open DemoPortlet1Portlet.java file.

2. Declare the following attributes:

public static final String FORM_ID = "FormID";
public static final String FORM_NAME = "FormName";
public static final String FORM_STATE = "FormState";
public static final String ACTION_TEXT = "MyAction";

Note: Make sure the values of FORM_ID, FORM_NAME and FORM_STATE must be same to the name defined for in the WSDL file.

3. Modify processAction() method

public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {

String id = request.getParameter(FORM_ID);
String name = request.getParameter(FORM_NAME);
String state = request.getParameter(FORM_STATE);

request.setAttribute(FORM_ID, id);
request.setAttribute(FORM_NAME, name);
request.setAttribute(FORM_STATE, state);
}

3. Save the changes

4. Open DemoPortlet2PortletSessionBean.java and define following attributes

private String id = "";
private String name = "";
private String state = "";

5. Generate getter and setter methods for the above attributes and save the changes.

6. Open DemoPortlet2Portlet.java file.

7. Declare the following attributes:

public static final String FORM_ID = "FormID";
public static final String FORM_NAME = "FormName";
public static final String FORM_STATE = "FormState";
public static final String ACTION_TEXT = "MyAction";

Note: Make sure the values of FORM_ID, FORM_NAME and FORM_STATE must be same to the name defined for in the WSDL file.

8. Modify processAction() method

public void processAction(ActionRequest request, ActionResponse response) throws
PortletException, java.io.IOException {
DemoPortlet2PortletSessionBean sessionBean = getSessionBean(request);
String id = request.getParameter(FORM_ID);
String name = request.getParameter(FORM_NAME);
String state = request.getParameter(FORM_STATE);
sessionBean.setId(id);
sessionBean.setName(name);
sessionBean.setState(state);
}

9. Save the changes

JSP Modifications:
1. Open DemoPortlet1PortletView.jsp

2. Modify the JSP code as follows:

<%@ page session="false" contentType="text/html"
import="java.util.*,javax.portlet.*,demoportlet1.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>


<%
PortletURL actionUrl = renderResponse.createActionURL();
actionUrl.setParameter("ACTION_NAME", DemoPortlet1Portlet.ACTION_TEXT);
%>

">
Enter ID: "
type="text"/>

Enter Name: "
type="text"/>

Enter State: "
type="text"/>

" type="submit"
value="Submit"/>




3. Save the changes

4. Open DemoPortlet2PortletView.jsp

5. Modify the JSP code as follows:

<%@ page session="false" contentType="text/html"
import="java.util.*,javax.portlet.*,demoportlet2.*" %>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet" %>


<%
DemoPortlet2PortletSessionBean sessionBean =
(DemoPortlet2PortletSessionBean)renderRequest.getPortletSession()
.getAttribute(DemoPortlet2Portlet.SESSION_BEAN);
%>

Entered Id is = <%= sessionBean.getId()%>

Entered Name is = <%= sessionBean.getName()%>

Entered State is = <%= sessionBean.getState()%>

6. Save the changes

Deploy the DemoPortlets.war portlet

  1. Export the DemoPortlets Project as a WAR file.(See Figure 13.)
  2. Install the DemoPortlets.war file in WebSphere Portal Server (See Figure 14.)
  3. Once the installation of the portlet is completed. Create the page
  4. Place both the portlets on the same page
  5. Create the wires between both portlets by selecting the Wire link on top of the page
  6. Define a wire for each attribute defined and click Add wire, as shown in the figure (See Figure 15.)
  7. Once all the wires created press Done.
  8. Go to the page where both portlets are placed.
  9. Test the portlets by entering dummy data and press Submit. You should see the values on the second portlet.
Conclusion
The WebSphere Portal Server Property Broker allows passing complex data between portlets without defining complex data type inside the WSDL files.

1 comments:

Unknown said...

Thanks for the detailed steps and description to implement IPC. It is working fine but only failing in one scenario as mentioned below:

1. I have commandLink on my source jsf page , when click on it, I will go to Destination page. I used the same steps what you mentioned. But the client requirement is they want to open the link in new tab or new window. Currently portlet communication or navigation is happening in the same page. I need to do it in new tab. I tried setting 'target ="_blank" and also target ="_new" ' on commandLink. but they are not opening the link in new page when i click on it. Would you please let me know How can i achieve this?

Note : i implemented IPC using JSR 168 and portlet wiring.