Oracle9iAS Portal Developer Kit
Adding Parameters and Events to Portlets

PDK Release 2 (9.0.2 and later)


Oracle9iAS Portal and the PDK introduce several new concepts - page parameters, public portlet parameters and events - that enable portlet developers to easily write reusable, complex portlets. In this document, portlet developers will learn how to create and use public portlet parameters, portlet events , and private portlet parameters. For a discussion of the fundamental concepts behind parameters and events in Oracle9iAS Portal review the article, A Primer on Portlet Parameters and Events.

The examples in this article demonstrate how to construct the declarations required in provider.xml and the code required in the implementation .jsp files. Note that adding declarations to provider.xml will not automatically generate corresponding .jsp code nor will using the PDK APIs generate entries in provider.xml - the portlet developer must add directly any modifications to the portlet declaration and implementation.

Adding public Portlet Parameters

Adding public portlet parameters involves two steps - adding the public portlet parameter definitions to provider.xml and then making use of the public portlet parameters in the implementation file.

Portlet Declaration - provider.xml

The inputParameter element is used to define public portlet parameters and has the following associated data

Each inputParameter is a simple, independent declaration that does not reference any other element in provider.xml nor is referenced by any other such element.

The highlighted section in the following excerpt from the PDK Sample Event Web Provider’s provider.xml declares public portlet parameters for the Public Parameter Portlet:

<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> 
  <id>1</id> 
  <name>PublicParameterPortlet</name> 
  <title>Public Parameter Portlet</title> 
  <description>This is a portlet that declares public portlet parameters.</description> 
  <acceptContentType>text/html</acceptContentType> 
  <acceptContentType>text/vnd.oracle.mobilexml</acceptContentType> 
  <inputParameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> 
    <name>param1</name> 
    <displayName>Input Parameter #1</displayName> 
    <description>This is public portlet parameter #1</description> 
  </inputParameter> 
  <inputParameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> 
    <name>param2</name> 
    <displayName>Input Parameter #2</displayName> 
    <description>This is public portlet parameter #2</description> 
  </inputParameter> 
  ... 
</portlet> 

Portlet Implementation

Public portlet parameters are read-only inputs to the portlet. Each public portlet parameter may have zero, one, or many values. Zero values means the public portlet parameter was not mapped by the page designer. When mapped to a page parameter, a public portlet parameter will take on all the values of the page parameter. When mapped to a system or constant value the public portlet parameter will have only one value.

The following code is taken from publicparam.jsp, the implementation file for the Public Parameter Portlet from the PDK Sample Event Web Provider. A table is created that contains all the values for the two public portlet parameters, param1 and param2

Note the following methods used in this example:

<%@page import = "oracle.portal.provider.v2.render.PortletRenderRequest,
                  oracle.portal.provider.v2.http.HttpCommonConstants"
%>


<table border=1> 
  <tr> 
    <th align=left>Parameter Name</th> 
    <th align=left>Value</th> 
  </tr> 
  
<% 
PortletRenderRequest portletRequest =  
   (PortletRenderRequest)request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); 
  
// The public portlet parameters declared in provider.xml are "param1" and "param2" 
String[] names = { "param1", "param2" }; 
  
// Display values for each of the public portlet 
// parameters "param1" and "param2" 
for ( int i = 0; i < 2; i++ ) 
{ 
  // Get the public portlet parameter values 
  String[] values = portletRequest.getParameterValues(names[i]);
  
  // Display the parameter's values. 
  // Each portlet parameter can have 0, 1, or multiple values. 
  if ( values == null ) 
  { 
    // Null array indicates no values for this parameter. 
%> 
    <tr> 
      <td><%= names[i] %></td> 
      <td>No values have been submitted yet.</td> 
    </tr> 
<% 
  } 
  else 
  { 
    // Loop through each of the values and display non-null values on a separate line. 
    for ( int j = 0; (values != null) && (j < values.length); j++ ) 
    { 
%> 
      <tr> 
        <td><%= names[i] %></td> 
        <td><%= values[j] %></td> 
      </tr> 
<% 
    } 
  } 
} 
%> 
</table> 

Making a Generic Public Parameter Receiving Portlet

In the previous example, the Public Parameter Portlet looked up public portlet parameter values using specific names. A more generic way to implement a portlet would be to retrieve all the parameter values passed to a portlet and then to filter out parameters by name.

The following example uses the following methods :

<%@page import = "oracle.portal.provider.v2.render.PortletRenderRequest, 
                  oracle.portal.provider.v2.http.HttpCommonConstants" 
%> 
  
<table border=1> 
  <tr> 
    <th align=left>Parameter Name</th> 
    <th align=left>Value</th> 
  </tr> 
  
<% 
PortletRenderRequest portletRequest =  
   (PortletRenderRequest)request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); 
  
// Get the portlet definition - needed to get the public portlet parameters 
PortletDefinition portlet = portletRequest.getPortletDefinition(); 
  
// Get the public portlet parameters 
ParameterDefinition[] parameters = portlet.getInputParameters(); 
  
// Display all values for each of the public portlet parameters 
for (int currParameter = 0; currParmaeter < parameters.length; currParameter++) 
{ 
  String name = parameters[currParameter].getName(); 
  
  // Get the parameter values 
  String[] values = portletRequest.getParameterValues(name); 
  
  // Display the parameter's values. 
  if ( values == null ) 
  { 
    // Null array indicates no values for this parameter. 
%> 
    <tr> 
      <td><%= names[i] %></td> 
      <td>No values have been submitted yet.</td> 
    </tr> 
<% 
  } 
  else 
  { 
    // Loop through each of the values and display non-null values on a separate line. 
    for ( int j = 0; (values != null) && (j < values.length); j++ ) 
    { 
%> 
      <tr> 
        <td><%= names[i] %></td> 
        <td><%= values[j] %></td> 
      </tr> 
<% 
    } 
  } 
} 
%> 
</table> 

Adding Events and Event Parameters

Adding events and event parameters involves two steps - adding the event and event parameter definitions to provider.xml and then making use of them in the implementation file.

Portlet Declaration - Provider.xml

The event element is used to define portlet public parameters and has the following associated data

Each event is a simple, independent declaration that does not reference any other element in provider.xml nor is referenced by any other such element.

Event parameters are very similar in syntax to public portlet parameters with the only difference being that the element is named parameter instead of inputParameter and each parameter element is nested within an owning event element.

The highlighted section in the following excerpt from the PDK Sample Event Web Provider ‘s provider.xml declares events and event parameters for the Event and Parameter Form Portlet:

<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> 
  <id>2</id> 
  <name>EventParameterForm</name> 
  <title>Event and Parameter Form Portlet</title> 
  <shortTitle>Event Parameter Form</shortTitle> 
  <description>This portlet demonstrates both how to receive data using public portlet 
    parameters and how to use a portlet event and event parameters to send data to a  
    page. 
  </description> 
  ... 
  <inputParameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> 
    <name>Name</name> 
    <displayName>Name</displayName> 
    <description>User name</description> 
  </inputParameter> 
  <inputParameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> 
    <name>Age</name> 
    <displayName>Age</displayName> 
    <description>User age</description> 
  </inputParameter> 
  <event class="oracle.portal.provider.v2.DefaultEventDefinition"> 
    <name>submit</name> 
    <description>Use this event to submit the form data to a page</description> 
    <parameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> 
      <name>name</name> 
      <displayName>name</displayName> 
      <description>Name entered in portlet form</description> 
    </parameter> 
    <parameter class="oracle.portal.provider.v2.DefaultParameterDefinition"> 
      <name>age</name> 
      <displayName>age</displayName> 
      <description>Age entered in portlet form</description> 
    </parameter> 
  </event> 
  <event class="oracle.portal.provider.v2.DefaultEventDefinition"> 
    <name>cancel</name> 
    <description>Use this event to handle cancellation while filling  
      out a form</description> 
  </event> 
    ...  
</portlet> 

Portlet Implementation

The following code was extracted from eventform.jsp, the implementation file for the Event and Parameter Portlet from the PDK Sample Event Web Provider. This example demonstrates setting up a form that can fire two events with one of the events having two event parameters.

In this example, a form is built up that has two input fields - name and age. There are two ways to submit the form - pressing one of the Submit or Cancel buttons. Pressing Submit causes the event parameters name and age to take on the values entered into the text fields. Pressing Cancel means that the values entered into the text fields will be lost because there are no event parameters declared for Cancel.

Note the following methods used in this example:

<%@page import="oracle.portal.provider.v2.render.PortletRendererUtil, 
                oracle.portal.provider.v2.render.http.HttpPortletRendererUtil, 
                oracle.portal.provider.v2.event.EventUtils" 
%> 
  
<% 
// The portlet definition in provider.xml includes the following: 
//    - Portlet parameters "Name" and "Age" 
//    - Event "submit" with event parameters "name" and "age" 
//    - Event "cancel" with no event parameters 
// 
// Note that event and parameter names are case sensitive. 
String eventSubmit    = EventUtils.eventName("submit"); 
String eventParamName = EventUtils.eventParameter("name"); 
String eventParamAge  = EventUtils.eventParameter("age"); 
String eventCancel    = EventUtils.eventName("cancel"); 
%> 
  
This portlet shows how to use portlet events and portlet event parameters 
to send data to a page and how to use public portlet parameters 
to receive page parameter values. 
<!-- 
  -- Associate the action URL with the form’s action attribute 
  --> 
<form method="POST" action="<%= HttpPortletRendererUtil.htmlFormActionLink(request, PortletRendererUtil.EVENT_LINK) % 
>"> 
  
<!-- 
  -- Oracle Portal uses hidden form fields to pass system information top itself 
  -- when a page is redisplayed through a link. 
  --> 
<%= HttpPortletRendererUtil.htmlFormHiddenFields(request, PortletRendererUtil.EVENT_LINK) %> 
  
<table> 
  <tr> 
    <td> <b>Name :</b> </td> 
    <td> 
            <input type="text" size="20" name="<%= eventParamName %>" value=""> 
    </td> 
  </tr> 
  <tr> 
    <td> <b>Age : </b> </td> 
    <td> 
      <input type="text" size="3" name="<%= eventParamAge %>" value=""> 
    </td> 
  </tr> 
</table> 
<INPUT TYPE=submit name="<%= eventSubmit %>" Value="Submit"> 
<INPUT TYPE=submit name="<%= eventCancel %>"  Value="Cancel"> 
</form> 

Simple links can be also be used for firing portlet events as demonstrated in the following alternative implementation for eventform.jsp. In this example, the event parameters cannot be entered by the user since there is no HTML form. Instead, the event parameters name and age are assigned a page parameter value and a constant value, respectively.

Note the following method used in the implementation 

<%@page import="oracle.portal.provider.v2.render.PortletRenderRequest,
                  oracle.portal.provider.v2.http.HttpCommonConstants,
                  oracle.portal.provider.v2.render.PortletRendererUtil,
                oracle.portal.provider.v2.event.EventUtils,
                oracle.portal.utils.v2.NameValuePair"
%>
 
<%
PortletRenderRequest portletRequest = 
  (PortletRenderRequest)request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
 
//
// The portlet definition in provider.xml includes the following:
// - Portlet parameters "Name" and "Age"
// - Event "submit" with event parameters "name" and "age"
// - Event "cancel" with no event parameters
//
// Note that event and parameter names are case sensitive.
//
String eventSubmit = EventUtils.eventName("submit");
String eventParamName = EventUtils.eventParameter("name");
String eventParamAge = EventUtils.eventParameter("age");
String eventCancel = EventUtils.eventName("cancel");
 
// Build up the list of parameters for the "submit" event
NameValuePair[] eventSubmitParams = new NameValuePair[3];
 
// Give the 'name' event parameter the value of the page parameter 'Name' 
if (request.getParameter("Name") == null)
{
  eventSubmitParams[0] = new NameValuePair(eventParamName, "");
}
else
{
  eventSubmitParams[0] = new NameValuePair(eventParamName, request.getParameter("Name"));
}
 
// Give the 'age' event parameter the constant value '23' 
eventSubmitParams[1] = new NameValuePair(eventParamAge, "23");
 
// The event name must be passed as a parameter on the URL
eventSubmitParams[2] = new NameValuePair(eventSubmit, "");
 
// Build up an empty list of parameters for the "cancel" event
NameValuePair[] eventCancelParams = new NameValuePair[1];
 
// The event name must be passed as a parameter on the URL
eventCancelParams[0] = new NameValuePair(eventCancel, "");
%>
 
This portlet shows how to use portlet events and portlet event parameters
to send data to a page and how to use public portlet parameters
to receive page parameter values.
 
<a href="<%=PortletRendererUtil.constructLink(portletRequest, 
  portletRequest.getRenderContext().getEventURL(), eventSubmitParams, true, true)%>">
Fire the 'submit' event by clicking on this link
</a>
<br>
 
<a href="<%=PortletRendererUtil.constructLink(portletRequest, 
  portletRequest.getRenderContext().getEventURL(), eventCancelParams, true, true)%>">
Fire the 'cancel' event by clicking on this link
</a>
<br>

Setting the passAllUrlParams Flag

The default behavior in previous versions of Oracle9iAS Portal was for all URL parameters to be passed to all portlets. However, with Oracle9iAS Portal, the default behavior has changed so that a portlet only receives its own public portlet parameters, its own private portlet parameters stripped of any qualification prefix, and the PDK system parameters. The passAllUrlParams flag was added to Oracle9iAS Portal to simplify migration of portlets built using previous versions of Oracle9iAS Portal.

When the value true is specified for the passAllUrlParamselement in a portlet’s declaration in provider.xml, the old style behavior of parameter passing will be performed for that particular portlet - it will receive all URL parameters. The following sample demonstrates how to add this flag to a portlet declaration in provider.xml, in this case the Public Parameter Portlet.

<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> 
  <id>1</id> 
  <name>PublicParameterPortlet</name> 
  <title>Public Parameter Portlet</title> 
  <description>This is a portlet that declares public portlet parameters.</description> 
  <passAllUrlParams>true</passAllUrlParams> 
... 
</portlet> 
Review the article, A Primer on Portlet Parameters and Events for more discussion of the passAllUrlParams flag and selective passing of parameters to portlets.

Adding Persistent Private Portlet Parameters

Private portlet parameters are by portlet developers to either maintain state for a portlet, using persistent private portlet parameters, or to enable one-time-only portlet actions, using transient private portlet parameters.

Private portlet parameters are created and used solely in the implementation file. Thus, they do not appear in provider.xml and are not available to the page designer.

The following code example demonstrates how to implement the Record Viewer Portlet that is used as an example in the article, A Primer on Portlet  Parameters and Events. In this example, one piece of persistent state information, the current record number, is passed to the portlet when a page is redisplayed. The current record number will be incremented or decremented depending on whether the user presses the Next or the Previous button.

The current record numberis maintained as state by using a qualified private portlet parameterbecause qualified private portlet parameters are preserved when following a link or submitting a form back to the same page (for more discussion of preservation of parameters review the article, A Primer on Portlet Parameters and Events). The qualified private portlet parameter is read in when the page is displayed and is assigned a value each time the form is submitted. Qualified private portlet parameters also solve the problem of name conflicts of private portlet parameters that may occur when using multiple instances of a portlet on a page or instances of different portlets that use the same private portlet parameter name.

Note the following methods used in this example:

<%@page import="java.util.*, oracle.portal.provider.v2.*" %> 
<%@page import="oracle.portal.provider.v2.http.HttpCommonConstants" %> 
<%@page import="oracle.portal.provider.v2.render.PortletRendererUtil" %> 
<%@page import="oracle.portal.provider.v2.render.PortletRenderRequest" %> 
<%@page import="oracle.portal.provider.v2.render.http.HttpPortletRendererUtil" %> 
  
<%@ page import="oracle.portal.utils.v2.NameValuePair" %> 
  
<% 
  String textCurrRecord  = "currRecord"; 
  String paramCurrRecord =  
    HttpPortletRendererUtil.portletParameter(request, textCurrRecord); 
  
  PortletRenderRequest portletRequest = (PortletRenderRequest) 
    request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); 
  
  // Retrieve the current record number passed to the portlet 
  int currRecord; 
  String submittedCurrRecord = portletRequest.getQualifiedParameter(textCurrRecord); 
  if (submittedCurrRecord == null) 
  { 
    currRecord = 1; 
  } 
  else 
  { 
    try 
    { 
      currRecord = Integer.valueOf(submittedCurrRecord).intValue(); 
    } 
    catch (NumberFormatException e) 
    { 
      currRecord = 1; 
    } 
  } 
  
  // Calculate the previous and next values 
  int prevRecord = currRecord - 1; 
  if (prevRecord < 1) 
  { 
    prevRecord = 1; 
  } 
  int nextRecord = currRecord + 1; 
%> 
  
<b>This portlet shows how to use qualified, persistent  
private parameters to maintain portlet state.</b> 
  
<br><br> 
  
<b>Current record: <%=currRecord%></b> 
  
// The first form handles the previous action 
<form method="POST" action="<%= HttpPortletRendererUtil.htmlFormActionLink( 
      request,PortletRendererUtil.PAGE_LINK) %>"> 
  <%= HttpPortletRendererUtil.htmlFormHiddenFields( 
      request,PortletRendererUtil.PAGE_LINK) %> 
  <INPUT TYPE="hidden" name="<%=paramCurrRecord%>" value="<%=prevRecord%>" /> 
  <INPUT TYPE=submit name="Previous" Value="Previous"> 
</form> 
  
// The second form handles the next action 
<form method="POST" action="<%= HttpPortletRendererUtil.htmlFormActionLink( 
      request,PortletRendererUtil.PAGE_LINK) %>"> 
  <%= HttpPortletRendererUtil.htmlFormHiddenFields( 
      request,PortletRendererUtil.PAGE_LINK) %> 
  <INPUT TYPE="hidden" name="<%=paramCurrRecord%>" value="<%=nextRecord%>" /> 
  <INPUT TYPE=submit name="Next" Value="Next"> 
</form> 

Adding Transient Private Portlet Parameters

The following code example demonstrates how to implement the Bank Account Portlet that is used as an example in the article, A Primer on Portlet Parameters and Events. In this example, two pieces of transient state information, the action and the amount of money, are passed to the portlet when the page is redisplayed via a Bank Account Portlet form submission. The action value is used to indicate that a bank account transfer is to be performed immediately. The amount value determines the size of the bank account transfer.

Portlet Declaration - provider.xml

Transient portlet parameters rely on the use of unqualified portlet parameters. If the passAllUrlParams flag is set to true in the portlet declaration in provider.xml the unqualified portlet parameters will be passed to a portlet (along with all other URL parameter values). Setting the passAllUrlParams flag to false, the default value, will cause unqualified portlet parameters to be filtered out and not sent to the portlet.

<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition"> 
  <id>7</id> 
  <name>BankAccount</name> 
  <title>Bank Account Portlet</title> 
  <description> 
    This portlet uses the passAllUrlParams flag and unqualified parameters 
    to allow the user to request that a bank account transaction be performed. 
  </description> 
  <passAllUrlParams>true</passAllUrlParams> 
  ... 
</portlet> 

Portlet Implementation

Like persistent private portlet parameters, transient private portlet parameters are created and used solely in the implementation file. Thus, they do not appear in provider.xml and are not available to the page designer, however, the passAllUrlParams flag must be set to true so that they are actually sent to a portlet and not filtered out by Oracle9iAS Portal.

The action and amount values are implemented as transient state by using unqualified portlet parameters because unqualified portlet parameters are never preserved when following a link or submitting a form back to the same page (for more discussion of preservation of parameters review the article, A Primer on Parameters and Events). The unqualified portlet parameter is read in when the page is displayed and is assigned a value each time the Bank Account Portlet’s form is submitted. Unqualified portlet parameters leave the onus on the portlet developer to solve the problem of name conflicts of private portlet parameters that may occur when using multiple instances of a portlet on a page or instances of different portlets that use the same private portlet parameter name. This example will work correctly if only one Bank Account Portlet is added to a page. The portlet developer must devise some way of uniquely naming a portlet instance’s unqualified portlet parameters. The only restriction the the portlet developer must observe is that if an unqualified portlet parameter is given the prefix ‘_piref’ then Oracle Portal will recognize it as a qualified private portlet parameter.

Note the following methods used in this example:

<%@page import="java.util.*, oracle.portal.provider.v2.*" %> 
<%@page import="oracle.portal.provider.v2.http.HttpCommonConstants" %> 
<%@page import="oracle.portal.provider.v2.render.PortletRendererUtil" %> 
<%@page import="oracle.portal.provider.v2.render.PortletRenderRequest" %> 
<%@page import="oracle.portal.provider.v2.render.http.HttpPortletRendererUtil" %> 
  
<% 
  String paramAmount = "Amount"; 
  String paramAction = "Action"; 
  
  PortletRenderRequest portletRequest =  
 (PortletRenderRequest) request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST); 
%> 
  
<b>This portlet shows how to use the passUrlParams flag and  
unqualified, transient parameters to perform a portlet action.</b> 
  
// The account transfer is performed by submitting the following form 
<form method="POST" action="<%= HttpPortletRendererUtil.htmlFormActionLink( 
    request,PortletRendererUtil.PAGE_LINK) %>"> 
  <%= HttpPortletRendererUtil.htmlFormHiddenFields(request,PortletRendererUtil.PAGE_LINK) %> 
  <table> 
    <tr> 
      <td> 
        <b>Amount $</b> 
      </td> 
      <td> 
        <input type="text" size="20" name="<%= paramAmount %>" value=""> 
      </td> 
    </tr> 
  </table> 
  <br> 
  <INPUT TYPE=submit name="<%= paramAction %>" Value="Transfer"> 
</form> 
  
// Parse the inputs to see if a transfer should be performed 
<% 
if (portletRequest.getParameter(paramAction) != null) 
{ 
  String submittedAmount = portletRequest.getParameter(paramAmount); 
  
  if (submittedAmount == null || submittedAmount.trim().length() == 0) 
  { 
%> 
    <b>Please specify an amount!</b> 
<% 
  } 
  else 
  { 
    try 
    { 
      double amount = Double.valueOf(submittedAmount).doubleValue(); 
      if (amount != 0) 
      { 
%> 
        <b>Successfully transferred $<%=submittedAmount%>.</b> 
<% 
      } 
    } 
    catch (NumberFormatException e) 
    { 
%> 
      <b>Invalid amount.</b> 
<% 
    } 
  } 
} 
%> 

Revision History: