60 Building Java Portlets Using the Oracle PDK-Java

This chapter describes how to build Java portlets using the Oracle PDK-Java. Oracle PDK-Java is an Oracle proprietary technology for building Java portlets.

Tip:

For building new Java portlets, you should consider using the JSR 286 standard. For more information, see Chapter 59, " Building Standards-Based Java Portlets Using JSR 286."

This chapter includes the following sections:

60.1 Introduction to PDK-Java Portlets

PDK-Java gives you a framework to simplify the development of Java portlets by providing commonly required utilities and enabling you to leverage existing development skills and application components such as JSPs, servlets, and static HTML pages. PDK-Java also enables you to create portlets without having to deal directly with the complexity of communications between WebCenter Portal: Framework and producers.

The PDK-Java framework is divided into the following areas:

  • The Producer Adapter insulates the developer from the HTTP syntax defined by WebCenter Portal: Framework for communication with web producers. It translates the information passed between WebCenter Portal: Framework and your Java web producer. Without an adapter, your producer would not only manage portlets, but it would also have to communicate this information directly to WebCenter Portal: Framework in the expected language. The adapter eliminates the need for your web producer to understand the portal language and vice-versa.

  • The Producer Interface defines the APIs (functions) required by your Java implementation to integrate with the Producer Adapter. The Producer Adapter receives messages from the Framework application, translates them into calls to the Producer Interface, and translates the producer's response into a format that the application can understand. The Producer Interface contains a set of Java classes that define the methods your producer implements and, in often, provides a standard implementation. Some of the primary classes are as follows:

    • ProviderDefinition (oracle.portal.provider.v2.ProviderDefinition)

    • ProviderInstance (oracle.portal.provider.v2.ProviderInstance)

    • PortletDefinition (oracle.portal.provider.v2.PortletDefinition)

    • PortletInstance (oracle.portal.provider.v2.PortletInstance)

    • ParameterDefinition (oracle.portal.provider.v2.ParameterDefinition)

    • EventDefinition (oracle.portal.provider.v2.EventDefinition)

  • The Producer Runtime provides a base implementation that follows the specification of the Producer Interface. The Producer Runtime includes a set of default classes that implement each of the Producer Interfaces and enables you to leverage the rendering, personalization, and security frameworks provided with PDK-Java. These classes and the associated frameworks simplify the development of a producer by implementing common functions for WebCenter Portal: Framework requests and providing a declarative mechanism for configuring the producer. Using the Producer Runtime, you can focus your development efforts on the portlets themselves rather than the infrastructure needed to communicate with the Framework application. If the standard behavior of the Producer Runtime does not meet your requirements, then you can easily extend or override specific behaviors. Some of the primary classes are as follows:

    • DefaultProviderDefinition (oracle.portal.provider.v2.DefaultProviderDefinition)

    • DefaultProviderInstance (oracle.portal.provider.v2.DefaultProviderInstance)

    • DefaultPortletDefinition (oracle.portal.provider.v2.DefaultPortletDefinition)

    • DefaultPortletInstance (oracle.portal.provider.v2.DefaultPortletInstance)

    • PortletRenderer (oracle.portal.provider.v2.render.PortletRenderer)

    • PortletPersonalizationManager (oracle.portal.provider.v2.personalize.PortletPersonalizationManager)

    • PortletSecurityManager (oracle.portal.provider.v1.http.DefaultSecurityManager)

  • The Producer Utilities provide methods for simplifying the rendering of portlets. The utilities include methods for constructing valid links (hrefs), rendering the portlet's container (including the header), rendering HTML forms that work within a page, and supporting portlet caching.

Oracle JPDK producers use open standards, such as XML, SOAP, HTTP, or Java EE for deployment, definition, and communication with applications. WebCenter Portal incorporates portlets from a Oracle JPDK producer, which communicates with the consumer application using SOAP over HTTP.

There are several benefits to developing portlets and exposing them through Oracle JPDK producers:

  • Deploy portlets remotely

  • Leverage existing web application code to create portlets

  • Specify producers declaratively

  • Use standard Java technologies (for example, servlets and JSPs) to develop portlets.

To expose your portlets using a Oracle JPDK producer, you must first create a producer that manages your portlets and communicates with WebCenter Portal using SOAP. For more information, see Section 60.5, "Deploying PDK-Java Portlets."

For more information about the PDK-Java, see the Oracle Fusion Middleware Java API Reference for Oracle PDK-Java at:

http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10691/index.html?overview-summary.html

60.2 Creating a PDK-Java Portlet

WebCenter Portal provides a wizard, available in JDeveloper, for quickly and easily creating the initial framework of your PDK-Java portlets.

This section includes the following subsections:

60.2.1 How to Create a PDK-Java Portlet

Using the Create Oracle PDK-Java Portlet wizard in JDeveloper you can quickly and easily create PDK-Java portlets. You can choose which portlet modes you want to implement and the implementation method (JSP, HTTP servlet, Java class, or HTML) to use for each mode. The wizard then creates a simple implementation for each of the selected modes.

To create a PDK-Java portlet using the JDeveloper wizard:

  1. In JDeveloper, open the portlet producer application under which you want to create your portlet, or create a new portlet producer application.

    For information about how to create a portlet producer application, see Section 5.5, "Creating a Portlet Producer Application."

    Note:

    If you do not use the WebCenter Portal - Portlet Producer Application template to create the portlet producer application, you must manually add the appropriate portlet building technology scopes to the application.

    Applications built using the WebCenter Portal - Framework Application template are not scoped for portlet creation.

  2. Right-click the project under which you want to create your portlet (for example, Portlets), and choose New.

    Note:

    To create the portlet in an existing producer, right-click the producer's provider.xml file and choose Add Portlet. This takes you directly to the General Portlet Information page of the Create Oracle PDK-Java Portlet wizard (step 8).

  3. In the New Gallery, expand Web Tier, select Portlets and then Oracle PDK-Java Portlet, and click OK.

  4. On the Provider Details page of the Create Oracle PDK-Java Portlet wizard, enter a name for the new producer to contain your portlet. This name must be unique within the project.

    Tip:

    In the PDK-Java, the term provider is used instead of producer. A provider is the same thing as a producer.

  5. Select Generate Deployment Properties File.

    This automatically generates two .properties files:

    • serviceID.properties defines properties for a producer with that service ID. The service ID has the same value as the producer name.

    • _default.properties is a default properties file. A producer application may have multiple producers, each with its own service ID. On registration, if no service ID is defined, then the default properties file is used.

  6. Select Generate XML Entries.

    This automatically generates a producer definition file (provider.xml) for the producer that contains details of the portlets belonging to the producer, including those generated by the wizard.

  7. Select Generate Index JSP and then click Next.

    This automatically generates an index.jsp file that lists all the producers that reside in the application with hyperlinks that enable easy access to producer test pages.

  8. On the General Portlet Information page, enter a name and display name for your portlet.

    The name is used internally and is not exposed to users. The display name is displayed to users in portlet selection lists, such as the Component Palette.

    The description is not implemented in Framework applications so you do not need to enter a value in this field unless your portlet is likely to be consumed by other applications, such as Oracle Portal.

  9. In the Timeout Interval (Seconds) field, enter the number of seconds to allow for rendering the portlet.

  10. In the Timeout Message field, enter a message to display if the rendering of the portlet exceeds the timeout interval specified and then click Next.

  11. On the View Modes page, under Show Page, from the Implementation Style dropdown list, select the implementation style to use for the portlet's Shared Screen mode.

    • Select JSP to implement the portlet's Shared Screen mode as a JavaServer Page. In the File Name field, enter the name of the file to be generated by the wizard.

    • Select HTTP Servlet to implement the portlet's Shared Screen mode as an HTTP servlet. In the Package Name field, enter the name of the package that contains the HTTP servlet. In the Class Name field, enter the Java class to be referenced with the portlet's Shared Screen mode.

    • Select HTML File to implement the portlet's Shared Screen mode as an HTML file. In the File Name field, enter the name of the file to be generated by the wizard. Note that, when you choose HTML File, the following code is added inside the <renderer> element of your provider.xml file:

      <showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer">
          <resourcePath>provider_id/portlet_name/file.html</resourcePath>
          <contentType>content_type</contentType>
          <charSet>char_set</charSet>
       </showPage>
      

      charSet indicates the character set that the producer must use to encode the HTML page. The default character set is determined by JDeveloper preferences. If you require a different character set, you must update this element of provider.xml accordingly.

    • Select Java Class to implement the portlet's Shared Screen mode as a Java class. In the Package Name field, enter the name of the package that contains the Java class. In the Class Name field, enter the name of the Java class.

    For more information about Shared Screen mode, see Section 57.4.1.1, "View Mode."

  12. To implement Full Screen mode for your portlet, select Show Details Page and then select an implementation style as described for Shared Screen mode in step 11.

  13. At this point in the wizard, you can click Finish to create the portlet immediately, using the default values for all remaining settings.

    To provide additional details for your portlet, click Next and follow the remaining steps.

  14. On the Customize Modes page, Edit Page is selected by default. To implement Edit mode for your portlet, select an implementation style as described for Shared Screen mode in step 11. If you do not want to implement Edit mode, then deselect Edit Page.

    For more information about Edit mode, see Section 57.4.1.2, "Edit Mode."

  15. To implement Edit Defaults mode for your portlet, select Edit Defaults Page, and then select an implementation style as described for Shared Screen mode in step 11.

    For more information about Edit Defaults mode, see Section 57.4.1.3, "Edit Defaults Mode."

  16. Click Next.

  17. On the Additional Modes page, to implement Help mode for your portlet, select Help Page, and then select an implementation style as described for Shared Screen mode in step 11.

    For more information about Help mode, see Section 57.4.1.4, "Help Mode."

  18. To implement About mode for your portlet, select About Page, and then select an implementation style as described for Shared Screen mode in step 11.

    For more information about About mode, see Section 57.4.1.5, "About Mode."

  19. Click Next.

  20. On the Public Portlet Parameters page, click Add to add a public parameter to your portlet.

    This adds a new row to the table of parameters. Double-click each field in the row to provide a name, display name, and description for the parameter.

    Repeat this step to add more public parameters. When you are done, click Next.

    Public portlet parameters enable a portlet to communicate with the page on which it resides and with other portlets on that page. For more information, see Section 60.3.3, "How to Implement Public Parameters."

  21. Oracle PDK-Java events are not supported in Framework applications, so on the Public Portlets Events page, click Finish.

    For more information about events, see the Oracle Fusion Middleware Developer's Guide for Oracle Portal.

60.2.2 What Happens When You Create a PDK-Java Portlet

When you use the Create Oracle PDK-Java Portlet wizard, JDeveloper generates a default implementation of the portlet. Specifically, the following files are created:

  • Files for each portlet mode you selected, for example portletnameEditPage.jsp.

  • provider.xml is the producer definition file that contains details of the portlets belonging to the producer.

  • web.xml is the web deployment descriptor file for the application.

  • weblogic.xml includes a shared library definition pointing to the PDK-Java shared library.

  • index.jsp is used by JDeveloper for testing purposes.

  • _default.properties is the default properties file.

  • serviceID.properties is the properties file for the producer identified by serviceID.

All these files are required to deploy and run the portlet successfully, except for index.jsp.

You can see all these files in the Application Navigator, as shown in Figure 60-1.

Figure 60-1 Files Generated for a PDK-Java Portlet

Shows contents of Applications - Navigator.
Description of "Figure 60-1 Files Generated for a PDK-Java Portlet"

60.3 Developing PDK-Java Portlets

When you have built your initial portlet implementation using the Create Oracle PDK-Java Portlet wizard, the next step is to create the code that drives the portlet content and behavior.

You can find the JavaDoc reference for the PDK-Java in the Oracle Fusion Middleware Java API Reference for Oracle PDK-Java at:

http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10691/index.html?overview-summary.html

This section includes the following subsections:

The source code for many of the examples referenced in this section is available as part of the Portlet Developer's Kit (PDK).

When you unzip the PDK-Java, you can find the examples in:

../pdk/jpdk/v2/src/oracle/portal/sample/v2/devguide

60.3.1 General Guidelines for PDK-Java Portlets

When you build PDK-Java portlets for use in WebCenter Portal, you should consider the following:

  • Your portlet must not contain any code that relies upon the URL format or parameters in the request that were not explicitly added by your portlet.

  • You should never assume that your portlet is the only one on a page, regardless of the portlet mode. For example, even if your portlet is in Edit mode, you should not assume that it is the only portlet on the page.

  • Never write a portlet mode that simply redirects. A redirect can only be issued while processing a post to your portlet or following a link generated by your portlet.

60.3.2 How to Add Portlet Modes

In the Create Oracle PDK-Java Portlet wizard, you add portlet modes by checking boxes on the wizard pages. For more information about using the wizard, see Section 60.2.1, "How to Create a PDK-Java Portlet." For each portlet mode that you select in the wizard, a basic skeleton is created. If you want to add a portlet mode after creating the portlet, you can do that by updating provider.xml and creating HTML or JSPs in JDeveloper.

The principles of implementing portlet modes using RenderManager are the same for all modes.

For more detailed information about the PDK runtime classes used in this section, see the JavaDoc in the Oracle Fusion Middleware Java API Reference for Oracle PDK-Java at:

http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10691/index.html?overview-summary.html

To add a portlet mode:

  1. In JDeveloper, open the application that contains the portlet.

  2. Expand the project that contains the portlet.

  3. Expand the Web Content node and then the htdocs node and then the node for the producer.

  4. Right-click the node for the portlet and choose New.

    Tip:

    The node for the portlet is located under Web Content > htdocs > provider.

  5. In the New Gallery, expand Web Tier, select HTML or JSP, and click OK.

    You must create an HTML file or a JSP for each mode to add to your portlet. For example, to implement Help mode, create an HTML file to provide the help content.

  6. In the resulting dialog, enter a file name for the HTML file or JSP and click OK.

  7. In the visual editor, edit the content of the page to implement the desired functionality.

    For example, for Help mode, you could add the following HTML:

    <p>This is the <i>Help</i> mode of your portlet!</p>
    
  8. In the Application Navigator, right-click the provider.xml file for the provider that owns the portlet and choose Open.

    Tip:

    The provider.xml file is located under Web Content > WEB-INF > providers > provider.

  9. Change the value of the appropriate tag for the mode you are adding to true.

    For example, if you are adding Help mode, change the hasHelp tag as follows:

    <hasHelp>true</hasHelp>
    

    This indicates to the PDK Framework that a link or icon to that mode should be rendered.

  10. Add the code to point to the HTML page or JSP that you created earlier for the mode.

    For example, for the Help page, add the following code:

    <helpPage>/htdocs/myprovider/myportlet/myHelpPage.html</helpPage>
    
  11. Save your changes.

60.3.3 How to Implement Public Parameters

PDK-Java and WebCenter Portal: Framework provide public and private portlet parameters to enable you to easily write reusable, complex portlets. The Create Oracle PDK-Java Portlet wizard creates portlets that are set up to use parameters. This feature enables you to focus solely on adding business logic to your portlets and does not require any changes to provider.xml.

Using the Create Oracle PDK-Java Portlet wizard, you can easily create a portlet with public parameters. When you register the producer and drop the portlet on a page, the portlet's parameters are automatically linked to page variables.

Note:

Each portlet is limited to 4K of data. The lengths of parameter and event names, display names, and descriptions all contribute toward this 4K limit. Hence, you should not use too many parameters and events for each portlet, or give them lengthy names and descriptions.

To create a portlet with public parameters:

  1. In JDeveloper, open the application that contains the portlet.

  2. Right-click the project under which you want to create your portlet, and choose New.

    Note:

    To create the portlet in an existing producer, right-click the producer's provider.xml file and choose Add Portlet. This takes you directly to the General Portlet Information page of the Create Oracle PDK-Java Portlet wizard.

  3. In the New Gallery, expand Web Tier, select Portlets and then Oracle PDK-Java Portlet, and click OK.

  4. Proceed through the Create Oracle PDK-Java Portlet wizard until you reach the Public Portlet Parameters page.

    See Section 60.2.1, "How to Create a PDK-Java Portlet" for basic information about going through the wizard.

  5. On the Public Portlet Parameters page, click Add.

    This adds a new row to the table of parameters.

  6. Replace the default values in the Name, Display Name, and Description fields with something more meaningful for your parameter.

  7. Add more parameters as required and then click Finish.

  8. In the Application Navigator, right-click the provider.xml file for the provider that owns the portlet and choose Open.

    The provider.xml file is located under Web Content > WEB-INF > providers > provider.

    You should see entries for the parameters that you added on the Public Portlet Parameters page in the wizard, for example, as shown in Example 60-1.

    Example 60-1 provider.xml Sample, Public Parameters

    <?xml version = '1.0' encoding = 'UTF-8'?><?providerDefinition version="3.1"?>
    <provider class="oracle.portal.provider.v2.DefaultProviderDefinition">
      <session>false</session>
      <passAllUrlParams>false</passAllUrlParams>
      <preferenceStore class=
         "oracle.portal.provider.v2.preference.FilePreferenceStore">
       <name>prefStore1</name>
       <useHashing>true</useHashing>
      </preferenceStore>
      <portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
          <id>1</id>
          <name>MyPortlet</name>
          <title>My Portlet</title>
          <description>My Portlet Description</description>
          <timeout>40</timeout>
          <showEditToPublic>false</showEditToPublic>
          <hasAbout>false</hasAbout>
          <showEdit>true</showEdit>
          <hasHelp>false</hasHelp>
          <showEditDefault>false</showEditDefault>
          <showDetails>false</showDetails>
          <inputParameter class=
            "oracle.portal.provider.v2.DefaultParameterDefinition">
           <name>Parameter_01</name>
           <displayName>Parameter_01</displayName>
           <description>My first parameter</description>
          </inputParameter>
          <inputParameter class=
            "oracle.portal.provider.v2.DefaultParameterDefinition">
           <name>Parameter_02</name>
           <displayName>Parameter_02</displayName>
           <description>My second parameter</description>
          </inputParameter>
          <inputParameter class=
            "oracle.portal.provider.v2.DefaultParameterDefinition">
           <name>Parameter_03</name>
           <displayName>Parameter_03</displayName>
          </inputParameter>
          <renderer class="oracle.portal.provider.v2.render.RenderManager">
             <renderContainer>true</renderContainer>
             <renderCustomize>true</renderCustomize>
             <autoRedirect>true</autoRedirect>
             <contentType>text/html</contentType>
             <showPage>/htdocs/myportlet/MyPortletShowPage.jsp</showPage>
             <editPage>/htdocs/myportlet/MyPortletEditPage.jsp</editPage>
          </renderer>
          <personalizationManager class=
            "oracle.portal.provider.v2.personalize.PrefStorePersonalizationManager">
           <dataClass>
            oracle.portal.provider.v2.personalize.NameValuePersonalizationObject
           </dataClass>
          </personalizationManager>
       </portlet>
    </provider>
    
  9. In the Application Navigator, right-click the portletnameShowPage.jsp for your portlet and choose Open.

    The file is located under Web Content > htdocs > provider > portlet.

    The portlet includes logic for retrieving the parameters, for example, as shown in Figure 60-1.

    Example 60-2 ShowPage.jsp Sample

    <%@page contentType="text/html; charset=windows-1252"
            import="oracle.portal.provider.v2.render.PortletRenderRequest"
            import="oracle.portal.provider.v2.http.HttpCommonConstants"
            import="oracle.portal.provider.v2.ParameterDefinition"
    %>
    <%
       PortletRenderRequest pReq = (PortletRenderRequest)
          request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    %>
    <P>Hello <%= pReq.getUser().getName() %>.</P>
    <P>This is the <b><i>Show</i></b> render mode!</P>
    <%
       ParameterDefinition[] params =
           pReq.getPortletDefinition().getInputParameters();
    %>
    <p>This portlet's input parameters are...</p>
    <table align="left" width="50%" ><tr><td><span
    class="PortletHeading1">Name</span></td><td><span
    class="PortletHeading1">Value</span></td></tr>
    <%
       String name = null;
       String value = null;
       String[] values = null;
       for (int i = 0; i < params.length; i++)
       {
           name = params[i].getName();
           values = pReq.getParameterValues(name);
           if (values != null)
           {
               StringBuffer temp = new StringBuffer();
               for (int j = 0; j < values.length; j++)
               {
                   temp.append(values[j]);
                   if (j + 1 != values.length)
                   {
                       temp.append(", ");
                   }
               }
               value = temp.toString();
           }
           else
           {
               value = "No values have been submitted yet.";
           }
    %>
    <tr>
      <td><span class="PortletText2"><%= name %></span></td>
      <td><span class="PortletText2"><%= value %></span></td>
    </tr>
    <%
       }
    %>
    </table>
    
  10. Add logic to your portlet that allows it to submit parameter values entered by users.

  11. Create a second portlet using the same steps that simply displays parameter values that it retrieves.

  12. Register the producer with a Framework application. For more information, see Section 62.3, "Registering an Oracle PDK-Java Portlet Producer with a WebCenter Portal: Framework Application."

  13. Add the two portlets to a page in the application. For more information, see Section 62.6, "Adding Portlets to a Page."

  14. In the Structure window of the Application Navigator, right-click an element of the page and choose Go to Page Definition.

    The page definition should look similar to Example 60-3. Notice the variables at the page level and the parameters at the portlet level (indicated in bold).

    Example 60-3 Page Definition File Sample

    <?xml version="1.0" encoding="UTF-8"?>
    <pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel"
                    version="10.1.3.38.90" id="untitled1PageDef"
                    Package="view.pageDefs">
      <executables>
        <variableIterator id="variables">
          <variable Name="portlet1_Parameter_01" Type="java.lang.Object"/>
          <variable Name="portlet1_Parameter_02" Type="java.lang.Object"/>
          <variable Name="portlet1_Parameter_03" Type="java.lang.Object"/>
        </variableIterator>
        <portlet id="portlet1"       portletInstance="/oracle/adf/portlet/PdkPortletProducer1_1153936627784
              /applicationPortlets/Portlet1_abfc5a10_010c_1000_8003_82235f50d831"
            class="oracle.adf.model.portlet.binding.PortletBinding"
            xmlns="http://xmlns.oracle.com/portlet/bindings">
          <parameters>
            <parameter name="Parameter_01" pageVariable="portlet1_Parameter_01"/>
            <parameter name="Parameter_02" pageVariable="portlet1_Parameter_02"/>
            <parameter name="Parameter_03" pageVariable="portlet1_Parameter_03"/>
          </parameters>
        </portlet>
      </executables>
    </pageDefinition>
    
  15. Run the application.

  16. Enter values in the first portlet and the same values should be displayed in the second portlet.

60.3.4 How to Implement Private Parameters

In some cases, you might need a parameter that is known only to the portlet instance. These parameters are known as private parameters because they have no connection to the page and are known only to the portlet. Private parameters often come in handy when you are building navigation for your portlet. For example, if you have a portlet made up of multiple pages, then you can use private parameters to jump to another resource of the portlet.

This section includes the following subsections:

60.3.4.1 About Private Parameters

Private parameters are used in classic web applications to pass information from links or forms in the browser back to the server. The server in turn takes actions and returns the appropriate content. For example, if the user of a dictionary web site asks for information about hedgehogs, then the URL submitted to the server might append a private parameter as follows:

http://dictionary.reference.com/search?q=Hedgehog

If the server is responsible for rendering the whole page and the client communicates directly with the server, then this form of URL works well. In a Framework application, the client does not communicate directly with portlets. Instead, WebCenter Portal: Framework mediates between the client and the portlet. Moreover, because most pages have multiple portlets, WebCenter Portal: Framework communicates with multiple portlets.

For example, suppose a page contains two portlets, a thesaurus portlet and a dictionary portlet. Both portlets use q as a parameter to record the search queries made by the user. If the user queries the thesaurus portlet, then the URL used to rerequest the page with the updated thesaurus portlet must contain the thesaurus portlet's parameter, q. The thesaurus parameter must also be distinguished from dictionary portlet parameter 1, which performs the same function for that portlet.

You must ensure that the portlet meets the following criteria:

  • It properly qualifies its own parameters when they are built into links and forms.

  • It leaves unchanged any parameters that do not belong to it.

The following API call transforms an unqualified parameter name into a qualified parameter name:

HttpPortletRendererUtil.portletParameter(HttpServletRequest request, String param);

HttpPortletRendererUtil is in the package oracle.portal.provider.v2.render.http.

For example:

qualParamQ = HttpPortletRendererUtil.portletParameter(r, "q");

To fetch the value of a portlet parameter from the incoming request, you can use the following API:

Note:

The API converts the parameter name into the qualified parameter name before fetching the value from the incoming request. Hence, you need not perform this step.

PortletRenderRequest.getQualifiedParameter(String name)

PortletRenderRequest is in the package oracle.portal.provider.v2.render.

For example:

valueQ = r.getQualifiedParameter("q");

The other aspect of a portlet's responsibilities with private parameters is to not disturb the parameters on the URL that it does not own. The utilities you may use to ensure adherence to this rule are discussed in Section 60.3.4.3, "Building Links with the Portlet URL Types" and Section 60.3.4.4, "Building Forms with the Portlet URL Types."

60.3.4.2 About Portlet URL Types

When a portlet renders itself, WebCenter Portal: Framework passes it various URLs, which the portlet can then use to render links. You can fetch and manipulate these URLs to simplify the task of creating links. The following is a list of the URLs provided to portlets:

  • PAGE_LINK is a URL to the page upon which the portlet instance resides. You use this URL as the basis for all intraportlet links. If the portlet renders a link that navigates the user to another section of the same portlet, then this navigation must be encoded as a set of parameters using the PAGE_LINK.

  • DESIGN_LINK is a URL to the portlet's personalization (Edit mode) page. A portlet's Edit and Edit Defaults modes are not rendered on the same page as the portlet. The Edit and Edit Defaults modes take over the entire browser window. The portlet's Edit and Edit Defaults modes are not necessarily accessible to every user. It represents a minimal, static framework in which the portlet is free to render its personalization options. This URL is only of use when rendering Personalize links.

  • BACK_LINK is a URL to a useful return point from the current page where the portlet renders itself. For example, when the portlet is rendering its personalization page (Edit mode), this link refers to the page on which the portlet resides and from which the user navigated to the personalization page. Consequently, it is the link you encode in the buttons that accept or cancel the pending action. This URL is only useful for the desktop rendering of portlets (usually in Edit or Edit Defaults mode).

60.3.4.3 Building Links with the Portlet URL Types

To build links with Portlet URL types, you must access them and use them when writing portlet rendering code. To fetch the URL for a link, you call the following APIs in PDK-Java:

portletRenderRequest.getRenderContext().getPageURL()
portletRenderRequest.getRenderContext().getEventURL()
portletRenderRequest.getRenderContext().getDesignURL()
portletRenderRequest.getRenderContext().getLoginServerURL()
portletRenderRequest.getRenderContext().getBackURL()

In portlet navigation, you must add (or update) your portlet's parameters in the page URL. To perform this task, you can use the following API to build a suitable URL:

UrlUtils.constructLink(
    PortletRenderRequest pr,
    int linkType, -- UrlUtils.PAGE_LINK in this case
    NameValue[] params,
    boolean encodeParams,
    boolean replaceParams)

UrlUtils resides in the package called oracle.portal.provider.v2.url. Notice that you do not actually fetch the page URL yourself. Rather you use the supplied portlet URL type, UrlUtils.PAGE_LINK.

The parameter names in the params argument should be fully qualified. Moreover, if you properly qualify the parameters, UrlUtils.constructLink with the appropriate linkType does not disturb other URL parameters that are not owned by the portlet.

An alternative version of UrlUtils.contructLink accepts a URL as the basis for the returned URL. If you require an HTML link, then you can use UrlUtils.constructHTMLLink to produce a complete anchor element.

The following example portlet, ThesaurusLink.jsp, uses the parameter q to identify the word for which to search the thesaurus. It then creates links on the found, related words that the user may follow to get the thesaurus to operate on that new word. To see the initial submission form that sets the value of q, see the example in Section 60.3.4.4, "Building Forms with the Portlet URL Types."

<%
    String paramNameQ = "q";
    String qualParamNameQ = 
    HttpPortletRendererUtil.portletParameter(paramNameQ);
    PortletRenderRequest pRequest = (PortletRenderRequest)
        request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    String paramValueQ = pRequest.getQualifiedParameter(paramNameQ);
%>
<!-- Output the HTML content -->
<center>
    Words similar to <%= paramValueQ %>
    <br>
    Click the link to search for words related to that word.
    <br>
    <ul>
<%
        String[] relatedWords = Thesaurus.getRelatedWords(paramValueQ);
        NameValue[] linkParams = new NameValue[1]; 
        for (int i=0; i<=relatedWords.length; i++)
        {
            linkParams[0] = new NameValue(
                qualParamNameQ, relatedWords[i]);
%>
            <li>
            <b> <%= relatedWords[i] %> </b>
            <%= UrlUtils.constructHTMLLink(
                pRequest,
                UrlUtils.PAGE_LINK,
                "(words related to " + relatedWords[i] + ")",
                "",
                linkParams,
                true,
                true)%>
           </li>
<%
        }
%>
   </ul>
</center>

60.3.4.4 Building Forms with the Portlet URL Types

The use of portlet parameters in forms is similar to their use in links. The following two fundamental rules continue to apply:

  • Qualify the portlet's parameter names.

  • Do not manipulate or remove the other parameters on the incoming URL.

In terms of markup and behavior, forms and links differ quite considerably. However, just as with links, PDK-Java contains utilities for complying with these two basic rules.

A parameter name is just a string, whether it is a link on a page or the name of a form element. Therefore, the code for properly qualifying the portlet's parameter name is the same as that described in Section 60.3.4.3, "Building Links with the Portlet URL Types."

Forms differ from links in the way you ensure that the other parameters in the URL remain untouched. Once you open the form in the markup, you can make use of the following APIs:

UrlUtils.htmlFormHiddenFields(pRequest,UrlUtils.PAGE_LINK, formName);
UrlUtils.htmlFormHiddenFields(someURL);

where formName = UrlUtils.htmlFormName(pRequest,null).

Note:

Just as parameters in URLs and element names in forms require qualification to avoid clashing with other portlets on the page, form names must be fully qualified because any given page might have several forms on it.

The htmlFormHiddenFields utility writes HTML hidden form elements into the form, one form element for each parameter on the specified URL that is not owned by the portlet.

<INPUT TYPE="hidden" name="paramName" value="paramValue">

Thus, you need only to add their portlet's parameters to the form.

The other item of which you should be aware is how to derive the submission target of your form. In most cases, the submission target is the current page:

formTarget = UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK)

The value of formTarget can be the action attribute in an HTML form or the target attribute in a SimpleForm. Even though the method name includes HTML, it actually just returns a URL and thus you can use it in mobile portlets, too.

The following example form renders the thesaurus portlet's submission form. For the portlet that results from the submission of this form, see the example in Section 60.3.4.3, "Building Links with the Portlet URL Types."

<%
    String paramNameSubmit = "submit";
    String paramNameQ = "q";
    String qualParamNameQ =
        HttpPortletRendererUtil.portletParameter(paramNameQ);
    String qualParamNameSubmit = 
    HttpPortletRendererUtil.portletParameter(paramNameSubmit);
    PortletRenderRequest pRequest = (PortletRenderRequest)
        request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    String formName = UrlUtils.htmlFormName(pRequest,"query_form");
%>
<!-- Output the HTML content -->
<center>
    <b>Thesaurus</b>
    Enter the word you want to search for
    <form name="<%= formName %>" method="POST" 
        action="<%= UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK) %>"> 
        <%= UrlUtils.htmlFormHiddenFields(pRequest,UrlUtils.PAGE_LINK, formName)%> 
        <table><tr><td>
            Word of interest:
        </td><td>
            <input
                type="text"
                size="20"
                name="<%= qualParamNameQ %>"
                value="">
        </td></tr></table>
        <input type=submit name="<%= qualParamNameSubmit %>" Value="Search">
    </form>
</center>

60.3.4.5 Implementing Navigation within a Portlet

You can implement navigation within a portlet in one of three ways:

  • Pass navigation information in rendered URLs using private portlet parameters. Branching logic within the portlet code then determines which section of the portlet to render based on the URL. This option represents a small extension to the thesaurus example presented in Section 60.3.4.3, "Building Links with the Portlet URL Types" and Section 60.3.4.4, "Building Forms with the Portlet URL Types." Basically, instead of performing thesaurus search operations using the value of parameter q, the portlet branches based on the parameter value and renders different content accordingly.

  • Pass navigation information as described in the previous item but use PDK-Java to interpret the parameter and thus branch on its value. This option requires some further changes to the thesaurus example and is more fully explained later in this section.

  • Use session storage to record the portlet state and private parameters to represent actions rather than explicit navigation. This method provides the only way that you can restore the portlet to its previous state when the user navigates off the page containing the portlet. Once the user leaves the page, all private portlet parameters are lost and you can only restore the state from session storage, assuming you previously stored it there. This option requires that you understand and implement session storage. For more information about implementing session storage, see Section 60.3.6, "How to Access Session Information."

The following portlet code comes from the multi-page example in the sample producer of PDK-Java:

<portlet>
    <id>11</id> 
    <name>Multipage</name> 
    <title>MultiPage Sample</title> 
    <shortTitle>MultiPage</shortTitle> 
    <description>
        This portlet depicts switching between two screens all 
        in an application page.
    </description> 
    <timeout>40</timeout> 
    <timeoutMessage>MultiPage Sample timed out</timeoutMessage> 
    <renderer class="oracle.portal.provider.v2.render.RenderManager">
        <contentType>text/html</contentType> 
        <showPage>/htdocs/multipage/first.jsp</showPage> 
        <pageParameterName>next_page</pageParameterName> 
    </renderer>
</portlet>

Note:

The value of pageParameterName is the name of a portlet parameter, next_page, that the PDK-Java framework intercepts and interprets as an override to the value of the showPage parameter. If the PDK-Java framework encounters the qualified version of the parameter when the multipage portlet is requested, then it renders the resource identified by next_page rather than first.jsp. PDK-Java does not render the parameter within the portlet, that responsibility falls to the portlet.

You can modify the thesaurus example to operate with the use of this parameter. Specifically, you can use the form submission portlet to be the input for the thesaurus (the first page of the portlet), then navigate the user to the results page, which contains links to drill further into the thesaurus. The following examples illustrate these changes.

Note:

The example that follows is most useful for relatively simple cases, such as this thesaurus example. If your requirements are more complex (for example, you want to build a wizard experience), then you should consider using an MVC framework such as Struts. For information about how to build portlets from struts applications, see Section 60.6, "Creating a Struts Portlet."

ThesaurusForm.jsp:

<%
    PortletRenderRequest pRequest = (PortletRenderRequest)
        request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    String paramNameSubmit = "submit";
    String paramNameQ = "q";
    String qualParamNameQ =
        HttpPortletRendererUtil.portletParameter(pRequest, paramNameQ);
    String qualParamNameSubmit = 
    HttpPortletRendererUtil.portletParameter(pRequest, paramNameSubmit);
    String formName = UrlUtils.htmlFormName(pRequest,"query_form");
%>
<!-- Output the HTML content -->
<center>
    <b>Thesaurus</b>
    Enter the word you want to search for
    <form name="<%= formName %>" method="POST" 
        action="<%= UrlUtils.htmlFormActionLink(pRequest,UrlUtils.PAGE_LINK) %>"> 
        <%= UrlUtils.htmlFormHiddenFields(pRequest,UrlUtils.PAGE_LINK, formName)
%> 
        <%= UrlUtils.emitHiddenField(
                HttpPortletRendererUtil.portletParameter(request, "next_page"),
                "htdocs/path/ThesaurusLink.jsp" ) %>
        <table><tr><td>
            Word of interest:
        </td><td>
            <input
                type="text"
                size="20"
                name="<%= qualParamNameQ %>"
                value="">
        </td></tr></table>
        <input type=submit name="<%= qualParamNameSubmit %>" Value="Search">
    </form>
</center>

Notice how next_page must be explicitly set to point to ThesaurusLink.jsp. If you do not explicitly set next_page in this way, then it defaults to the resource registered in provider.xml, which is ThesaurusForm.jsp.

ThesaurusLink.jsp:

<%
    PortletRenderRequest pRequest = (PortletRenderRequest)
        request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    String paramNameQ = "q";
    String paramNameNextPage = "next_page";
    String qualParamNameQ = 
    HttpPortletRendererUtil.portletParameter(pRequest, paramNameQ);
    String qualParamNameNextPage = 
        HttpPortletRendererUtil.portletParameter(pRequest, paramNameNextPage);
    String paramValueQ = pRequest.getQualifiedParameter(paramNameQ);
%>
<!-- Output the HTML content -->
<center>
    Words similar to <%= paramValueQ %>
    <br>
    Click the link to search for words related to that word.
    <br>
    <ul>
<%
        Thesaurus t = new Thesaurus();
        String[] relatedWords = t.getRelatedWords(paramValueQ);
        NameValue[] linkParams = new NameValue[2]; 
        linkParams[0] = new NameValue(
            qualParamNameNextPage, "htdocs/path/ThesaurusLink.jsp");
        for (int i=0; i<relatedWords.length; i++)
        {
            linkParams[1] = new NameValue(
                qualParamNameQ, relatedWords[i]);
%>
            <li>
            <b> <%= relatedWords[i] %> </b>
            <%= UrlUtils.constructHTMLLink(
                pRequest,
                UrlUtils.PAGE_LINK,
                "(words related to " + relatedWords[i] + ")",
                "",
                linkParams,
                true,
                true)%>
           </li>
<%
        }
%>
   </ul>
   <a href="<%=XMLUtil.escapeXMLAttribute
               (pRequest.getRenderContext().getPageURL())%>">
      Reset Portlet
   </a>
</center>

60.3.4.6 Restricting Navigation to Resources

One limitation of implementing navigation with private parameters is that users could potentially navigate to portlet resources that you prefer to restrict. To control navigation to restricted resources, you can create a whitelist of acceptable resources to which a user may navigate. If you do not construct a whitelist to restrict navigation, then your portlet's resources are accessible according to the following default rules:

  • Any path immediately beneath the servlet root context is navigable. For example, /index.jsp is accessible but /WEB-INF/web.xml is not.

  • Any path under the htdocs directory is navigable. For example, both /htdocs/multipage/first.jsp and /htdocs/lottery/lotto.jsp are accessible.

To change this default behavior, you can add allowable path values to the provider definition file, provider.xml. For example, suppose you have a portlet where a JSP is used as a controller to forward requests to other pages depending on the pageParameterName private parameter. The XML excerpt in Example 60-4 allows resources under /htdocs/multiportlet to be shown. All other resources are restricted.

Example 60-4 Whitelist Excerpt from the provider.xml File

<portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
   <id>1</id>
   <name>Multipage</name>
   <title>A MultiPage Portlet</title>
   ...
   <renderer class="oracle.portal.provider.v2.render.RenderManager">
          <contentType>text/html</contentType>
          <showPage>/htdocs/multiportlet/controller.jsp</showPage>
          <pageParameterName>show_page</pageParameterName>
          <allowedPath>/htdocs/multiportlet/*</allowedPath>
   </renderer>
</portlet>

The pattern matching rules for this feature are similar to URL pattern matching in web.xml files. The rules are as follows:

  • To match the defined patterns, the resource path must exactly match unless wildcards are used.

  • The first wildcard is for path matching and consists of a string beginning with / and ending with /*. Any resource whose path starts with this string is matched. For an <allowedPath> value of /htdocs/sub1/*, valid values of the private parameter include /htdocs/sub1/file.jsp and /htdocs/sub1/sub2/file2.jsp.

  • The second wildcard is for file type matching and consists of a string starting with *. and ending with a file extension. Valid values for the page parameter end with that file extension. For an <allowedPathvalue> of *.jsp, valid values of the private parameter include /htdocs/sub1/file.jsp and /htdocs/sub1/file2.jsp.

60.3.5 How to Use JNDI Variables

When writing Java portlets, you may set deployment-specific properties through the JNDI service such that their values may be retrieved from your producer code. In this way, you can specify any property in a producer deployment and then easily access it anywhere in your producer code.

You can use JNDI variables to change producer property values after the producer has been deployed. The environment entry must be declared in web.xml. It can then be updated on deployment using a deployment plan.

PDK-Java provides utilities to enable the retrieval of both producer and non-producer JNDI variables within a Java EE container.

This section includes the following subsections:

60.3.5.1 Declaring JNDI Variables

You declare JNDI variables in the web.xml file for your producer. The format for declaring a JNDI variable is as follows:

<env-entry>
    <env-entry-name>variableName</env-entry-name>
    <env-entry-type>variableType</env-entry-type>
    <env-entry-value>variableValue</env-entry-value> 
</env-entry>

The env-entry-name element contains the name by which you want identify the variable. env-entry-type contains the fully qualified Java type of the variable. env-entry-value contains the variable's default value.

This section includes the following subsections:

60.3.5.1.1 Variable Types

In the env-entry-type element, you must supply the fully qualified Java type of the variable, which is expected by your Java code. The Java types you may use in your JNDI variables are as follows:

  • java.lang.Boolean

  • java.lang.String

  • java.lang.Integer

  • java.lang.Double

  • java.lang.Float

The Java EE container uses these type declarations to automatically construct an object of the specified type and gives it the specified value when you retrieve that variable in your code.

60.3.5.1.2 Variable Naming Conventions

The PDK-Java defines environment variables that can be set at the individual producer service level or at the web application level. To avoid naming conflicts between different producer services or different application components packaged in the same web application, Oracle recommends you devise some naming convention.

Note:

If you use the EnvLookup method, then you must use oracle/portal/provider/service/property. You cannot substitute your own company name or component in this case.

For example:

  • Producer service-specific names should be of the form:

    company/component name/producer name/variable name
    
  • Shared names must be of the form:

    company/component name/producer name/global
    

where:

  • company is the name of the company owning the application.

  • component name is the name of the application or component with which the producer is associated.

  • producer name is the service name of the producer.

  • variable name is the name of the variable itself.

As you can see, these naming conventions are similar to those used for Java packages. This approach minimizes the chance of name collisions between applications or application components. PDK-Java provides utilities that enable you to retrieve variables in this form without hard coding the service name of the producer into your servlets or JSPs. The service name need only be defined in the producer's WAR file. For more information about retrieving JNDI variables, see Section 60.3.5.3, "Retrieving JNDI Variables."

60.3.5.1.3 Examples

The following examples illustrate producer variable names:

oracle/portal/myProvider/myDeploymentProperty
oracle/portal/myprovider/myProperties/myProperty

The following example illustrates non-producer variable names:

oracle/portal/myOtherProperty

60.3.5.2 Setting JNDI Variable Values

In your producer deployment, you may want to set a new value for some or all of your JNDI variables. You can perform this task by setting the values manually within a WLS deployment plan. Deployment plans can be created for the producer deployment through the WLS console.

To set variable values manually within a deployment plan:

  1. Go to the producer deployment with the WLS console and create a new deployment plan if one does not exist.

  2. Edit the deployment plan XML file. For each deployment property you want to set, add the following variable definition directly under the <deployment-plan> tag:

    <variable-definition>
      <variable>
        <name>jndi_var_def</name>
        <value>false</value>
      </variable>
    </variable-definition>
    
  3. To tie this variable definition to the actual JNDI variable, add the following for each property under the WEB-INF/web.xml module descriptor (oracle/portal/sample/rootDirectory is used as an example):

    <module-descriptor external="false">
      <root-element>web-app</root-element>
      <uri>WEB-INF/web.xml</uri>
      <variable-assignment>
        <name>jndi_var_def</name>
        <xpath>/web-app/env-entry/[env-entry-name="oracle/portal/sample/rootDirectory"]/env-entry-value</xpath>
       </variable-assignment>
    </module-descriptor>
    
  4. Save and close the file.

  5. Select Update on the producer deployment to apply the deployment plan for the new settings to take effect.

60.3.5.3 Retrieving JNDI Variables

JNDI is a standard Java EE technology. As such, you can access JNDI variables through Java EE APIs. For example:

String myVarName = "oracle/portal/myProvider/myVar"
String myVar = null;
try 
{
   InitialContext ic = new InitialContext();
   myVar = (String)ic.lookup("java:env/" + myVarName);
}
catch(NamingException ne)
{
   exception handling logic
}

In addition to the basic Java EE APIs, PDK-Java includes a simple utility class for retrieving the values of variables defined and used by the PDK itself. These variables conform to the naming convention described in Section 60.3.5.1.2, "Variable Naming Conventions" and are of the form:

oracle/portal/provider_service_name/variable_name
oracle/portal/variable_name

To use these APIs, you need only provide the provider_service_name and the variable_name. The utilities construct the full JNDI variable name, based on the information you provide, and look up the variable using code similar to that shown earlier and return the value of the variable.

The EnvLookup class (oracle.portal.utils.EnvLookup) provides two lookup() methods. One retrieves producer variables and the other retrieves non-producer variables. Both methods return a java.lang.Object, which can be cast to the Java type you are expecting.

The following code example illustrates the retrieval of a producer variable:

EnvLookup el = new EnvLookup();
String s = (String)el.lookup(myProviderName, myVariableName);

myProviderName represents the service name for your producer, which makes up part of the variable name. myVariableName represents the portion of the variable name that comes after the producer's service name. The example assumes the variable being retrieved is of type java.lang.String.

To retrieve a non-producer variable, you use the same code, you pass only one parameter, the variable name, to the lookup(), again excluding the oracle/portal prefix.

EnvLookup el = new EnvLookup();Object o = el.lookup(myVariableName);

Table 60-1 shows the JNDI variables provided by default with PDK-Java. If you do not declare these variables, then PDK-Java looks for their values in their original locations (web.xml and the deployment properties file).

Table 60-1 PDK-Java JNDI Variables

Variable Description
oracle/portal/provider/provider_name/autoReload

Boolean auto reload flag. Defaults to true.

oracle/portal/provider/provider_name/definition

Location of producer's definition file.

oracle/portal/provider/global/log/logLevel

Log setting (0 through 8). 0 being no logging and 8 the most possible logging.

oracle/portal/provider/provider_name/maxTimeDifference

Producer's HMAC time difference.

oracle/portal/provider/<service_name>/resourceUrlKey

Authentication key for resource proxying through the Parallel Page Engine.

oracle/portal/provider/provider_name/rootDirectory

Location for producer personalizations. No default value.

oracle/portal/provider/provider_name/sharedKey

HMAC shared key. No default value.

oracle/portal/provider/provider_name/showTestPage

(non-producer) A Boolean flag that determines if a producer's test page is accessible. Defaults to true.

oracle/portal/provider/global/transportEnabled

A Boolean flag that determines whether Edit Defaults personalizations may be exported and imported.


60.3.6 How to Access Session Information

When a user accesses a page, it initiates a public, unauthenticated session and tracks information about the session across requests. If the user logs in, then this session becomes an authenticated session of the logged-in user. This session terminates when any of the following occur:

  • The browser session terminates (that is, the user closes all the browser windows).

  • The user explicitly logs out.

  • The session times out because the user's idle time exceeds the configured limit.

As part of the metadata generation, all of the producers that contribute portlets to the page are contacted, if they specified during registration that they be called for some special processing. This call allows producers to do processing based on the user session, log the user in the producer's application if needed, and establish producer sessions. For producers, this call is referred to as initSession. As most web-enabled applications track sessions using cookies, this API call enables the producer of the application to return cookies.

You can use the session store to save and retrieve information that persists during the portal session. This information is only available, and useful, to you during the life of the session. You should store only temporary information in the session store. Application developers may use the session store to save information related to the current user session. Data in the session store can be shared across portlets.

If the information you want to store must persist across sessions, then you may want to store it in the preference store instead. Some common applications of the session store are as follows:

  • To cache data that is expensive to load or calculate (for example, search results).

  • To cache the current state of a portlet (for example, the current range, or page, of search results displayed in the portlet, or sequence of events performed by user).

Before you implement session storage, you should carefully consider the performance costs. Because portlets and producers are remote, it can be a relatively expensive operation to create and maintain even a small amount of information in the session store. For this reason, you may want to avoid altogether any session storage for public pages that are accessed frequently by many users.

Furthermore, while using the session store with producers, you create a stateful application that tracks state information in memory. Similarly, you create a stateful application if you use the file-system implementation of preference store.

If scalability is an important concern for you, then a stateful application may cause you problems. Stateful applications can affect the load-balancing and failover mechanism for your configuration. Even though you may deploy multiple middle-tiers, you must implement sticky routing (where the same node handles subsequent requests in the same session) to track state. Sticky routing may result in lopsided load-balancing or loss of session data in case a node crashes, affecting failover. This issue is one reason why many developers prefer to build stateless applications. However, if scalability is not a concern, then a stateful application should present no problems for you.

The PDK Framework represents the session with a ProviderSession object, which is established during the call to the Provider Instance's initSession method. This object is associated with the ProviderUser. To make data persistent between requests, you must write data into the session object using the setAttribute method on the ProviderSession object. This method maps a java.lang.Object to a java.lang.String and stores that mapping inside the session object. The String can then be used to retrieve the Object during a subsequent request, provided the session is still valid.

A producer session may become invalid for the following reasons:

  • The session times out.

  • The invalidate method on ProviderSession is called.

  • The JVM process running the servlet container is terminated.

All portlets contained by the same ProviderInstance share the same session for a particular ProviderUser. Therefore, data unique to a particular portlet instance must be mapped to a unique String in the session. This is accomplished using the portletParameter method in the PortletRendererUtil class. This method makes a supplied String parameter or attribute name unique to a PortletInstance, by prefixing it with a generated identifier for that instance. You can use the returned instance-specific name to write portlet instance data into the session.

For more detailed information about the PDK Framework classes, see the JavaDoc in the Oracle Fusion Middleware Java API Reference for Oracle PDK-Java at:

http://docs.oracle.com/cd/E23943_01/apirefs.1111/e10691/index.html?overview-summary.html

In the example in this section, session storage is used to count the number of times your portlet has rendered in Shared Screen mode.

To implement session storage:

  • Import ProviderSession, PortletRendererUtil, and HttpPortletRendererUtil.

  • Retrieve the producer session.

  • Read and write the session by accessing it from within your Java portlet.

  • Set the session to true in provider.xml.

  • Register the producer for session storage and set the Login Frequency.

The steps that follow describe how to add a session count to your portlet that displays how many times the portlet has been rendered for the current session.

  1. After using the wizard to create a portlet, you can edit the JSP for the Show page in Oracle JDeveloper. You must import the following classes:

    <%@page contentType="text/html; charset=windows-1252"
    import="oracle.portal.provider.v2.render.PortletRenderRequest"
    import="oracle.portal.provider.v2.http.HttpCommonConstants"
    import="oracle.portal.provider.v2.ProviderSession"
    import="oracle.portal.provider.v2.render.PortletRendererUtil"
    import="oracle.portal.provider.v2.render.http.HttpPortletRendererUtil"
    %>
    
  2. Insert code that checks for a valid session first and then increments the count and displays it. If the session is valid and a previously stored value exists, then you display the value, increment the count, and store the new value. If the session is valid but no previously stored value exists, then you initialize a new count starting with 1, and display and store the value. You also want to obtain the unique string key for this portlet and then use an it in an array to count the session. If no session information was received, then you want to provide information to the user indicating they may need to log in again.

    <%
    PortletRenderRequest pReq = (PortletRenderRequest)
    request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    ProviderSession pSession = pReq.getSession();
      if (pSession != null)
      {
        String key = PortletRendererUtil.portletParameter(pReq, "count");
        Integer i = (Integer)pSession.getAttribute(key);
        if (i == null)
        {
          i = new Integer(0);
        }
        i = new Integer(i.intValue()+1);
        pSession.setAttribute(key, i);
    %>
    
    <p>Render count in this session: <%=i%> </p>
    
    <% 
      } 
      else 
      {
    %>
    
    <p>The session has become invalid</p>
    <br>
    Please log out and log in again.
    <%
      } 
    %>
    
  3. By default, the wizard does not set session to true in provider.xml. You must update this flag in order for the producer to receive session information from the portal. You should only set this tag to true if you are using session information in your producer or portlets. By setting this flag to true, extra load is added to the producer calls.

    <provider class="oracle.portal.provider.v2.DefaultProviderDefinition">
    <session>true</session>
    
  4. Register your producer with session support. For a reminder on how to register your portlet, see Section 62.3, "Registering an Oracle PDK-Java Portlet Producer with a WebCenter Portal: Framework Application."

  5. If you have not added your Java portlet to a page, then do so now. Ensure that you perform the following tasks:

    • Refresh the producer to accept the new changes.

    • Re-login in case your session is no longer valid.

60.3.7 How to Enhance PDK-Java Portlet Performance with Caching

When you have completed the basic functionality of your portlet, you may want to turn your attention to portlet performance.

Caching is a common technique for enhancing the performance of web sites that include a great deal of dynamic content. JSR 286 portlets support expiry-based and validation-based caching.

For more information about caching, see Section 57.4.4, "Portlet Performance."

This section includes the following subsections:

60.3.7.1 Activating Caching for PDK-Java Portlets

To use the caching features in your producers, you must first activate the middle tier cache. This cache is known as the PL/SQL Cache because it is the same cache used by mod_plsql, the Oracle HTTP Server plug-in that calls database procedures, and hence database producers, over HTTP.

Usually, your administrator is responsible for the configuration details of caching.

60.3.7.2 Implementing Expiry-Based Caching in PDK-Java Portlets

Expiry-based caching is a simple caching scheme to implement, and can be activated declaratively in your XML producer definition. You can set an expiry time for the output of any ManagedRenderer you use by setting its pageExpires property to the number of minutes you want the output to be cached for.

To add expiry-based caching:

  1. After you have used the Create Oracle PDK-Java Portlet wizard to build a portlet as described in Section 60.2.1, "How to Create a PDK-Java Portlet," edit the provider.xml file and set the pageExpires property tag of showPage to the required value. For example, to cache portlet output for 1 minute, set pageExpires to 1.

    By default the wizard generates a standard and compressed tag for showPage. Expand the tag to include a subtag of pageExpires:

    <showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer">
       <resourcePath>/htdocs/mycacheportlet/MyCachePortletShowPage.jsp
          </resourcePath>
       <pageExpires>1</pageExpires>
    </showPage>
    
  2. Test that the portlet is cached for 1 minute by adding some JSP code to your show page. You can simply add the current time to your JSP.

    <%@page contentType="text/html; charset=windows-1252"
       import="oracle.portal.provider.v2.render.PortletRenderRequest"
       import="oracle.portal.provider.v2.http.HttpCommonConstants"
       import="java.util.Date"
       import="java.text.DateFormat"
    %>
    
    <%
     PortletRenderRequest pReq = (PortletRenderRequest)
       request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
     DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,
       DateFormat.LONG,pReq.getLocale());
     String time = df.format(new Date());
    %>
    
    <P>Hello <%=pReq.getUser().getName() %>.</P>
    <P>This is the <b><i>Edit</i></b> render mode!</P>
    <P>This information is correct as of <%=time%>.</P>
    

    When viewing the portlet, you see that the time (including seconds) is constant for one minute. After the time has expired, the portlet displays the most current time and a new cache is set.

60.3.7.3 Implementing Validation-Based Caching in PDK-Java Portlets

Adding validation-based caching requires slightly more effort, but gives you explicit control over exactly which requests to your producer are cache hits. As an example, you may want to update the cache only when data within the portlet has changed. To implement this algorithm, you must override the prepareResponse method. The signature of the BaseManagedRenderer.prepareResponse method is:

public boolean prepareResponse(PortletRenderRequest pr)
                        throws PortletException,
                               PortletNotFoundException

In your version of prepareResponse(), do the following:

  • Retrieve the cached version identifier set by the consumer in the render request by calling the HttpPortletRendererUtil.getCachedVersion() method:

    public static java.lang.String getCachedVersion
        (PortletRenderRequest request)
    
  • If the portlet finds the previously cached version valid, then the appropriate header must be set by calling the HttpPortletRendererUtil.useCachedVersion() method. It also instructs the RenderManager that it is not necessary to call renderBody() to render the portlet body.

    public static void useCachedVersion(PortletRenderRequest request)
    

    Otherwise, use HttpPortletRendererUtil.setCachedVersion() to generate a new version of the portlet, which is cached. It also indicates to the consumer that the renderBody() method has to be called to regenerate the portlet content.

    public static void setCachedVersion(PortletRenderRequest request,
                                        java.lang.String version,
                                        int level)
                                 throws java.lang.IllegalArgumentException
    

For validation-based caching, you need not update provider.xml. You can view the portlet by refreshing the page or adding the portlet to a page and updating the content. If the content has changed, then the portlet shows the new content. If the content has not changed, then a cached version of the portlet is displayed.

60.3.8 How to Manage the Persistence Store for PDK-Java Portlets

The portlet persistence store is used for persisting consumer registration handles and portlet preference data. PDK-Java portlet producers can use one of two types of persistence store: File or Database. The database used for the persistence store must be JDBC-compatible.

For more information, see Section 57.4.3, "Portlet Personalization and Customization."

This section includes the following subsections:

60.3.8.1 Setting up a Persistence Store for a PDK-Java Producer

The type of persistence store used for PDK-Java producers is determined by the preferenceStore tag in the provider.xml file.

Table 60-2 lists and describes the attributes and parameters used with the preferenceStore tag.

Table 60-2 Attributes and Parameters of the preferenceStore Tag

Attribute/Parameter Description

class

This required attribute specifies the Java class that defines the location and other details of portlet preferences. For example, a file-based persistence store might use:

<preferenceStore class="oracle.portal.provider.v2.preference.FilePreferenceStore">

A database persistence store might use:

<preferenceStore class="oracle.portal.provider.v2.preference.DBPreferenceStore">

OmniPortlet uses its own class, for example:

<preferenceStore class="oracle.webdb.reformlet.ReformletFilePreferenceStore">

name

This required parameter provides a name for the persistence store. Use any value you choose. For example:

<preferenceStore class="oracle.portal.provider.v2.preference.DBPreferenceStore">
  <name>MyPDKProducerPreferenceStore</name>
</preferenceStore>

connection

This required parameter for a database persistence store points to a JNDI connection that connects with a schema containing the portlet persistence store. For example:

<preferenceStore class="oracle.portal.provider.v2.preference.FCFDBPreferenceStore">
  <name>MyPDKProducerPreferenceStore</name>
  <connection>java:comp/env/jdbc/portletPrefs</connection>
</preferenceStore>

rootDirectory

This optional parameter specifies the location where the file-based persistence store preferences are stored.When this parameter is not included with the preferenceStore tag, the default file-based persistence store location is used. This is the same folder where the producer's provider definition file is stored.

useHashing

This optional parameter is used when specifying a file based persistence store, and accepts the value true or false. When it is set to true, each preference data file is stored in an extra subdirectory with a name determined by hashing the data file name. Using this parameter can improve file system performance by limiting the number of preference data files stored in a single directory.

For example:

<preferenceStore class="oracle.portal.provider.v2.preference.FilePreferenceStore">
  <name>PDKProducerPreferenceStore</name>
  <useHashing>true</useHashing>
</preferenceStore>

60.3.8.2 Migrating a PDK-Java Producer Persistence Store

PDK-Java has two PreferenceStore implementations, DBPreferenceStore and FilePreferenceStore. DBPreferenceStore persists data using a JDBC-compatible relational database and FilePreferenceStore persists data using the file system.

If you have installed Oracle PDK-Java, then you can manage the information stored in the persistence store by using the Preference Store Migration and Upgrade Utility, which is included in the pdkjava.jar file. Note that you must run this tool from WC_ORACLE_HOME.

Note:

You must set the classpath when running this tool to include pdkjava.jar, ptlshare.jar, and ojdbc6.jar. For example:

java -classpath WC_ORACLE_HOME\jdeveloper\modules\oracle.dms_11.1.1\dms.jar;
WC_ORACLE_HOME\wlserver_10.3\server\lib\ojdbc6.jar;WC_ORACLE_HOME\jdeveloper\webcenter\modules\oracle.portlet.server_11.1.1\pdkjava.jar;
WC_ORACLE_HOME\jdeveloper\webcenter\modules\oracle.portlet.server_11.1.1\ptlshare.jar
oracle.portal.provider.v2.preference.MigrationTool

The syntax of the migration utility is:

java oracle.portal.provider.v2.preference.MigrationTool
  -mode [file | db | filetodb | filetofile | dbtofile | dbtodb]
  [-remap language | locale]
  [-countries iso_country_code]
  [-pref1UseHashing true | false]
  [-pref1Driver driver]
  {-pref1RootDirectory directory |
   -pref1User username -pref1Password password -pref1URL url}
  [-pref2UseHashing true | false]
  [-pref2Driver driver]
  {-pref2RootDirectory directory |
   -pref2User username -pref2Password password -pref2URL url}
  [-upfixwpi filename]

where

  • -mode is the mode in which you want to run the Preference Store Migration and Upgrade Utility

    filetodb, filetofile, dbtofile, or dbtodb indicates to run in migration mode. See Section 60.3.8.2.1, "Migration Mode" for more information about this mode.

    file or db indicates to run in upgrade mode. See Section 60.3.8.2.2, "Upgrade Mode" for more information about this mode.

  • -remap is the localePersonalizationLevel (language or locale). Note that you only must use this option to change localePersonalizationLevel as part of your upgrade or migration.

  • -countries specifies a prioritized list of ISO country codes, indicating your order of preference in a collision between remapped preferences for different countries. -countries is only meaningful if you also specified the -remap option.

  • -pref1UseHashing specifies whether you want to employ hashing on the source for this operation.

  • -pref1Driver is the driver for the source database. If you do not specify this parameter, the nearest matched driver is used.

  • -pref1RootDirectory is the path of a source file system, for example, j2ee/home/applications/jpdk/jpdk/WEB-INF/providers/sample.

  • -pref1User is the user name for a source database.

  • -pref1Password is the password for a source database.

  • -pref1URL is the URL to a source database, for example, jdbc:oracle:thin:@myserver.mydomain.com:1521:mysid.

  • -pref2UseHashing specifies whether you want to employ hashing on the destination for this operation.

  • -pref2Driver is the driver for the destination database. If you do not specify this parameter, the nearest matched driver is used.

  • -pref2RootDirectory is the path of a destination file system, for example, j2ee/home/applications/jpdk/jpdk/WEB-INF/providers/sample.

  • -pref2User is the user name for a destination database.

  • -pref2Password is the password for a destination database.

  • -pref2URL is the URL to a destination database, for example, jdbc:oracle:thin:@myserver.mydomain.com:1521:mysid.

  • -upfixwpi indicates a log file for the operation.

This section includes the following subsections:

60.3.8.2.1 Migration Mode

Use a migration mode to copy data from a source persistence store to a target persistence store. When the utility is run in this mode, the persistence stores for all the portlet definitions are updated.

Table 60-3 describes the migration modes in which you can run the utility.

Table 60-3 Migration Modes in Which to Run the Utility

Mode Description

filetodb

Use when data must be copied from a FilePreferenceStore to a DBPreferenceStore.

filetofile

Use when data must be copied from one FilePreferenceStore to another FilePreferenceStore that is in a different location.

dbtofile

Use when data must be copied from a DBPreferenceStore to a FilePreferenceStore.

dbtodb

Use when data must be copied from one DBPreferenceStore to another DBPreferenceStore that is based on a different database table.


If the destination for the operation is a database, you must ensure that the destination WebLogic Server is created using the WebCenter Portal portlet template and the appropriate schemas have been created using the RCU. For more information, see Oracle Fusion Middleware Installation Guide for Oracle WebCenter Portal.

When using a migration mode, you can also use the -remap and -countries options to specify that the data must be upgraded while being migrated. Specifically, you use these options to ensure that the locale-specific preferences are appropriately remapped.

You can use the other options accepted by the utility to specify the properties of the persistence stores involved in the upgrade or migration process. These options must correspond to the tags you specify in provider.xml to describe the persistence stores.

Properties beginning with the prefix -pref1 correspond to properties of the source persistence store (in an upgrade mode, this is the only persistence store). For example, specifying -pref1UseHashing true -pref1RootDirectory j2ee/home/applications/jpdk/jpdk/WEB-INF/providers/sample sets the useHashing and rootDirectory properties of a source FilePreferenceStore.

When a migration basic mode is selected, properties beginning with the prefix -pref2 correspond to properties of the target persistence store. For example, specifying -pref2User portlet_prefs -pref2Password portlet_prefs -pref2URL jdbc:oracle:thin:@myserver.mydomain.com:1521:mysid sets the database connection details on a target DBPreferenceStore.

Example 60-5 PDK-Java Migration Utility Command Line, Migration

java -classpath WC_ORACLE_HOME/webcenter/modules/oracle.portlet.server_11.1.1/pdkjava.jar:
WC_ORACLE_HOME/webcenter/modules/oracle.portlet.server_11.1.1/ptlshare.jar:WC_ORACLE_HOME/ucm/shared/classes/ojdbc14.jar \
oracle.portal.provider.v2.preference.MigrationTool \
-mode dbtofile \
-pref1User portlet_prefs \
-pref1Password portlet_prefs \
-pref1URL jdbc:oracle:thin:@myserver.mydomain.com:1521:mysid \
-pref2RootDirectory /mydirectory/preferences
60.3.8.2.2 Upgrade Mode

Use an upgrade mode to upgrade data in place, and to modify existing locale-specific preferences in the persistence store so that the naming format used is compatible with the current version of WebCenter Portal and a given localePersonalizationLevel setting.

Table 60-4 describes the upgrade modes in which you can run the utility.

Table 60-4 Upgrade Modes in Which to Run the Utility

Mode Description

file

Use when data in a FilePreferenceStore must be upgraded.

db

Use when data in a DBPreferenceStore must be upgraded.


An upgrade mode can be used in the following scenarios:

  • You have upgraded from Oracle PDK 9.0.4.0.0 or earlier and want to use existing portlets with the default localePersonalizationLevel setting of language (In earlier releases, the default setting was locale).

  • You have upgraded from Oracle Portal 9.0.2.0.0 or earlier and want to use existing portlets with a localePersonalizationLevel setting of locale (Oracle Portal now uses different names for some locales and therefore some existing data must be remapped).

  • You want to change the localePersonalizationLevel for an existing portlet from locale to language or vice-versa.

When using an upgrade mode, you must use the -remap option to specify the localePersonalizationLevel (language or locale) that you are upgrading to. You can also use the -countries option to specify a prioritized list of ISO country codes, indicating your order of preference in a collision between remapped preferences for different countries. For example, if you specify -remap language -countries GB,US in the command, then it means that if the utility comes across both US English and British English preferences (en_US and en_GB) in a given preference store, it remaps the British English preference to become the English-wide preference (en).

Example 60-6 PDK-Java Migration Utility Command Line, Upgrade

java -classpath WC_ORACLE_HOME/webcenter/modules/oracle.portlet.server_11.1.1/pdkjava.jar:
WC_ORACLE_HOME/webcenter/modules/oracle.portlet.server_11.1.1/ptlshare.jar:WC_ORACLE_HOME/ucm/shared/classes/ojdbc14.jar \
  oracle.portal.provider.v2.preference.MigrationTool \
 -mode file -remap language
 -countries GB,US -pref1UseHashing true 
 -pref1RootDirectory j2ee/home/applications/jpdk/jpdk/WEB-INF/providers/sample

60.3.9 How to Move a PDK-Java Portlet Producer

In some situations, you may want to move a portlet producer. For example, you may need to move it to a new server.

To move a PDK-Java portlet producer:

  1. Install the new producer.

  2. Make the persistence store of the original producer available to the new producer by performing one of the following tasks:

    • Migrate the persistence store using the Preference Store Migration and Upgrade Utilities (see Section 60.3.8.2, "Migrating a PDK-Java Producer Persistence Store" for more information), or

    • Configure the new producer to use the same persistence store as the original producer. If the database persistence store is being used, then you must point the WebLogic Server data source to the same database as the original producer.

  3. Update the URL of the producer registration by using Enterprise Manager Fusion Middleware Control or the WLST commands: setWSRPProducerRegistration or setPDKJavaProducerRegistration.

60.3.10 How to Export and Import PDK-Java Portlet Producers at Design Time

You can export and import portlet producers at design time. For more information, see Section 59.3.14, "How to Export and Import Portlet Producers at Design Time."

60.4 Testing PDK-Java Portlets

Before making your portlets available in a production environment, it is highly advisable to test them first to make sure that they behave as expected.

This section includes the following subsections:

60.4.1 How to Test PDK-Java Portlet Producer Applications on Integrated WebLogic Server

The Integrated WebLogic Server (Integrated WLS) provides a quick and easy way of testing your portlets because it is preconfigured so that you can run applications within JDeveloper without needing to create deployment profiles.

To test a PDK-Java portlet on Integrated WLS:

  1. In JDeveloper, open the portlet producer application that owns the portlet that you want to test.

  2. Expand the portlet project (for example, Portlets).

  3. Right-click a JSP page, for example, index.jsp in the project folder and select Run. Running index.jsp triggers packaging and deployment of your portlet producer application on an instance of Integrated WLS named after the application.

  4. Check the IntegratedWebLogicServer - Log window to monitor the deployment progress. The log shows the URL of the application test page, as shown in Figure 60-2. The format of the URL is http://host:port/application_name-Portlets-context-root/index.jsp.

    Figure 60-2 DefaultServer - Log

    Description of Figure 60-2 follows
    Description of "Figure 60-2 DefaultServer - Log"

  5. The PDK-Java Application Test page displays in a browser window, as shown in Figure 60-3.

    Figure 60-3 Portlet Producer Application Test Page

    Description of Figure 60-3 follows
    Description of "Figure 60-3 Portlet Producer Application Test Page"

  6. Click the link underneath Service Name. Your browser should open with a page similar to the one shown in Figure 60-4. The URL of this page is the one required to register the producer with another application.

    Figure 60-4 Producer Test Page

    Shows provider test page.
    Description of "Figure 60-4 Producer Test Page"

  7. Alternatively, you can construct the URL yourself as follows:

    http://host:port/context-root/providers/producer_name
    

    where:

    • host is the server to which your producer has been deployed.

    • port is the HTTP Listener port. Typically, it is 7101. When the server is started, the port is displayed in the console.

    • context-root is the Web Application's Context Root, which you specified earlier and can be found in the WAR Deployment Profile Properties under General.

    • producer_name is the name of the portlet's producer. A WAR file may contain multiple producers, hence you should always include the name of the producer for clarity. Otherwise, you get the default producer, which is the first producer created. The default producer is defined by the _default.properties file. This is created with the first producer in a project.

    If you enter this URL in your browser, you should see a page similar to the one in Figure 60-4.

  8. While the application is running, you can switch back and forth between JDeveloper and your browser to make changes at design time in your application, save the changes, and then refresh the test page in your browser.

  9. When the producer is successfully running, you should register it with an application and add one or more portlets to a page to check that it is working correctly. Registering a producer gives applications the information they require to locate and communicate with that producer. After you register a producer, it is exposed as a connection, and the producer and its portlets become available in the Application Resources panel under the Connections node, or in the Resource Palette.

    To register producers of PDK-Java portlets, follow the instructions provided in Section 62.3, "Registering an Oracle PDK-Java Portlet Producer with a WebCenter Portal: Framework Application."

    To add your portlets to a page, follow the instructions provided in Section 62.6, "Adding Portlets to a Page."

  10. To stop an Integrated WLS instance, in the Run Manager tab, select DefaultServer and click the red Stop icon. When the instance stops, the application is undeployed, and therefore, comes unavailable.

    Tip:

    You can also stop an Integrated WLS instance by clicking the red Stop icon in the IntegratedWebLogicServer - Log window and selecting DefaultServer.

60.4.2 What Happens When You Test PDK-Java Portlet Producer Applications on Integrated WebLogic Server

When you run PDK-Java portlets on Integrated WLS the following happens:

  • Configuration files for PDK-Java portlets are added to the WEB-INF directory.

  • The web.xml file is updated with listener and server classes, filters, parameters, and other configurations that are required to run the portlet producer application successfully.

    For example, the ResourceServlet pdkresource, the oracle.portlet.server.service.ContextFilter filter, and so on. These configurations vary depending upon the portlet requirements.

  • Libraries required for PDK-Java portlets are added to the weblogic.xml file, for example, oracle.portlet-producer.jpdk.

60.4.3 How to Deploy a PDK-Java Portlet Producer to the Integrated WebLogic Server

When you run a PDK-Java portlet producer application on the Integrated WLS instance, when the instance stops, the application is undeployed and therefore becomes unavailable. For a more persistent testing scenario, you can deploy your portlet producer application to the Integrated WLS so that it is always available while the Default Server is running.

If you choose this method, then you must first create deployment profiles, as described in Section 61.2, "Creating a WAR Deployment Profile." If you deploy your application to the Integrated WLS, then the Deployment Configuration dialog displays to enable you to configure and customize deployment settings. The file system MDS repository precreated by JDeveloper displays in the Repository Name field.

For information about deploying and running an application on the Integrated WLS, see Section 69.2, "Deploying a Framework Application to the Integrated WebLogic Server."

60.4.4 How to Test Portlet Personalization

If you have implemented personalization for your portlet, then the Personalize link only appears on the portlet for authenticated users. Hence, to test the personalization of a portlet (the Personalize link), you must have some form of security implemented for the application consuming the portlet. For testing purposes, you may prefer to just configure the most basic authentication possible. For more information, see Section 68.12, "Configuring Basic Authentication for Testing Portlet Personalization."

60.5 Deploying PDK-Java Portlets

You can deploy your portlet producer to any WebLogic Managed Server that is configured to support WebCenter Portal portlet producers. For a list of prerequisites that you must complete before deployment, see Section 61.1, "Introduction to Deploying Portlet Producers."

The first step of deploying a PDK-Java portlet producer is to create a WAR deployment profile to indicate how the producer and its associated files should be packaged. For more information, see Section 61.2, "Creating a WAR Deployment Profile."

You can deploy PDK-Java portlets only as EAR files, so after creating the WAR deployment profile, you must also create an EAR deployment profile to package the entire application. For more information, see Section 69.3.2.2, "Creating Deployment Profiles."

Note:

While creating the EAR deployment profile, ensure that the WAR file is included in the application's EAR file.

After you have created the EAR deployment profile, you can deploy your portlet producer to the managed server. For more information, see Section 61.3, "Deploying a Portlet Producer to a WebLogic Managed Server."

Note:

When deploying a PDK-Java portlet producer, you will not see the Select deployment type dialog, as the producer does not contain JSR 286 portlets.

When you deploy a PDK-Java portlet producer to a WebLogic Managed Server, the configuration settings described in Section 60.4.2, "What Happens When You Test PDK-Java Portlet Producer Applications on Integrated WebLogic Server" are added to the application EAR file at design time.

60.6 Creating a Struts Portlet

Oracle PDK contains extensions to integrate Apache Struts applications. This section explains how to build a portlet from an existing struts application. You can also follow these steps to create a portlet that uses the Model View Controller paradigm. The PDK-Java extensions described in this section rely on Apache Struts 1.1.

You can use the Struts framework to enhance portlet behavior. For example, a Struts controller may be used for page flow within a portlet. A portlet renderer is used as a bridge between portlet render requests and Struts servlet requests

The following code shows a portion of the producer definition file (provider.xml):

...
<renderContainer>true</renderContainer>
    <renderCustomize>true</renderCustomize>
    <autoRedirect>true</autoRedirect>
    <contentType>text/html</contentType>
    <showPage class="oracle.portal.provider.v2.render.http.StrutsRenderer">
        <defaultAction>showCustomer.do</defaultAction>
    </showPage>
</renderer>
...

The showPage of the Struts portlet contains two important components:

  • The renderer class (oracle.portal.provider.v2.render.http.StrutsRenderer) receives the render requests and forwards them to the Struts Action Servlet.

  • The defaultAction tag defines the Struts action that is used by default when the portlet is called for the first time.

The PDK-Java enables you to easily develop a view (portlet view) of your Struts application. This view enforces a consistent look and feel of your Struts portlet using portal styles, and enables the end user to use the application within the portal.

To create a Struts portlet, you must use the PDK-Java Struts tags, which are extensions of the default Struts JSP tags. This development process is similar to that of creating a standalone Struts application. For portlets in a producer application to use the Struts framework, the Struts components must be part of the same web application.

To publish a part of an existing Struts application as a portlet, Oracle recommends that you first create a new view to serve as the portlet view of your application. This view uses existing objects (Actions, ActionForm, and so on) with a new mapping and new JSPs.

Note:

Although Oracle recommends that you create a portlet view of your application, you could alternatively replace your application's struts tags with PDK-Java struts tags. This approach enables your application to run both as a standalone struts application and a portlet.

In this example, you create a portlet that enables you to add a new entry to a blog. Figure 60-5 and Figure 60-6 show how you submit a blog and save a blog entry.

Figure 60-5 Submitting a Blog

Shows updating a BLOG.
Description of "Figure 60-5 Submitting a Blog"

Figure 60-6 Saving a Blog Entry

Shows saving a BLOG.
Description of "Figure 60-6 Saving a Blog Entry"

prepareNewBlog is a simple empty action that redirects the request to the enterNewBlog.jsp page. This page shows a form for submitting a new blog.

The corresponding entry in the struts-config.xml is:

<action path="/prepareNewBlog" scope="request"
    type="view.PrepareNewBlogAction" >
    <forward name="success" path="/view/enterNewBlog.jsp"/>
</action>
<action path="/saveNewBlog" name="blogForm" scope="request"
    type="view.SaveNewBlogAction" input"/view/enterNewBlog.jsp"  >
    <forward name="success" path="/view/newBlogConfirmation.jsp"/>
</action>

This section includes the following subsections:

60.6.1 How to Create a New Flow and View to Host the Portlet Actions

To create a new view, first create a new set of ActionMappings (page flow) that redirects the various actions and requests to Portal-specific JSPs.

<action path="/portal/prepareNewBlog" scope="request"
    type="view.PrepareNewBlogAction" >
    <forward name="success" path="/view/portal/enterNewBlog.jsp"/>
</action>
<action path="/portal/saveNewBlog" name="blogForm" scope="request"
    type="view.SaveNewBlogAction" input="/view/enterNewBlog.jsp"  >
    <forward name="success" path="/view/portal/newBlogConfirmation.jsp"/>
</action>

As you can see, only the path attributes are modified. The FormBean Action responsible for the application business logic remains unchanged.

60.6.2 How to Create the New JSPs

As specified in the previous step, the actions forward the request to new JSPs, which are responsible for rendering the portlet content. Your new portlet view JSPs can share the HTML with the standalone view, but ensure the portlet meets the following criteria:

  • Uses styles that enforce a consistent look and feel with the rest of the page.

  • Contains HTML code that is allowed in HTML table cells (that is, no <html>, <body>, and <frame> tags).

  • Uses the PDK-Java version of the Struts HTML tag library. This renders URLs in the correct format to work in a portlet context.

The PDK Struts HTML tag library contains versions of the Struts HTML tags that can be used in portlet markup.

Note:

You can register the Oracle PDK with Oracle JDeveloper so that you can drop the tags from the Oracle JDeveloper Components Palette. For more information, see the Registering a Custom Tag Library in JDeveloper section in the Oracle JDeveloper online Help.

60.6.3 How to Create a Portlet

You can create your Struts portlet either manually or by using the Create Oracle PDK-Java Portlet wizard. Although the wizard does not explicitly offer Struts support, you can use the wizard to build your Struts portlet.

To create a portlet:

  1. In JDeveloper, open the Oracle PDK-Java Portlet wizard.

    For more information, see Section 60.2.1, "How to Create a PDK-Java Portlet."

  2. On the View Modes page of the wizard, for the Show Page mode, select an Implementation Style of Java Class.

  3. For the Package Name, enter oracle.portal.provider.v2.render.http.

  4. For the Class Name, enter StrutsRenderer. This generates the skeleton of the portlet renderer class, StrutsRenderer.

  5. As the StrutsRenderer is part of the PDK, you do not need this generated file. So, when you finish the wizard, you must delete the file generated by the wizard. To do so, click the file in the System Navigator window, then from the File menu, select Erase from Disk in JDeveloper.

  6. Edit the provider.xml and change the following properties:

    At the producer level, perform the following:

    • If the Struts application uses sessions (for example, the form synchronizer token mechanism is used or <actionInSession> is set to true), then enable session handling:

      <session>true</session>
      

    At the portlet level, perform the following:

    • If you want users to always return to the same portlet state as when they left the container page, then you can configure the struts renderer to save the struts action in the struts context:

      <actionInSession>true</actionInSession>
      

      If you prefer that users always start from the beginning of the portlet when they return from outside the container page, then you should not save the struts action:

      <actionInSession>false</actionInSession>
      

      Note that this setting is the default behavior.

    • Specify the first action to raise when the portlet is called. Use the following code:

      <showPage class="oracle.portal.provider.v2.render.http.StrutsRenderer">
      <defaultAction>/portal/prepareNewBlog.do</defaultAction>
      </showPage>
      

60.6.4 How to Extend the Portlet to Add Business Logic

In your application, you should add code specific to your environment, such as the user's information, personalization, and localization. To do so, you can create a new Action class that is only called in context, and handles all business logic.

60.6.5 How to Register the Producer

Now that your portlet is ready to be used by consumers, you must make it accessible by registering it. For information about how to register your PDK-Java portlet, see Section 62.3, "Registering an Oracle PDK-Java Portlet Producer with a WebCenter Portal: Framework Application."

60.7 Troubleshooting PDK-Java Portlets

This section provides information to assist you in troubleshooting problems you may encounter while creating and testing PDK-Java portlets.

This section includes the following subsections:

60.7.1 Cannot Access the Create Portlet Wizard

Problem

In the New Gallery, I cannot find the Oracle PDK-Java Portlet option.

Cause

The application in which you are trying to create the PDK-Java portlet was created using WebCenter Portal's Framework application template and therefore is not scoped for portlet creation.

Solution

  1. Try creating the portlet in a Portlet Producer Application or any application scoped for portlet creation (any application except for those built using WebCenter Portal's Framework application template).

  2. In the New Gallery, click the All Technologies tab to list all available options regardless of the technology scope of the application.

60.7.2 Cannot Add the Portlet Functionality that I Want to the Portlet

Problem

I cannot find the option to add certain features, for example portlet events or public render parameters, to the portlet in the Create Oracle PDK-Java Portlet wizard.

Cause

The Create Oracle PDK-Java Portlet wizard does not provide the option to add certain features to portlets.

Solution

After you create the portlet using the Create Oracle PDK-Java Portlet wizard, edit the portlet to add advanced functionality. For more information, see Section 60.3, "Developing PDK-Java Portlets."