Skip Headers
Oracle® Application Server Portal Developer's Guide
10g Release 2 (10.1.2)
Part No. B14134-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

5 Building Java Portlets

This chapter explains how to create Java portlets based on the Java Portlet Specification, how to build Java portlets using Oracle Application Server Portal Developer Kit-Java (PDK-Java), and how to make a portlet out of your struts application:

More on Portal Center

The source code for many of the examples referenced in this chapter are available as part of PDK-Java. You can download PDK-Java from the Oracle Application Server Portal Developer Kit (PDK) page on OTN, http://www.oracle.com/technology/products/ias/portal/pdk.html.

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

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

5.1 Guidelines for Creating Java Portlets

When you write your portlets in Java for either the Java Portlet Specification (JPS) or PDK-Java, you should follow the best practices described in this section. All of these guidelines pertain specifically to the Show modes of your portlet. A Show mode is an area of functionality provided by a portlet.


Note:

JPS offers some modes not offered by OracleAS Portal and vice versa. If you are coding portlets to JPS, you can declare custom portlet modes that map to the extra modes offered by OracleAS Portal.

An OracleAS Portal portlet may have the following Show modes, each with its own visualization and behavior. JPS portlets can define custom portlet modes in portlet.xml. Defining custom modes is especially useful if the portlet must interoperate with portal implementations from other vendors.

5.1.1 Shared Screen Mode (View Mode for JPS)

A portlet uses Shared Screen mode (known as View mode in JPS) to appear on a page with other portlets. This is the mode most people think about when they envision a portlet. Portlets are rendered inside HTML table cells when in Shared Screen mode. This means a portlet can display any content that can be rendered within a table cell, including, among other technologies, HTML, plug-ins, and Java applets. The actual size of the table cell is variable depending on user settings, the browser width, and the amount and style of content in the portlet. When developing portlets, remember that your portlet will share a page with others and you cannot completely control its dimensions and placement.

5.1.1.1 HTML Guidelines for Rendering Portlets

Plain HTML is the most basic way to render portlets and provides a great deal of flexibility to portlet developers. You can use almost any standard HTML paradigm, such as links, forms, images, tables, as long as it can display within an HTML table cell. Improperly written HTML may appear inconsistently across different browsers and, in the worst case, could cause parts of your page not to appear at all. Ensure that you adhere to the following rules:

  • Use standard HTML. The official HTML specification is available from the W3C (more information available at: http://www.w3.org/MarkUp/).

  • Avoid unterminated and extraneous tags. The behavior of pages with improperly terminated tags is unpredictable because it depends on what the browser chooses to do. Tools like weblint (http://www.weblint.org/) and HTML Tidy (http://www.w3.org/People/Raggett/tidy/) can help detect and fix hanging and unnecessary tags.

  • Avoid elements that cannot be rendered properly in an HTML table cell. Some constructs cannot be used simply because they do not display correctly in a table cell. Frames, for example, do not appear when inserted in a table.

  • Keep portlet content concise. Do not try to take full screen content and expose it through a small portlet. You end up with portlet content too small or cramped for smaller monitors.

  • Do not create fixed-width HTML tables in portlets. You have no way to tell how wide of a column your portlet will have on a user's page. If your portlet requires more room than given, it might overlap with another portlet in certain browsers.

  • Avoid long, unbroken lines of text. The result is similar to what happens with wide fixed-width tables. Your portlet might overlap other portlets in certain browsers.

  • Check behavior when resizing the page. Test your portlet's behavior when the browser window is resized to ensure that it works in different browser window sizes.

  • Check behavior when the default browser font changes. People may choose whatever font size they wish and they can change it at any point in time. Your portlet should handle these situations gracefully.

The HTML you use also impacts the perceived performance of your site. Users judge performance based on how long it takes for them to see the page they requested, and browsers require time to interpret and display HTML. Given that, you should:

  • Avoid deeply nested tables. Deeply nested tables slow performance dramatically in some older browser versions. OracleAS Portal draws several levels of tables to render portlets. If your portlets use tables within tables, your users may have to wait quite a while for those pages to render.

  • Avoid lengthy, complex HTML. Portlets share a page with other portlets. Thus, portlet generation times can significantly effect the overall performance of the page. If portlets must render complex HTML or wait for external resources, such as third party applications, it can greatly slow the rendering of the page.

5.1.1.2 Cascading Style Sheet Guidelines for Rendering Portlets

The fonts and colors of every portlet on a page should match the style settings chosen by the user. To accomplish this goal, these style selections are embedded automatically using a Cascading Style Sheet (CSS) on each OracleAS Portal page. The portlets access these settings for their fonts and colors, either directly or using the API.

While different browsers have implemented varying levels of the full CSS specification, OracleAS Portal uses a very basic subset of this specification to allow for consistent fonts and colors. CSS implementation levels should not affect the consistency of your pages across browsers. Follow these guidelines for using CSS:

  • Use CSS instead of hard coding. Hard coding fonts and colors is extremely dangerous. If you hard code fonts and colors, your portlet may look out of place when the user changes the page style settings. Since you have no way of knowing the user's font and color preference choices, you might also choose to hard code a font color that turns out to be the same as the user's chosen background color, in which case your portlet appears to be invisible to that user.

  • Use the CSS APIs to format your text. The stylesheet definition is available at the top of OracleAS Portal pages, but you should not call it directly. Instead, use the APIs provided to format your text appropriately. This method ensures that your portlets work even if the stylesheet changes in the future.

  • Avoid using CSS for absolute positioning. Since users can customize their portal pages, you cannot guarantee that your portlet can appear in a particular spot.

5.1.2 Edit Mode (JPS and OracleAS Portal)

A portlet uses Edit mode to allow users to customize the behavior of the portlet. Edit mode provides a list of settings that the user can change. These customizable settings may include the title, type of content, formatting, amount of information, defaults for form elements, and anything that affects the appearance or content of the portlet.

Portal users typically access a portlet's Edit mode by clicking Customize on the portlet banner. When you click Customize, a new page appears in the same browser window. The portlet typically creates a Web page representing a dialog box to choose the portlet's settings. Once you apply the settings, you automatically return to the original page.

5.1.2.1 Guidelines for Edit Mode Options

The following guidelines should govern what you expose to users in Edit mode:

  • Allow users to customize the title of the portlet. The same portlet may be added to the same portal page several times. Allowing the user to customize the title helps alleviate confusion.

  • If using caching, invalidate the content. If customizations cause a change in portlet display or content, you must ensure that the portlet content is regenerated and not returned from the cache. Otherwise, the user may see incorrect content.

  • Do not use Edit mode as an administrative tool. Edit mode is meant to give users a way of changing the behavior of their portlets. If you need to change provider settings or do other administrative tasks, you should create secured portlets specifically for those tasks.

5.1.2.2 Guidelines for Buttons in Edit Mode

For consistency and user convenience, Edit mode should implement the following buttons in the following order:

  • OK saves the user customizations and redirects the browser back to the calling portal page

  • Apply saves the user customizations and reloads the current page.

  • Cancel redirects the browser to the calling portal page without saving changes. Cancel differs from Reset to Defaults in that it leaves the current settings alone.

5.1.2.3 Guidelines for Rendering Customization Values

When you show the forms used to change customization settings, you should default the values such that the user does not have to constantly re-enter settings. When rendering the customization values, follow a specific sequence to provide consistent behavior. Following is the sequence for rendering customization values:

  1. User preference: Query and display this user's customizations, if available.

  2. Instance defaults: If no user customizations are found, query and display system defaults for the portlet instance. These are set in Edit Defaults mode and only apply to this portlet instance.

  3. Portlet defaults: If no system default customizations are found, display general portlet defaults, which may be blank. General portlet defaults are sometimes hard coded into the portlet but should be overridden if either of the two previous conditions apply.

This logic allows the customizations to be presented in a predictable way, consistent with the other portlets in the portal. PDK-Java makes this type of logic easy to implement.

5.1.3 Edit Defaults Mode (JPS and OracleAS Portal)

A portlet uses the Edit Defaults mode to allow page designers to customize the default behavior of a particular portlet instance. Edit Defaults mode provides a list of settings that the page designer can change. These customizable settings may include the title, type of content, formatting, amount of information, defaults for form elements, and anything that affects the appearance or content of the portlet.

These default customization settings can change the appearance and content of that individual portlet for all users. Because Edit Defaults mode defines the system level defaults for what a portlet displays and how it displays it, this mode should not be used as an administrative tool or for managing other portlets.

Page designers access Edit Defaults mode from the Customize Page when they choose Customize for Others. The link is labeled Edit Defaults on the banner of the wire frame diagram of that portlet.

When you click Edit Defaults, a new page appears in the same browser window. The portlet typically creates a Web page representing a dialog box to customize the portlet instance settings. Once the settings are applied, you are automatically returned to the original page.

5.1.3.1 Guidelines for Edit Defaults Mode Options

The following guidelines should govern what you expose to page designers in Edit Defaults mode:

  • If using caching, invalidate the cache. If customizations cause a change in portlet display or content, you must ensure that the portlet content is regenerated and not returned from the cache. Otherwise, the user may see incorrect content.

  • Do not use Edit Defaults mode as an administrative tool. Edit Defaults mode gives users a way of changing the behavior of their portlets. If you need to change provider settings or do other administrative tasks, you should create secured portlets specifically for those tasks.

5.1.3.2 Guidelines for Buttons in Edit Defaults Mode

For consistency and user convenience, Edit mode should implement the following buttons in the following order:

  • OK saves the user customizations and redirects the browser back to the calling portal page.

  • Apply saves the user customizations and reloads the current page.

  • Cancel redirects the browser to the calling portal page without saving changes. Cancel differs from Revert to Defaults in that is leaves the current settings alone.

5.1.3.3 Guidelines for Rendering Customization Values

When you show the forms used to change customization settings, you should default the values so that the page designer does not have to constantly re-enter settings. When rendering the customization values, follow a specific sequence to provide consistent behavior. Following is the sequence for rendering customization values:

  1. Instance preferences: Query and display system defaults for the portlet instance.

  2. Portlet defaults: If no system default customizations are found, display general portlet defaults, which may be blank. General portlet defaults are sometimes hard coded into the portlet but should be overridden by system defaults.

This logic allows the customizations to be presented in a predictable way, consistent with the other portlets in the portal.

5.1.4 Preview Mode (JPS and OracleAS Portal)

A portlet uses Preview mode to show the user what the portlet looks like before adding it to a page. Preview mode visually represents what the portlet can do.

Portal users typically access a portlet's Preview mode by clicking on its Preview icon from the Add Portlet page. A window then displays the preview of the chosen portlet. The user then has the option to add that portlet to the page. Portal administrators may access Preview mode from the Portlet Repository.

Note that the portal does not draw the portal banner when rendering the portlet in this mode.

5.1.4.1 Guidelines for Preview Mode

The following guidelines should govern what you expose to users in Preview mode:

  • Provide an idea of what the portlet does. Preview mode should generate enough content for the user to get an idea of the actual content and functionality of the portlet.

  • Keep your portlet previews small. The amount of data produced in this mode should not exceed a few lines of HTML or a screen shot. Preview mode appears in a small area and exceeding the window's size looks unprofessional and forces users to scroll.

  • Do not use live hyperlinks. Links may not behave as expected when rendered on the Add Portlet page or the Portlet Repository. Hyperlinks can be simulated using the underline font.

  • Do not use active form buttons. Forms may not behave as you expect them to when rendered on the Add Portlet page or the Portlet Repository. If you decide to render form elements, do not link them to anything.

5.1.5 Full Screen Mode (OracleAS Portal)

Portlets use Full Screen mode to show more details than possible when sharing a page with other portlets. Full Screen mode lets a portlet have the entire window to itself.

For example, if a portlet displays expense information, it could show a summary of the top ten spenders in Shared Screen mode and the spending totals for everyone in Full Screen mode. Portlets can also provide a shortcut to Web applications. If a portlet provided an interface to submitting receipts for expenses in Shared Screen mode, it could link to the entire expense application from Full Screen mode.

Portal users access a portlet's Full Screen mode by clicking the title of the portlet.

Technically, JPS portlets do not have Full Screen mode. However, you can implement the equivalent of Full Screen mode for a JPS portlet with View mode (Shared Screen mode) and a maximized state for the window.

5.1.5.1 Guidelines for Full Screen Mode

The following guidelines should govern what you expose to users in Full Screen mode:

  • Avoid elements that cannot be rendered properly in an HTML table cell. Even though Full Screen mode has a window to itself, the portlet is still formatted in an HTML table cell. Hence, you should avoid constructs that do not display correctly in a table cell. Frames, for example, do not appear when inserted in a table.

  • Provide a way to navigate to the previous page. You should provide users with a link or button that takes them back to the original portal page.

5.1.6 Help Mode (JPS and OracleAS Portal)

A portlet uses Help mode to display information about the functionality of the portlet and how to use it. The user should be able to find useful information about the portlet, its content, and its capabilities with this mode.

Portal users access a portlet's Help mode by clicking Help in the portlet banner.

5.1.6.1 Guidelines for Help Mode

The following guidelines should govern what you expose to users in Help mode:

  • Describe how to use the portlet. Users may not know all the features your portlet provides just from its interface. Describe the features and how to get the most out of them.

5.1.7 About Mode (JPS and OracleAS Portal)

Users should be able to see what version of the portlet is currently running, its publication and copyright information, and how to contact the author. Portlets that require registration may link to Web-based applications or contact information from this mode, as well.

Portal users access a portlet's About mode by clicking About on the portlet banner. A new page appears in the same browser window. The portlet can either generate the content for this new page or take the user to an existing page or application.

5.1.7.1 Guidelines for About Mode

The following guidelines should govern what you expose to users in About mode:

  • Display relevant copyright, version, and author information. Users want to know what portlet they are using and where they can get more information. The about page may become important when supporting your portlets.

5.1.8 Link Mode (OracleAS Portal)

A portlet uses Link mode to render a link to itself that displays on a mobile page. When the user clicks the link, the portlet is called in Show mode but with a different content type.

For JPS portlets that declare support of the Oracle Mobile XML content type, OracleAS Portal renders the link in one of two ways:

  • Call the portlet's View mode with the MINIMIZED window state, if the portlet declares support for it.

  • Otherwise, render a link using the portlet's title.

5.1.8.1 Guidelines for Link Mode

The following guidelines should govern what you expose to users in Link mode:

  • Limit content. Users should see the same data as Shared Screen mode but without all of the graphic images and unnecessary content that would be difficult or impossible to view effectively on the tiny screen of a mobile device.

5.2 Introduction to Java Portlet Specification and WSRP

Organizations engaged in enterprise portal projects have found application integration to be a major issue. Until now, users developed portlets using proprietary APIs for a single portal platform and often faced a shortage of available portlets from a particular portal vendor. All this changes with the introduction of the following standards:

These two standards enable the development of portlets that interoperate with different portal products, and therefore widen the availability of portlets within an organization. This wider availability can, in turn, dramatically increase an organization's productivity when building enterprise portals.

WSRP is a Web services standard that allows the plug-and-play of visual, user-facing Web services with portals or other intermediary Web applications. Being a standard, WSRP enables interoperability between a standards enabled container and any WSRP portal. WSRP defines:

JPS is a specification that defines a set of APIs to enable interoperability between portlets and portals, addressing the areas of aggregation, personalization, presentation, and security. JPS defines container services which provide:

Oracle actively participates in the WSRP committee and is also a member of the expert group for JPS. Oracle is committed to supporting these standards and is working on a production release of a WSRP-enabled portal. Today, Oracle Technology Network (OTN) members can:

5.2.1 The Relationship Between WSRP and JPS

WSRP is a communication protocol between portal servers and portlet containers, while JPS describes the Java Portlet API for building portlets. Combining these standards enables developers to integrate their applications from any internal or external source as portlets with WSRP portals. Building portal pages becomes as simple as selecting portlets from the OracleAS Portal repository. Figure 5-1 shows the architecture of the WSRP specification.


Note:

Figure 5-1 illustrates the use of JPS portlets with WSRP, but it should be noted that WSRP can also work with non-JPS portlets.

Figure 5-1 WSRP Specification Architecture

Shows JPS portlet containers and WSRP portal.
Description of the illustration pdg_java_arch1.gif

Since OracleAS Portal's existing architecture is so similar to the one specified by the WSRP committee, OracleAS Portal is able to support communication between our portal and both the new Java Portlet APIs as well as our existing APIs (PDK-Java). Figure 5-2 shows the architecture of the WSRP portal. Notice that the JPS-compliant portlet container uses the WSRP protocol for communication and the PDK-Java portlet container uses Oracle's proprietary protocol for communication.

Figure 5-2 OracleAS Portal's WSRP Architecture

Shows PDK-Java and JPS portlets and WSRP portal.
Description of the illustration pdg_java_arch2.gif

5.3 Building JPS-Compliant Portlets with Oracle JDeveloper

Using a convenient download from OTN, you can add extensions to Oracle JDeveloper for building portlets. To use this extension, you perform the steps in the following procedures:


Note:

OracleAS Portal is not WSRP-enabled in Release 9.0.4. You can, however, build and test your standards-based portlets today. To build standards-based portlets, use Oracle JDeveloper with the OracleAS Portal Add-In as described Section 5.3.2, "Building JPS-compliant Portlets". To test your standards-based portlets against a WSRP-enabled OracleAS Portal, you must use the Portlet Standards Developer's Preview release or portalstandards.oracle.com.

This section assumes the following:

5.3.1 Installing the Oracle JDeveloper Portal Add-In

The OracleAS Portal Developer Kit (PDK) provides you with the necessary libraries to install an add-in for Oracle JDeveloper that dramatically increases your flexibility and productivity when developing portlets. This extension includes two wizards, one for building JPS-compliant portlets and one for building PDK-Java portlets. Both wizards guide you through the steps of creating the portlet skeleton and all you need do then is implement your own business logic.

To obtain the add-in:

  1. Visit http://portalstudio.oracle.com.

  2. On the left side of the page, click Integration/Utilities.

  3. Click Portal Add-In for Oracle JDeveloper to download portal-addin.zip.

  4. Click Install Instructions and read and follow the instructions.


Note:

You can also just go to http://portalstudio.oracle.com and search for portal-addin.zip.

5.3.2 Building JPS-compliant Portlets

Once you have successfully installed the Portlet Wizard for Java, you can begin your interoperability portlet development quickly and easily with Oracle JDeveloper:

5.3.2.1 Creating a Portlet

This section walks you through the Portlet Wizard. You can choose which portlet Show modes you want to implement and the implementation method (JSP, HTTP servlet, Java class, or HTML). The wizard then creates a simple sample implementation for each of the selected modes.

  1. After you open Oracle JDeveloper, click the workspace where you want to create this project. If you do not have a workspace, you can create one as follows:

    1. Right-click the Applications node in the Applications - Navigator and choose New from the context menu.

    2. Choose Workspace from the Items list in the New Gallery dialog box.

    3. Click OK.

    4. Enter a Workspace Name and Directory Name, and clear Add a New Empty Project in the Create Workspace dialog box.

    5. Click OK.

  2. Right-click the name of the workspace in the Applications - Navigator and choose New Project from the context menu.

  3. Click Empty Project in the Items list in the New Gallery dialog box.

  4. Click OK.

  5. Enter the Project Name and Directory Name in the Create Project dialog box.

  6. Click OK.

  7. Right-click your project and select New from the context menu.

  8. In the Categories list, expand the Web Tier category and click Portlets.


    Note:

    If you cannot find Portlets, refer to Section 5.3.1, "Installing the Oracle JDeveloper Portal Add-In" to ensure that you have installed the add-in correctly.

  9. In the Items list, click Java Portlet.


    Note:

    Clicking Java Portlet opens the Portlet Wizard for creating JPS-compliant portlets. Clicking Oracle PDK Java Portlet opens the Portlet Wizard for creating PDK-Java portlets.

  10. Click OK. The Portlet Wizard appears.

  11. If you are on the Welcome page of the wizard, click Next.

  12. On the General Portlet Properties page, enter the values as described in Table 5-1 and shown in Figure 5-5.

    Table 5-1 General Portlet Properties Values

    Property Value
    Class Enter the name of the class the wizard will create. The field is primed with a default class name that you may accept or change.
    Package Browse the packages in the project and select the one in which the class will reside. If you do not select a package, the wizard uses the default package of the project.
    Default Language Select the default language that your portlet will support. The wizard uses English by default.
    Customizable Select whether your portlet will be customizable by end users. The wizard allows customization by default.

    Figure 5-5 General Portlet Properties Page

    Shows General Portlet Properties page.
    Description of the illustration pdg_java_jwiz_genprop.gif

  13. Click Next.


    Note:

    The Finish button is not enabled until after the second step of the wizard has been completed.

  14. On the Name and Attribution page, enter the values as described in Table 5-2 and shown in Figure 5-6.

    Table 5-2 Name and Attribution Values

    Property Value
    Display Name (required) Enter the name that will be displayed in the OracleAS Portal catalog or repository. Enter My Java Portlet for this example.
    Portlet Title (required) Enter the title that will appear on the portlet header (on a portal page). Enter Welcome to my company for this example.
    Short Title Enter the title that will appear on the portlet header for mobile devices. Enter Welcome for this example.
    Description Enter a description of your portlet. Enter This Java portlet displays a welcome message to users. for this example.
    Keywords Enter keywords to help users find the portlet in the portal. Enter welcome, new users, company information for this example.

    Figure 5-6 Name and Attribution Page

    Shows Name and Attribution page.
    Description of the illustration pdg_java_jwiz_nameatt.gif

  15. Click Next to continue specifying the portlet's properties or click Finish. If you click Finish at this point, the wizard chooses the default values for all remaining settings.

  16. On the Content Types and Portlet Modes page shown in Figure 5-7, select the content types for your portlet and map the portlet modes to an implementation. By default, your portlet will display text/html as the content type, and a portlet mode of View. If Customizable was selected on the General Portlet Properties page, then edit also appears as a portlet mode for text/html.

    Figure 5-7 Content Types and Portlet Modes Page

    Shows Content Types and Portlet Modes page.
    Description of the illustration pdg_java_jwiz_conty_portmodes.gif

    1. If you need to add content types other than text/html, click text/html and then click Add. For the purposes of this example, you do not need to add any other content types.

    2. If you need to add additional portlet modes, click an existing portlet mode (for example, view) and click Add. The list of available portlet modes displays, as shown in Figure 5-8, and you can add portlet modes by moving the desired portlet modes from the Available Modes list to the Selected Modes list. For the purposes of this example, you do not need to select any other portlet modes. When you are finished with the Portlet Modes dialog box, click OK.

      Figure 5-8 Portlet Modes Dialog Box

      Shows Portlet Modes dialog.
      Description of the illustration pdg_java_jwiz_pmodes.gif

    3. Once you have added all of the desired portlet modes, you need to choose the function to be performed for each mode. For each portlet mode, click the portlet mode and choose the desired function from the radio group on the right. For the purposes of this example, choose Generate JSP for both the edit and view portlet modes, and leave the default path and file name of the generated JSP. For more information on portlet modes, refer to Section 5.1, "Guidelines for Creating Java Portlets".


      Note:

      Generate JSP and Custom Code generate code for you in the specified location. Map to Path routes the request through to an existing Web resource that you will create separately yourself.

  17. Click Next.

  18. If you selected Customizable on the General Portlet Properties page earlier in the wizard, the Customization Preferences page, shown in Figure 5-9, now displays and you can declare preferences for your portlet. If you did not select Customizable earlier, then this page is skipped. On the Customization Preferences page, you specify a preference name, default value, and whether the preference value should be translated:

    Figure 5-9 Customization Preferences Page

    Shows Customization Preferences page.
    Description of the illustration pdg_java_jwiz_cust_pref.gif

    1. To add a preference, click Add and fill in the Add New Preference dialog box, show in Figure 5-10, (Name, Default Value(s), and whether it should be translated).


      Note:

      The Name is always translated, but there is not always a need to translate the Default Value. For example, if the value is an integer, no translation is needed

      Figure 5-10 Add New Preference Dialog Box

      Shows New Preferences dialog box.
      Description of the illustration pdg_java_jwiz_new_pref.gif

    2. To delete a preference, choose it in the Portlet Preferences list and click Remove.

  19. Click Next.

  20. On the Security Roles page, shown in Figure 5-11, you can add security roles to your portlet. The wizard has no predefined security roles. It parses the web.xml for security roles and enables them to be referenced by your portlet. You will not need to do anything for this step as a new project has no security roles defined. You can manually create the security roles according to JPS later.

  21. Click Next.

  22. On the Caching page, you specify whether to enable caching of your portlet by default. The portlet itself may choose to cache content for any given response. The settings on this page come into force when the portlet itself does not specify a caching condition for a response. For the purposes of this example, fill out this page as described below and shown in Figure 5-12:

    1. Click Cache Portlet.

    2. Click Cache Content Expires After.

    3. Accept the default duration of the cached copy (60 seconds).


    Note:

    If you did not want any default caching for this portlet, you would choose Do Not Cache By Default. In this case, the wizard actually sets a cache duration of 0 seconds. As stated above, this cache setting only comes into play when the portlet itself does not specify a caching condition for a response.

    If you choose no caching here and you later decide that you want default caching for the portlet, you can easily go back and change the cache duration value in the portlet.xml file, which is generated by the wizard, to some number greater than zero.


  23. Click Next.

  24. On the Initialization Parameters page, shown in Figure 5-13, you can add any required initialization parameters for the portlet. Initialization parameters provide the Web application developer, who decides what goes into the .war file, an alternative to JNDI variables for configuring the behavior of all of the different components of the Web application (for example, servlets and portlets) in a compatible way. For more information on initialization parameters, refer to the Java Portlet Specification. For the purposes of this example, no initialization parameters are needed.

    Figure 5-13 Initialization Parameters Page

    Shows Initialization Parameters page.
    Description of the illustration pdg_java_jwiz_init_param.gif

  25. Click Next.

  26. Click Finish to generate the files for your portlet. In this case, the following files should be generated for your project node in the Applications - Navigator (see Figure 5-14):

    • Generated code for each View mode, assuming that you selected Generate JSP on the Content Types and Portlet Modes page. If you selected Custom Code instead, that code will reside in the portlet's Java class.

    • Two Java classes

    • portlet.xml

    • web.xml

5.3.2.2 Adding Portlet Logic

Once you create the default implementation, you can extend the sample code with your own business logic to implement the desired functionality and features. Refer to the JavaDoc or JPS for more information on adding functionality and features. For the purposes of this example, you do not need to perform this step and can proceed directly to the deployment procedure.

5.3.2.3 Deploying Your Portlet to an Application Server

After you finish the wizard and successfully generate your portlet, you are ready to deploy it to an application server. Because you chose to create a JPS-compliant portlet, you can deploy it using the wizard for any vendor's JPS-compliant container. The following procedures describe how to deploy a JPS-compliant portlet to Oracle's WSRP container running on Oracle Application Server Containers for J2EE:

5.3.2.3.1 Creating a Connection to Oracle Application Server Containers for J2EE

To establish a connection to your application server, perform the following steps:


Note:

The steps that follow describe the procedure for deploying to a standalone instance of Oracle Application Server Containers for J2EE. For information about deploying to a full Oracle Application Server instance, please refer to the Oracle JDeveloper online help system.

  1. If it is not still open, start Oracle JDeveloper and open the project you created in the previous sections.

  2. In the Navigator, click the Connections tab.

  3. Right-click the Connections node and select New Application Server Connection from the context menu. Complete the wizard that displays as follows:

    1. If the Welcome page appears, click Next. If you do not want the Welcome page to appear in future, be sure to select Skip this Page Next Time.

    2. Enter a meaningful name for the connection (for example, PDKStandardsOC4J), and choose Standalone OC4J as the connection type.

    3. Click Next.

    4. Enter the administrator's user name and password. This password was set during the installation of the PDK Standards Oracle Application Server Containers for J2EE.

    5. Click Next.

    6. Enter the information in Table 5-3.

      Table 5-3 Settings for New Application Server Connection

      Setting Value
      URL Enter the full RMI URL for this setting. For example:

      ormi://my.machine.com:23791/

      The RMI port number may be found in:

      OC4J_HOME/j2ee/home/config/rmi.xml

      Target Web Site Enter the name of the target Web site containing your deployed J2EE application files. For the purposes of this example, you can accept the default value, http-web-site.
      Local Directory Where admin.jar for OC4J Is Installed Enter the path to the local admin.jar that is version-compatible with the remote servers specified in the URL setting above. For JPS-compliant portlets built with Oracle JDeveloper 9.0.3, you need to change the default path in this setting to point to an instance of Oracle Application Server Containers for J2EE Release 9.0.4. For example:

      OC4J_HOME\j2ee\home


    7. Click Next.

    8. Verify the connection details by clicking Test Connection. A success message should appear if everything is correct. If the test fails, you may need to revise your connection information.

    9. Click Finish.

5.3.2.3.2 Deploying the WAR File

To create and deploy a WAR file, perform the following steps:

  1. Go to the Applications - Navigator.

  2. In your current project, right-click web.xml and choose Create WAR Deployment Profile from the context menu.

  3. In the Save Deployment Profile dialog box, change the name to something meaningful (for example, jsrportlet1.deploy).

  4. Click OK.

  5. In the Profile Settings dialog box, perform the following steps:

    1. Click Specify J2EE Web Context Root and enter my-portlet in the adjacent field.

    2. Click OK.

  6. Right-click the deployment profile (for example, jsrportlet1.deploy) and choose Deploy to > the application server connection (for example, PDKStandardsOC4J) from the context menu.

  7. Await the Deployment Finished message in the Deployment Log at the bottom of Oracle JDeveloper and verify that no errors occurred.

  8. Take the URL provided in the log (for example, http://myserver.com:8888/my-portletFoot 2 ) and append /portlets?WSDL to construct the URL you use to register your JPS-compliant portlet with OracleAS Portal. For example:

    http://myserver.com:8888/my-portlet/portlets?WSDL
    

    Note:

    In some cases, you may get a message in the log stating that Oracle JDeveloper was unable to determine the HTTP port number of the remote server. Typically, you can determine the port number yourself by looking at the URL that takes you to your Oracle Application Server Containers for J2EE home page (for example, http://myserver.com:8888).

5.3.2.4 Registering and Viewing Your Portlet

After you've created and deployed the provider and its portlet(s), you must register the provider with OracleAS Portal. Registering your provider gives OracleAS Portal the information it needs to locate and communicate with your provider. After you register a provider, the provider and its portlets become available in the Portlet Repository. They are also listed in the OracleAS Portal Navigator.


Note:

When you build portlets and providers with built-in tools, such as the Portlet Builder, OracleAS Portal automatically registers the provider for you. Once you've created your portlet, it automatically displays in the Portlet Repository. OracleAS Portal also offers built-in portlets that are contained in a preconfigured provider. For example, OmniPortlet and Web Clipping are portlets that you can use out of the box, and are already registered with OracleAS Portal. You can view these portlets in the Add Portlets list. However, if you build the portlets and providers programmatically, you must then register these providers in order to make them available to the portal user.

This section describes how to register your provider and add your portlet to pages:

5.3.2.4.1 Registering on a Local OracleAS Portal Instance

To register your standards-based portlets against a WSRP-enabled OracleAS Portal, you must have installed and configured the Portlet Standards Developer's Preview release. You can obtain this preview release from the Oracle Technology Network. Assuming you have a local instance of the WSRP-compliant OracleAS Portal, you can register your portlet as follows:

  1. Open OracleAS Portal and log in as normal. Note that to register your provider, you need to have Manage or Edit privileges on providers. If you do not have these privileges, you need to request them from your administrator.

  2. If you are not already on the Builder page, click Builder in the upper right corner.

  3. Click the Administer tab.

  4. Click the Portlets subtab.

  5. In the Remote Providers portlet, click Register a Provider.

  6. On the Register Provider page, shown in Figure 5-15, enter the values as described in Table 5-4.

    Table 5-4 Register Provider Page Values

    Setting Value
    Name your_nameProvider
    Display Name your_name Provider
    Timeout 100
    Timeout Message The your_name Provider has timed out!
    Implementation Style WSRP

  7. Click Next.

  8. On the Define Connection page, shown in Figure 5-16, enter the WSDL URL for your provider in the WSDL URL field. This URL is the one that you created in step 8 of Section 5.3.2.3.2, "Deploying the WAR File". For example:

    http://myserver.com:8888/my-portlet/portlets?WSDL
    
  9. Click Next.

  10. On the Portal Registration Information page, shown in Figure 5-17, you fill in any registration properties required by the provider. If there are none, you can proceed to the next step.

    Figure 5-17 Portal Registration Information Page

    Shows Portal Registation Information page.
    Description of the illustration pdg_java_regp_reg_props.gif

  11. Click Next.

  12. On the Control Access page, shown in Figure 5-18, assign privileges for this provider as desired. For the purposes of this example, you can enter a group (for example, PORTAL_ADMINISTRATORS) for Grantee and click Add.

  13. Click Finish. You should see a Registration Confirmation page similar to the one in Figure 5-19.

    Figure 5-19 Registration Confirmation Page

    Shows Registration Confirmation page.
    Description of the illustration pdg_java_regp_fin.gif

5.3.2.4.2 Registering on portal.standards.com

If you do not have a local instance of the WSRP-compliant OracleAS Portal, you can register your portlet as follows:

  1. Go to the OracleAS Portal Verification service on OTN:

    http://portalstandards.oracle.com/
    
    
  2. Follow the instructions in the document, How to Test Interoperability, located on OTN:

    http://portalstandards.oracle.com/pls/wsrp/docs/PAGE/WSRPPORTALPAGE/
    VERIFICATIONSERVER/TAB31866/HOW.TO.REGISTER.WSRP.PROVIDERS.HTML
    
5.3.2.4.3 Adding Your Portlet

Your portlet should now be available for adding to pages like any other portlet in the Portlet Repository. To add your portlet to a page, follow the instructions in Section 7.6.2, "Adding Portlets," of the Oracle Application Server Portal User's Guide.

5.4 Building PDK-Java Portlets with Oracle JDeveloper

Using a convenient download from OTN, you can add extensions to Oracle JDeveloper for building portlets. To use this extension, you perform the steps in the following procedures:

This section assumes the following:

5.4.1 Installing the Oracle JDeveloper Portal Add-In

For instructions on how to install the Oracle JDeveloper Portal add-in, refer to Section 5.3.1, "Installing the Oracle JDeveloper Portal Add-In".

5.4.2 Building PDK-Java Portlets

Once you have successfully installed the Oracle JDeveloper Portal add-in, you can begin your portlet development quickly and easily with Oracle JDeveloper:

5.4.2.1 Creating a Portlet and Provider

This section walks you through the Portlet Wizard. You can choose which portlet Show modes you want to implement and the implementation method (JSP, HTTP servlet, Java class, or HTML). The wizard then creates a simple sample implementation for each of the selected modes.

  1. After you open Oracle JDeveloper, click the workspace where you want to create this project. If you do not have a workspace, you can create one as follows:

    1. Right-click the Applications node in the Applications - Navigator and choose New from the context menu.

    2. Choose Workspace from the Items list in the New Gallery dialog box.

    3. Click OK.

    4. Enter a Workspace Name and Directory Name, and clear Add a New Empty Project in the Create Workspace dialog box.

    5. Click OK.

  2. Right-click the name of the workspace in the Applications - Navigator and choose New Project from the context menu.

  3. Click Empty Project in the Items list in the New Gallery dialog box.

  4. Click OK.

  5. Enter the Project Name and Directory Name in the Create Project dialog box.

  6. Click OK.

  7. Right-click your project and select New from the context menu.

  8. In the Categories list, expand the Web Tier category and click Portlets.


    Note:

    If you cannot find Portlets, refer to Section 5.3.1, "Installing the Oracle JDeveloper Portal Add-In" to ensure that you have installed the add-in correctly.

  9. In the Items list, click Oracle PDK Java Portlet.


    Note:

    Clicking Java Portlet opens the Portlet Wizard for creating JPS-compliant portlets. Clicking Oracle PDK Java Portlet opens the Portlet Wizard for creating PDK-Java portlets.

    Figure 5-20 New Gallery Dialog Box for Oracle PDK Java Portlet

    Shows New dialog box with Web Tier expanded.
    Description of the illustration pdg_java_jwiz_new_pdk.gif

  10. Click OK. The Portlet Wizard displays.

  11. If you are on the Welcome page of the wizard, click Next.

  12. On the Portlet Description page, shown in Figure 5-22, enter the names, description, and timeout settings. For the purposes of this example, you can accept the default values on this page.

    Figure 5-22 Portlet Description Page

    Shows Portlet Description page.
    Description of the illustration pdg_java_jwiz_desc_pdk.gif

  13. Click Next.

  14. The next few pages of the wizard enable you to define the portlet modes for this portlet. The Show Modes page, shown in Figure 5-23, enables you to choose the implementation style for the Show page and whether you want to implement Show details page:

    1. Show page is selected by default. Choose an Implementation style from the list. For the purposes of this example, choose JSP. Enter the File name for the JSP to be generated by the Portlet Wizard. For the purposes of this example, you may accept the default file name.

    2. If your portlet requires a details page, select Show details page and enter the Implementation style and File name as appropriate. For the purposes of this example, we do not need Show details.

  15. Click Next.

  16. On the Customize Modes page, shown in Figure 5-24, Edit page should already be selected. For the purposes of this example, choose an Implementation style of JSP and accept the default File name.

  17. Select Edit Defaults page and, for the purposes of this example, choose an Implementation style of JSP and accept the default File name.

  18. Click Next.

  19. On the Additional Modes page, shown in Figure 5-25, nothing is selected by default. For the purposes of this example, select Help page, choose an Implementation style of JSP, and accept the default File name.

  20. Select About page, choose an Implementation style of JSP, and accept the default File name.

  21. Click Next.

  22. On the Public Portlet Parameters page, shown in Figure 5-26, click Add.

  23. Enter the values as described in Table 5-5 and shown in Figure 5-26.

    Table 5-5 Public Portlet Parameter

    Name Display Name Description
    MyParam My Portlet Parameter This parameter displays a value.

    Figure 5-26 Public Portlet Parameters Page

    Shows Public Portlet Parameters page.
    Description of the illustration pdg_java_jwiz_pp_params.gif

  24. Click Next.

  25. On the Public Portlet Events page, shown in Figure 5-27, you can map parameters to events. For the purposes of this example, leave this page empty and click Next.

    Figure 5-27 Public Portlet Events Page

    Shows Public Portlet Events page.
    Description of the illustration pdg_java_jwiz_pp_events.gif

  26. On the Provider Description page, shown in Figure 5-28, enter MyJPWProvider as the Provider name. Ensure that all of the check boxes are selected.

    Figure 5-28 Provider Description Page

    Shows Provider Description page.
    Description of the illustration pdg_java_jwiz_prov_desc.gif

  27. Click Finish to generate the files for your portlet. In this case, the following files should be generated for your project in the Applications - Navigator (see Figure 5-29):

    • Files for each portlet mode you selected.

    • provider.xml

    • web.xml

    • index.jsp

    • _default.properties

    • myjpwprovider.properties

    All of the above files are required to deploy and run the portlet successfully, except for index.jsp, which is used by Oracle JDeveloper for testing purposes.

5.4.2.2 Adding Portlet Logic

Once you create the default implementation, you can extend the sample code with your business logic to implement the desired functionality and features. For the purposes of this example, you do not need to perform this step and can proceed directly to the testing and registration procedures.

5.4.2.3 Validating Your Portlet and Provider

After you have built your portlet, you need to check the configuration to ensure that the portlet and its provider operate correctly.


Note:

This procedure is for testing purposes only. After this procedure, you still need to register your provider as described in Section 5.4.2.5, "Registering and Viewing Your Portlet". For development and production, you should always deploy your portlet to an application server as described in Section 5.4.2.4, "Deploying to an Application Server".

  1. If it is not already open, open Oracle JDeveloper and the project your created in the previous sections.

  2. Find the index.jsp file for your portlet in the Navigator and right-click it.

  3. Choose Run from the context menu. Your browser should open with a page similar to the one shown in Figure 5-30.

    Figure 5-30 Portlet Application Test Page

    Shows portlet application test page.
    Description of the illustration pdg_java_jwiz_test.gif

  4. Click the link underneath Service Name. Your browser should open with a page similar to the one shown in Figure 5-31. Note that you need the URL from this page to register your provider, which is the next procedure.

5.4.2.4 Deploying to an Application Server

After you finish the wizard and successfully generate your portlet, you are ready to deploy it to an application server, Oracle Application Server Containers for J2EE. The following procedures describe how to deploy a portlet to Oracle Application Server Containers for J2EE:

5.4.2.4.1 Creating a Connection to Oracle Application Server Containers for J2EE

To establish a connection to your application server, perform the following steps:


Note:

The steps that follow describe the procedure for deploying to a standalone instance of Oracle Application Server Containers for J2EE. For information about deploying to a full Oracle Application Server instance, please refer to the Oracle JDeveloper online help system.

  1. If it is not still open, start Oracle JDeveloper and open the project you created in Section 5.4.2.1, "Creating a Portlet and Provider".

  2. In the Navigator, right-click Connections and select New Application Server Connection from the context menu. Complete the wizard that displays as follows:

    1. If the Welcome page appears, click Next. If you do not want the Welcome page to appear in future, be sure to select Skip this Page Next Time.

    2. Enter a meaningful name for the connection (for example, PDKJavaOC4J) and choose Standalone OC4J as the connection type.

    3. Click Next.

    4. Enter the administrator's user name and password. This password was set during the installation of the Oracle Application Server Containers for J2EE.

    5. Click Next.

    6. Enter the information in Table 5-6.

      Table 5-6 Settings for New Application Server Connection

      Setting Value
      URL Enter the full RMI URL for this setting. For example:

      ormi://my.machine.com:23791/

      The RMI port number may be found in:

      OC4J_HOME/j2ee/home/config/rmi.xml

      Target Web Site Enter the name of the target Web site containing your deployed J2EE application files. For the purposes of this example, you can accept the default value, http-web-site.
      Local Directory Where admin.jar for OC4J Is Installed Enter the path to the local admin.jar that is version-compatible with the remote servers specified in the URL setting above. For portlets you plan to deploy to Oracle Application Server Containers for J2EE 9.0.3, you can use the default admin.jar included with Oracle JDeveloper 9.0.3. For portlets you plan to deploy to Oracle Application Server Containers for J2EE 9.0.4, you need to change the default path in this setting to point to an instance of Oracle Application Server Containers for J2EE Release 9.0.4. For example:

      OC4J_HOME\j2ee\home


    7. Click Next.

    8. Verify the connection details by clicking Test Connection. A success message should display if everything is correct. If the test fails, you may need to revise your connection information.

    9. Click Finish.

5.4.2.4.2 Deploying the WAR File

To create and deploy a WAR file, perform the following steps:

  1. Right-click your portlet project and choose New from the context menu.

  2. In the New dialog box, under Categories, choose General > Deployment Profiles and, under Items, choose WAR File - J2EE Web Module.

  3. In the Save Deployment Profile dialog box, change the name to something meaningful (for example, myj2eeportlet1.deploy).

  4. Click OK.

  5. In the Profile Settings dialog box, perform the following steps:

    1. Click Specify J2EE Web Context Root and enter myj2eeportlet1.

    2. In the pane on the left, choose File Groups > WEB-INF/lib > Contributors.

    3. Check Portlet Development.

    4. Click OK.

    5. Choose File > Save All.

  6. Right-click the deployment profile (for example, myj2eeportlet1.deploy) and choose Deploy to > the application server connection (for example, PDKJavaOC4J) from the context menu.

  7. Await the Deployment Finished message in the Deployment Log at the bottom of Oracle JDeveloper and verify that no errors occurred.

  8. Take the URL provided in the Deployment Log (for example, http://myserver.com:8888/myj2eeportlet1) and append /providers to construct the URL you use to test and register your J2EE portlet with OracleAS Portal. For example:

    http://myserver.com:8888/myj2eeportlet1/providers
    
    

    Note:

    In some cases, you may get a message in the log stating that Oracle JDeveloper was unable to determine the HTTP port number of the remote server. Typically, you can determine the port number yourself by looking at the URL that takes you to your Oracle Application Server Containers for J2EE home page (for example, http://myserver.com:8888).

  9. Enter the URL you constructed in the preceding step in your browser. You should see a page similar to the one in Figure 5-32.

    Figure 5-32 PDK - Java Test Page for Portlets

    Shows PDK - Java test page.
    Description of the illustration pdg_java_j2ee_dep_test.gif

5.4.2.5 Registering and Viewing Your Portlet

After you've created and deployed the provider and its portlet(s), you must register the provider with OracleAS Portal. Registering your provider gives OracleAS Portal the information it needs to locate and communicate with your provider. After you register a provider, the provider and its portlets become available in the Portlet Repository. They are also listed in the OracleAS Portal Navigator.


Note:

When you build portlets and providers with built-in tools, such as the Portlet Builder, OracleAS Portal automatically registers the provider for you. Once you've created your portlet, it automatically displays in the Portlet Repository. OracleAS Portal also offers built-in portlets that are contained in a preconfigured provider. For example, OmniPortlet and Web Clipping are portlets that you can use out of the box, and are already registered with OracleAS Portal. You can view these portlets in the Add Portlets list. However, if you build the portlets and providers programmatically, you must then register these providers in order to make them available to the portal user.

This section describes how to register your provider and add your portlet to pages:

  1. Open OracleAS Portal and log in as normal. Note that to register your provider, you need to have Manage or Edit privileges on providers. If you do not have these privileges, you need to request them from your administrator.

  2. If you are not already on the Builder page, click Builder in the upper right corner.

  3. Click the Administer tab.

  4. Click the Portlets sub tab.

  5. In the Remote Providers portlet, click Register a Provider.

  6. On the Provider Information page, shown in Figure 5-33, enter the values as described in Table 5-7.

    Table 5-7 Provider Information Page Values

    Setting Value
    Name your_namePDKJProvider
    Display Name your_name PDKJProvider
    Timeout 100
    Timeout Message The your_name PDKJProvider has timed out!
    Implementation Style Web

  7. Click Next.

  8. On the Define Connection page, shown in Figure 5-34, enter the URL for your provider in the URL field. This URL is the one that you created in step 8 of Section 5.4.2.4.2, "Deploying the WAR File". For example:

    http://myserver.com:8888/myj2eeportlet1/providers
    
    
  9. Click Next.

  10. On the Control Access page, shown in Figure 5-35, assign privileges for this provider as desired. For the purposes of this example, you can enter a group (for example, PORTAL_ADMINISTRATORS) for Grantee and click Add.

  11. Click Finish. You should see a Registration Confirmation page similar to the one in Figure 5-36.

    Figure 5-36 Registration Confirmation Page

    Shows Registration Confirmation page.
    Description of the illustration pdg_java_jwiz_j2ee_fin.gif

  12. Your portlet should now be available for adding to pages just as any other portlet in the Portlet Repository. To add your portlet to a page, follow the instructions in Section 7.6.2, "Adding Portlets," of the Oracle Application Server Portal User's Guide.

5.4.3 Adding Render Modes

In the Portlet Wizard, you add Show modes by checking boxes on the wizard pages. Refer to Section 5.4.2, "Building PDK-Java Portlets" for more information about using the wizard. For each Show mode that you select in the wizard, a basic HelloWorld skeleton is created. If you need to add a Show mode after creating the portlet or you are adding one of the modes (preview or link) not available through the wizard, you can do that manually by updating provider.xml and HTML or JSPs in Oracle JDeveloper. To add Render modes, you need to perform the following tasks:

Once you have completed this section, you will be able to implement any Render mode using RenderManager because the principles are the same for all modes. For example, even though this section does not describe how to implement the Help mode in detail, you will understand how to do it, as the process is the same as for Preview mode, which is described here.

To learn about the extra requirements for rendering the special Edit and Edit Defaults Render modes, refer to the article, "Adding Customization to Java Portlets" on the Oracle Technology Center for OracleAS Portal. For more detailed information on the PDK runtime classes used in this article, refer to the JavaDoc.

5.4.3.1 Assumptions

  • You built a portlet using the wizard and successfully added it to a page.

5.4.3.2 Implementing Extra Show Modes

Your first task when creating Show modes manually is to create an HTML file or JSP for each mode. For example, if you want to implement Preview mode, you need to create an HTML file to provide preview content.

To create an HTML file to preview content, perform the following step:

  1. In Oracle JDeveloper, open the project that contains your portlets and select the portlet in the Applications - Navigator to ensure the HTML page is created in the appropriate place. You can use Oracle JDeveloper's design view to easily create HTML pages. For example, the following HTML could serve as a preview page:

    <p>This is the <i>preview</i> mode of your portlet!</p>
    
    

Once you have created the HTML file for previewing content, you are ready to update the XML provider definition.

5.4.3.3 Updating the XML Provider Definition

When you want to expose additional Render modes you must update your XML provider definition as follows:

  • Set a boolean flag that indicates to the PDK Framework that a link or icon to that mode should be rendered.

  • Point to the HTML file or JSP that you created for that mode.

For example, if you want to render Preview mode, perform the following steps:

  1. Edit the provider definition file, provider.xml and add the tag to activate Preview mode:

    <showPreview>true</showPreview>
    
    
  2. Specify the preview page to be the HTML page that you created in Section 5.4.3.2, "Implementing Extra Show Modes":

    <previewPage>/htdocs/myportlet/MyPortletPreviewPage.html</previewPage>
    
    
  3. Save the updates to provider.xml.

  4. Redeploy your portlet. Refer to step 6 in Section 5.4.2.4.2, "Deploying the WAR File".

5.4.3.4 Viewing the Portlet

To view the new Render modes, you must ensure that your updated XML provider definition is re-parsed. To do this, perform the following tasks:

  1. Copy the HTML file you created in Section 5.4.3.2, "Implementing Extra Show Modes" and provider.xml to the Oracle Application Server Containers for J2EE instance where you plan to deploy the portlet.

  2. Refresh the provider.

  3. Refresh the portal page containing your portlet.

To view Preview mode, do the following:

  1. Edit a page or create a new page and choose Add Portlet.

  2. Navigate to the location of your portlet with a Preview mode (for example, Portlet Staging Area). Note the magnifying glass icon next to the portlet shown in Figure 5-37

  3. Click the magnifying glass icon next to the portlet and a preview window similar to the one in Figure 5-38 appears.

5.4.4 Customizing Portlets

In Section 5.4.3, "Adding Render Modes" you learned how to use the PDK Provider Framework to activate and render additional Show modes that were either not activated when creating the portlet with the wizard or not available through the wizard (that is, Link and Preview modes). This section describes the two Customization modes (Edit and Edit Defaults) in more detail. When checked in the Java Portlet Wizard, Edit page and Edit Defaults page cause the generation of skeleton code for the two Customization modes. The skeleton code enables you to access the personalization framework with a few lines of code rather than completely hand coding a customization framework and a data store to hold the values.To add customization to your portlet, you need to do the following:

  • Update the Edit page of your portlet to set and retrieve customization changes.

  • Update the Edit Defaults page of your portlet to set and retrieve customization changes.

  • Update the Show page of your portlets to use the customization set by the user.

The Edit and Edit Defaults modes allow portlet users to change a set of customizable parameters supported by the portlet, which typically drive the way the portlet is rendered in other modes. For a particular instance of a portlet on an OracleAS Portal page, the customizations made in the Edit and Edit Defaults modes apply only to that instance of the portlet.

  • Edit mode customizations are specific to the individual user making the customizations. This mode is activated by clicking the Customize link on the portlet header in show mode.

  • Edit defaults mode customizations apply to all users in the same locale who have not yet made specific customizations to that portlet instance. This mode is generally only available to page designers, and can be activated by following the Edit icon on the page.

When rendering Edit and Edit Defaults modes, a PortletRenderer can carry out either of these tasks to support the customization process:

  • Renders the Edit Form: For each of the portlet's customizable parameters, PortletRenderer uses a PortletPersonalizationManager to retrieve the current value and renders a control in an HTML form so the current value can be edited.

  • Handles Edit Form actions: When an OK or Apply button is clicked on the standard edit form header, PortletRenderer uses a PortletPersonalizationManager to store the customized parameters submitted by the edit form and redirects the browser to the appropriate portal page.

Therefore, the purpose of the PortletPersonalizationManager controller is to enable a PortletRenderer to store and retrieve the current values of customizable parameters that apply to a particular portlet instance and user. The PDK Framework uses the abstraction of a PersonalizationObject as a container for a set of customized parameters and a PortletReference as the key under which a set of customizations are stored. Thus, a PortletPersonalizationManager is simply a mechanism that allows the storage and retrieval of persisted PersonalizationObjects under a given PortletReference.

A preference store is a mechanism for storing information like user preference data, portlet/provider settings, or even portlet data, while using OracleAS Portal. The information stored in the preference store is persistent in the sense that, even if you log out and log back in later, you could still access previously saved preferences. The preference store maintains the user preference information and invokes the user preferences whenever the user logs in again. PDK-Java provides the PrefStorePersonalizationManager, which uses a PreferenceStore implementation to persist customized data. Currently, PDK-Java has two PreferenceStore implementations: DBPreferenceStore and FilePreferenceStore. The DBPreferenceStore persists data using a JDBC compatible relational database and FilePreferenceStore persists data using the file system.

For more details of these implementations, consult the JavaDoc.


Note:

PDK-Java provides the Preference Store Migration/Upgrade Utility to help migrate the preference store from a file system to a database and upgrade customizations from earlier releases. This utility is described more fully on the Oracle Technology Network (http://www.oracle.com/technology/products/ias/portal/index.html).

To add customization functionality to your portlet you use PrefStorePersonalizationManager in conjunction with NameValuePersonalizationObject (that is, the default PersonalizationObject implementation). By default, the wizard generates a simple edit form for both the Edit and Edit Defaults modes to enable users to customize the portlet title. This section describes how to update the existing code to enable portal users to customize the portlet greeting.

5.4.4.1 Assumptions

  1. You have followed through and understood these sections:

  2. You built a portlet using the wizard, with Edit page and Edit Defaults page checked, and successfully added it to a page.

5.4.4.2 Implementing Customization for Edit and Edit Defaults Pages

The Edit page of your portlet is called when a user customizes the portlet. By default, the JSP generated by the wizard includes all of the required code to provide customization of the portlet title. You just need to insert a few lines of code into the Edit page for additional customization.

5.4.4.2.1 Reviewing the Generated Code

The wizard creates the following code for you by default:

<%@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.personalize.NameValuePersonalizationObject"
   import="oracle.portal.provider.v2.render.PortletRendererUtil"
%>

<%
 PortletRenderRequest pReq = (PortletRenderRequest)
   request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
%>

<P>Hello <%=pReq.getUser().getName() %>.</P>
<P>This is the <b><i>Edit</i></b> render mode!</P>
<%-- This page both displays the customization
     form and processes it,. Display the form if
     there is no action parameter, process it
     otherwise --%>

<%
 String actionParam = PortletRendererUtil.getEditFormParameter(pReq);
 String action = request.getParameter(actionParam);
 String title = request.getParameter("my2portlet_title");
 NameValuePersonalizationObject data = (NameValuePersonalizationObject)
    PortletRendererUtil.getEditData(pReq);
 // Cancel automatically redirects to the page, so
 // will only receive OK or APPLY
 if (action !=null)
 {
    data.setPortletTitle(title);
    PortletRendererUtil.submitEditData(pReq, data);
    return;
 }

 // Otherwise just render the form.
 title = data.getPortletTitle();
%>
<table border="0">
  <td width="20%">
   <p align="right">Title:</p>
  </td>
  <td width="80%">
   <input type="TEXT" name="my2portlet_title" value="<%= title %>">
  </td>
</table>
5.4.4.2.2 Modifying the Generated Code

The JSP contains an input field for the portlet title. This field represents the Customize page of the portlet where users can update the portlet title.

  1. Following the table in the generated code, add a second table containing a text field and a prompt, allowing users to enter a new greeting for the portlet:

    <table border="0">
      <tr>
        <td width="20%">
          <p align="right">Greeting:</p>
        </td>
        <td width="80%">
          <input type="TEXT" name="myportlet_greeting" value="<%= greeting %>">
        </td>
      </tr>
    </table>
    
    
  2. The HTML above simply specifies a field to enter a new greeting on the Edit page. This new greeting is displayed in the portlet's Shared Screen mode. Next, you add a string below String title that retrieves the value of the greeting:

    String title = request.getParameter("my2portlet_title");
    String greeting = request.getParameter("myportlet_greeting");
    
    
  3. Generating an Edit page from the wizard automatically includes access to the personalization framework in the page code. At the top of the Edit page, you see the NameValuePersonalizationObject declared. This form of personalization in OracleAS Portal allows easy storage of name/value pairs.

    The Edit page handles two cases: viewing the page or applying changes to it. The changes we have made so far affect the code for viewing the page. Applying changes to the Edit page is handled in the block of code beginning with if (action !=null).

    In this block of code, you must store the new portlet greeting. You must also account for the case where the user decides to make no changes and you simply retrieve the existing greeting:

    if (action !=null)
    {
         data.setPortletTitle(title);
         //Put the new greeting.
         data.putString("myportlet_greeting", greeting);
         PortletRendererUtil.submitEditData(pReq, data);
         return;
    }
    //Otherwise just render the form.
    title = data.getPortletTitle();
    //Get the old greeting.
    greeting = data.getString("myportlet_greeting");
    
    

You are now done updating the Edit page.

You can simply duplicate these changes for the Edit Defaults page. The Edit Defaults page is called when a page designer or portal administrator clicks Edit on the page and then clicks Edit Defaults. This page sets the default customization for this instance of the portlet. Even though the code in the JSP is identical, the PDK Framework and OracleAS Portal automatically handle the customization differently depending on the Show mode (Edit or Edit Defaults).

5.4.4.3 Implementing Customization for Show Pages

To have access to the personalization data in the portlet's Shared Screen mode, you need to add a few lines of code to the Show page. These lines include:

  • Adding import statements.

  • Declaring the NameValuePersonalizationObject.

  • Retrieving the customization data.

  1. Edit your Show page and import NameValuePersonalizationObject and PortletRendererUtil. You can copy these from the Edit page if necessary.

    <%@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.personalize.
         NameValuePersonalizationObject"
       import="oracle.portal.provider.v2.render.PortletRendererUtil"
    %>
    
    
  2. Declare the NameValuePersonalizationObject and retrieve the edit data from the portlet render request. You can copy this from the portlet's Edit page.

    <%
     PortletRenderRequest pReq = (PortletRenderRequest)
       request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
       NameValuePersonalizationObject data = (NameValuePersonalizationObject)
         PortletRendererUtil.getEditData(pReq);
    %>
    
    
  3. Get the string information from the customization framework:

    String greeting = data.getString("myportlet_greeting");
    
    
  4. Add some text to the Show page that displays the greeting in the Shared Screen mode of the portlet.

    <P>Hello <%= pReq.getUser()getName() %>.</P>
    <P>This is the <b><i>show</i>,</b> render mode!</P>
    <P>Greeting: <%= greeting %></P>
    
    

You have now completed updating the Show page of the portlet.

5.4.4.4 Preference Information Within the XML Provider Definition

The Portlet Wizard generates all of the needed tags for accessing the PreferenceStore in the XML provider definition file (provider.xml). By default, at the provider level, the wizard uses the FilePreferenceStore class to store preferences:

<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>

At the portlet level, tags are added to use PrefStorePersonalizationManager as the personalizationManager class and NameValuePersonalizationObject as the data class:

<personalizationManager class="oracle.portal.provider.v2.personalize.
   PrefStorePersonalizationManager">
    <dataClass>oracle.portal.provider.v2.NewValuePersonalizationObject</dataClass>
</personalizationManager

You need not make any changes or updates to the XML Provider Definition if you choose to continue to use the FilePreferenceStore class. However, if you have a global environment for OracleAS Portal (for example, you are running in a load balanced, multi-node cluster of Oracle Application Server Containers for J2EE instances) or would prefer to store preferences in the database, you can change the class from FilePreferenceStore to DBPreferenceStore.


Note:

For more information on using DBPreferenceStore, refer to Section "5.3.6 Step 6: Configure Portal Tools and Web Providers (Optional)" of the Oracle Application Server Portal Configuration Guide.

5.4.4.5 Viewing the Portlet

To view the customization changes you made in the preceding sections, you need to deploy the portlet to your application server or Oracle Application Server Containers for J2EE and refresh the page containing your portlet. You should now see that the portlet contains a null greeting. click Customize in the portlet title bar and update the greeting. When you return to the page, you should see your changes.

You can also test Edit Defaults by clicking Edit on the page and then clicking Edit Defaults. Since you have already modified the portlet, the changes will not appear to you in Shared Screen mode unless you view the page as a public user or a different user.

5.4.5 Passing Parameters and Submitting Events

OracleAS Portal and the PDK provide page parameters, public and private portlet parameters, and events to enable portlet developers to easily write reusable, complex portlets. The Portlet Wizard in Oracle JDeveloper creates portlets that are already set up to use parameters and events. This feature enables you to focus solely on adding business logic to your portlets and does not require any changes to provider.xml.

For an overview of parameters and events, refer to the following:

5.4.5.1 Assumptions

  1. You have followed through and understood Section 5.4.2, "Building PDK-Java Portlets".

  2. You built a portlet using the wizard and successfully added it to a page.

5.4.5.2 Adding Parameters to Your Portlets

Using the wizard in Section 5.4.2, "Building PDK-Java Portlets", you built a basic portlet and specified a parameter called MyParam. If you did not create a parameter, you can create a new portlet now by right clicking on provider.xml in the Applications - Navigator of Oracle JDeveloper, selecting Add Portlet, and following the steps in Section 5.4.2, "Building PDK-Java Portlets".

By default, the wizard creates a portlet to which you can easily map page parameters without updating any code or files. In this section, you will use the default parameter created for you by the wizard.

To use the default parameter, you only need to register the provider and add the portlet to a page. After that, you perform the following tasks:

  • Create a page parameter.

  • Wire the page parameter to your Java portlet.

  • Enter parameter values in the URL or another portlet that passes this page parameter.

  1. Go to the Parameter tab of the page properties. Note that parameters should be enabled by default, but, if not, you must enable them before proceeding.

  2. Create a page parameter called MyParameter with a default value of My Default Value.

  3. Expand your Java portlet and map the page parameter you just created to the portlet parameter.

    My Portlet Parameter = Page Parameter MyParameter
    
    
  4. Go back to the page. Notice that, in the portlet, a value of My Default Value appears.

  5. View the page and enter the parameter and a value at the end of the URL:

    &MyParameter=This%20portlet%20works
    
    

If you have a portlet, such as the Simple Parameter Form included with OmniPortlet, that can pass parameters, you can easily map parameters from that portlet to your Java portlet using the Events tab.

If you now take a look at the code and tags generated by the wizard, you see that very little code was needed to enable parameters in the Java portlet.

Review provider.xml. Note that the wizard added one tag group called inputParameter, which includes the name of the parameter for which the portlet listens.

<inputParameter class="oracle.portal.provider.v2.DefaultParameterDefinition">
  <name>MyParam</name>
  <displayName>My Portlet Parameter</displayName>
</inputParameter>

The wizard also generated code in the JSP that represents your Show page, which receives this parameter, and displays the parameter name and its value.

<% 
ParameterDefinition params[] = 
  pReq.GetPortletDefinition().getInputParameters();
%>

<p>This portlets input parameters are ...</p>
<table align="left" width="50%"><tr><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 < params.length; j++)
    {
       temp.append(values[j]);
       if (j + 1 != values.length)
       {
         temp.append(", ");
       }
    }
    value = temp.toString();
  }
  else
  {
    value = "No values submitted yet.";
  }
%>
<tr>
  <td><span class="PortletText2" <%= name %></span></td>
  <td><span class="PortletText2" <%= value %></span></td>
</tr>
<%
}
%>
</table>

5.4.5.3 Submitting Events

In the previous section, you created a portlet that received parameters. Now you will create a portlet that passes parameters and events to other portlets on the same page or a different page. Some portlets, like the Simple Parameter Form in OmniPortlet, provide an easy, declarative interface to create a simple form to pass parameters to other portlets. If you want complete control over the events passed and the look of your portlet, though, you can add events to your Java portlet.

The Portlet Wizard does not create all of the code needed to pass parameters to other portlets. The wizard updates the tags in provider.xml and requires that you add the necessary business logic to your JSP code. To create a portlet that uses events, you perform the following tasks:

5.4.5.3.1 Creating an Events Portlet

To create an events portlet, perform the following steps:

  1. Create a new portlet called MyEventsPortlet in the same provider by invoking the Portlet Wizard. Go through the wizard as normal. In step 5 of the wizard, create a parameter. In step 6 of the wizard, enter the information shown in Table 5-8.

    Table 5-8 Events

    Events Area Name Display Name Description
    Events Exposed MyEvent My Event This is my event.
    Parameters Associated MyParam My Parameter This is my parameter

    Figure 5-40 Public Portlet Events Page of Portlet Wizard

    Shows Public Portlet Events page.
    Description of the illustration pdg_java_event_wizard.gif

    The wizard generates the following code in provider.xml:


    Note:

    In the following example, notice that the input parameter and the event parameter have the same name, MyParam. They are two different parameters, even though they have the same name.

    <showDetails>false</showDetails>
    <inputParameter class="oracle.portal.provider.v2.
      DefaultParameterDefinition">
       <name>MyParam</name>
       <displayName>My Parameter</displayName>
    </inputParameter>
    <event class="oracle.portal.provider.v2.DefaultEventDefinition">
       <name>MyEvent</name>
       <displayName>My Event</displayName>
       <parameter class="oracle.portal.provider.v2.DefaultParameterDefinition">
         <name>MyParam</name>
         <displayName>My Parameter</displayName>
       </parameter>
    </event>
    <renderer class="oracle.portal.provider.v2.render.RenderManager">
    
    
  2. Import the needed classes:

    • oracle.portal.provider.v2.event.EventUtils

    • oracle.portal.utils.NameValue

    • oracle.portal.provider.v2.url.UrlUtils

  3. Add a link that passes the parameter value to another portlet. As shown in the sample code below, you receive the same page parameter as the previous portlet, but in addition you create a link that passes an event as well:

    <%@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"
    import="oracle.portal.provider.v2.event.EventUtils"
    import="oracle.portal.utils.NameValue"
    import="oracle.portal.provider.v2.url.UrlUtils"
    %>
    <%
    PortletRenderRequest pReq = (PortletRenderRequest)
    request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    %>
    <% 
      NameValue[] parameters = new NameValue[2];
      parameters[0] = new NameValue( EventUtils.eventName("MyEvent"),"");
      parameters[1] = new
    NameValue(EventUtils.eventParameter("MyParam"),pReq.getParameter
      ("MyParam"));
    %>   
    <span class="portletText1"><br>
    
    <a href="<%= UrlUtils.constructLink
      (pReq, pReq.getRenderContext().getEventURL(), parameters , true, true)%>">
    The value of the stock is <%= pReq.getParameter("MyParam") %>
    </a>
    <br><br></span>
    

    Note:

    This sample code does not handle NULL values. When the portlet is initially added to the page, you may receive an error, but, after wiring the portlet to the page parameter, it should work fine.

  4. Add the portlet to a different page (in the same page group) than the previous portlet (the Parameter Portlet). Expand the portlet and wire it to receive the same parameter as the previous portlet.

    My Parameter = Page Parameter MyParameter
    
    
  5. Apply your changes on the Parameter tab and go to the Events tab. Expand the Event portlet and select the event. Select Go to Page and find the page to which you want to pass the event. Choose the page where the Parameter portlet is located. Configure this portlet to pass an event as the page parameter MyParameter.

    MyParameter = Event Output MyParameter 
    
    

    Figure 5-41 Portlet Events in the Edit Page

    Shows Events tab.
    Description of the illustration pdg_java_event_edit.gif

  6. Click OK to view the page. Your Event portlet should have a link that displays the value received from the page.

    Figure 5-42 My Event Portlet Before Parameter Change

    Shows original Event portlet.
    Description of the illustration pdg_java_event_before.gif

  7. You can append a parameter value to the URL and the portlet displays the value in the link.

    &MyParameter=20
    
    
  8. When you click the link, that value is passed to the Parameter portlet on its page.

    Figure 5-43 My Event Portlet After Parameter Change

    Shows changed Event portlet.
    Description of the illustration pdg_java_event_after.gif

5.4.6 Accessing Session Information

When a user accesses any portal page, OracleAS Portal initiates a public unauthenticated session and maintains a cookie to track information about the session across requests. If the user logs in to OracleAS Portal, this session becomes an authenticated session of the logged-in user. This portal session terminates when:

  • 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.

A portal session exists from the time the user first accesses the portal to the time the session ends in one of these ways.

You can utilize 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 only store 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, you may want to store it in the preference store instead. Some common applications of the session store are:

  • 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 providers 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 Web providers, you create a stateful application that needs to track 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, a stateful application may cause you problems. Stateful applications can impact the load-balancing and failover mechanism for your OracleAS Portal configuration. Even though you may deploy multiple middle-tiers accessing the same OracleAS Portal instance, 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, impacting 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.

In previous sections, you learned how to use the PDK Framework to render portlet content in various Render modes and how to implement features such as customization, and parameters and events. This section describes you how to implement session storage for your portlet.

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

5.4.6.1 Assumptions

  1. You have followed through and understood Section 5.4.2, "Building PDK-Java Portlets".

  2. You built a portlet using the wizard and successfully added it to a page.

5.4.6.2 Implementing Session Storage

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 from OracleAS Portal, you need to 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 provider session may become invalid for the following reasons:

  • session times out

  • invalidate method on ProviderSession is called

  • 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. The returned instance-specific name can be used to write portlet instance data into the session. For more detailed information on the PDK Framework classes, refer to the JavaDoc

To implement session storage, you need to perform the following tasks:

  • Import ProviderSession, PortletRendererUtil, and HttpPortletRendererUtil.

  • Retrieve the provider session.

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

  • Set the session to true in provider.xml.

  • Register the provider 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 need to 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, you display the value, increment the count, and store the new value. If the session is valid but no previously stored value exists, 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, you want to provide information to the user indicating they may need to log back in.

    <%
    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 need to update this flag in order for the provider to receive session information from the portal. You should only set this tag to true if you are using session information in your provider or portlets. By setting this flag to true, extra load is added to the provider calls.

    <provider class="oracle.portal.provider.v2.DefaultProviderDefinition">
    <session>true</session>
    
    
  4. Register the provider for session support and set its Login Frequency to Once Per Session.

5.4.6.3 Viewing the Portlet

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

  • Set your provider to Once per User Session for the login frequency value.

  • Refresh the provider to accept the new changes.

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

5.4.7 Implementing Portlet Security

In the previous sections, you learned how to use the PDK Framework to render portlet content for various Show modes and how to implement features such as customization, parameters and events, and session storage. This section describes the available security services for your Java portlet. For more detailed information about the PDK classes referred to in this section, please refer to the JavaDoc.

5.4.7.1 Assumptions

  1. You have followed through and understood Section 5.4.2, "Building PDK-Java Portlets".

  2. You built a portlet using the wizard and successfully added it to a page.

5.4.7.2 Portlet Security Features

This section describes the various security features that are available to secure your portlet providers.

5.4.7.2.1 Authentication

When a user first logs in to an OracleAS Portal instance, they must enter their password to verify their identity and obtain access. This authentication is performed by OracleAS Single Sign-On server. Refer to Section 5.4.7.3, "Single Sign-On" for more information.

5.4.7.2.2 Authorization

Authorization determines if a particular user may view or interact with a portlet. OracleAS Portal provides two types of authorization checking:

  • Portal Access Control Lists (ACLs): After you are authenticated by OracleAS Single Sign-On, OracleAS Portal uses ACLs to determine what users privileges you have to perform actions on portal objects, such as folders and portlets. The actions available to a user can range from simply viewing an object to performing administrative functions on it. If you do not belong to a group that has been granted a specific privilege, OracleAS Portal prevents you from performing the actions associated with that privilege. Refer to Section 5.4.7.4, "OracleAS Portal Access Control Lists (ACLs)" for more information.

  • Programmatic Portlet Security: You can also implement your own security manager programmatically. Refer to Section 5.4.7.5, "Portlet Security Managers" for more information.

5.4.7.2.3 Communication Security

To this point, we have covered user authentication and authorization, which do not check the authenticity of messages received by a provider. To completely secure your providers, secure the communication between OracleAS Portal and a Web provider. (These methods do not apply to database providers, which execute within the OracleAS Portal database.) If the communication is not secured, it is possible for someone to imitate an OracleAS Portal instance and fool the Web provider into returning sensitive information. There are three types of communication security:

  • OracleAS Portal Server Authentication restricts access to a provider to a small number of recognized machines. This method compares the IP address or the host name of an incoming HTTP message with a list of trusted hosts. If the IP address or host name is in the list, the message is passed to the provider. If not, it is rejected before reaching the provider. Refer to Section 5.4.7.6, "OracleAS Portal Server Security" for more information.

  • Message Authentication appends a checksum based on a shared key to provider messages. When a message is received by the provider, the authenticity of the message is confirmed by calculating the expected value of the checksum and comparing it with the actual value received. If the values are the same, the message is accepted. If they are different, the message is rejected without further processing. The checksum includes a time stamp to reduce the chance of a message being illegally recorded in transit and resent later. Refer to Section 5.4.7.7, "Message Authentication" for more information.

  • Message Encryption relies on the use of the HTTPS protocol for OracleAS Portal to provider communication. Messages are strongly encrypted to protect the data therein. Encryption provides a high level of security, but it incurs a performance penalty due to the additional processing required for each message. Refer to Section 5.4.7.8, "HTTPS Communication" for more information.

For more information about communication security, refer to the Oracle Application Server Portal Configuration Guide.

5.4.7.3 Single Sign-On

Portlets act as windows into an application. They display summary information and provide a way to access the full functionality of the application. Portlets expose application functionality directly in the portal or provide deep links that take you to the application itself to perform a task.

For more information about Single Sign-On, refer to the Oracle Application Server Portal Configuration Guide.

An application may need to authenticate the user accessing the application through the portlet. These are the possible application authentication methods:

  • Partner Application. In this case, the application user is the same authenticated user used by OracleAS Portal.

  • External Application. In this case, the OracleAS Portal user is different from the application user, but the application user name and password are managed by the OracleAS Portal user.

  • No Application Authentication. In this case, the communication between provider and OracleAS Portal is not protected at all.

5.4.7.3.1 Partner Application

A partner application is an application that shares the same OracleAS Single Sign-On as OracleAS Portal for its authentication. Thus, when a user is already logged in to OracleAS Portal, their identity can be asserted to the partner application without them having to log in again.

Partner applications are tightly integrated with OracleAS Single Sign-On. When a user attempts to access a partner application, the partner application delegates the authentication of the user to OracleAS Single Sign-On. Once a user is authenticated (that is, has provided a valid username and password) for one partner application, the user does not need to provide a username or password when accessing other partner applications that share the same OracleAS Single Sign-On instance. The OracleAS Single Sign-On determines that the user was successfully authenticated and indicates successful authentication to the new partner application.

The advantages of a partner application implementation are as follows:

  • Provides the tightest integration with OracleAS Portal and OracleAS Single Sign-On Server.

  • Provides the best single sign-on experience to users.

  • Provides the most secure form of integration because user names and passwords are not transmitted between OracleAS Portal and the provider.

The disadvantages of a partner application implementation are as follows:

  • The application must share the same user repository as OracleAS Portal even though the application's user community may be a subset of the OracleAS Portal user community. While worth some consideration, this issue is a minor one because the portal pages that expose the application can be easily restricted to the application's user community.

  • The application can only be tightly integrated to one or more OracleAS Single Sign-On instances if they share the same user repository.

  • The application must be written such that it delegates authentication to OracleAS Single Sign-On.

  • You must have access to the application source code.

5.4.7.3.2 External Application

An external application uses a different authentication server than OracleAS Portal. The application may use a different instance of Single Sign-On Server used by OracleAS Portal or some other authentication method. However the Single Sign-On Server does store the username and password of the external application for that user. This means that when a user is already logged into Oracle Portal, they will be logged into the external application without having to type in their username or password.

Applications that manage the authentication of users can be loosely integrated with OracleAS Single Sign-On if the administrator registers them as external applications. When a user who was previously authenticated by OracleAS Single Sign-On accesses an external application for the first time, OracleAS Single Sign-On attempts to authenticate the user with the external application. The authentication process submits an HTTP request that combines the registration information and the user's user name and password for the application. If the user has not yet registered their user name and password for the external application, OracleAS Single Sign-On prompts the user for the required information before making the authentication request. When a user supplies a user name and password for an external application, OracleAS Single Sign-On maps the new user name and password to the user's OracleAS Portal user name and stores them. They will be used the next time the user needs authentication with the external application.

The advantages of an external application implementation are as follows:

  • Allows integration with many portals. If, however, one of the portals is preferred over the others, the application could be integrated as a partner application of that preferred portal and an external application of the others.

  • Provides a single sign-on experience for users. However, users still must maintain different user names and passwords. In addition, the external application user name mapping must be maintained.

  • Allows integration with multiple portals independent of their user repositories and OracleAS Single Sign-On.

  • Avoids the requirement of having access to the application source code.

The disadvantages of an external application implementation are as follows:

  • Does not share the same user repository as the portal, which requires additional maintenance of user information by the end user.

  • Transmits the user name and password to the provider in plain text, unless you implement SSL.

5.4.7.3.3 No Application Authentication

The provider trusts the OracleAS Portal instance sending the request completely. The provider can determine if the user is logged in and the portal user name, but the application has not authenticated the user.

The advantages of no application authentication are as follows:

  • Provides the easiest form of integration and the fastest to implement.

The disadvantages of no application authentication are as follows:

  • Provides the least security.

  • Provides the weakest integration with OracleAS Portal.

5.4.7.4 OracleAS Portal Access Control Lists (ACLs)

When you log on to an OracleAS Portal instance, you are authenticated by an OracleAS Single Sign-On instance. Having verified your identity, OracleAS Portal uses ACLs to determine whether you are authorized to access particular portlets and add them to your pages from the Portlet Repository.

OracleAS Portal ACLs operate according to the following security characteristics:

  • Privileges define the actions that can be performed on the object to which they are granted. Privileges include actions such as Manage and Execute.

  • OracleAS Portal users and their privileges are granted from the Administer tab of the Builder.

  • OracleAS Portal user groups are administered from the Administer tab of OracleAS Portal Builder. Membership in the groups and privileges granted to the groups are all defined and maintained here. A privilege granted to a user group is inherited by all the users of that group.

  • Provider privileges apply to the provider and all of its portlets. Provider ACLs are administered on the Provider tab of the OracleAS Portal Navigator.

  • Portlet privileges can override the privileges set for the provider of the portlet. Portlet ACLs are administered from the Provider tab of the OracleAS Portal Navigator. Clicking Open for a provider takes you to a page that manages the portlets of the provider.

For more information on the available privileges for each object, users, and user groups in OracleAS Portal, refer to the Oracle Application Server Portal Configuration Guide.

The advantages of ACLs are as follows:

  • ACLs offer a simple, yet powerful, mechanism to secure OracleAS Portal objects.

  • Central management of user group membership simplifies the management of ACLs because it negates the necessity of modifying the ACLs associated with each object.

The disadvantages of ACLs are as follows:

  • ACLs are applied at the provider or portlet level. You cannot vary the security rules for a portlet depending on the page where you place it.

5.4.7.5 Portlet Security Managers

Portlet security managers are implemented within a provider to verify that a given users may view an instance of the portlet. When a user views a page with a portlet instance on it, security managers determine whether the user has the appropriate privileges to see the portlet. Implementing access control methods in the provider restricts the retrieval of content from a portlet (that is, hides the portlet) from users without the appropriate privileges. Only if the specified characteristics, such as user details and preferences, pass the authorization logic will the content be retrieved for the user. If no portlet security methods are implemented in the provider, then any user name may be passed in, even fictitious, unauthenticated ones.

A provider can implement two portlet security methods:

  • Get a list of portlets.

  • Verify the accessibility of the portlet.

Portlets have access to the OracleAS Portal user privileges and groups of which the user is a member. The following information can be used by the security methods:

  • The default group of the user

  • The privileges of a user or group

  • The highest available privilege of a user across all groups

  • The objects the user can access (only in database providers)

The AuthLevelSecurityManager has access to the following information about authorization level:

  • Strongly authenticated.

    The user has been authenticated by OracleAS Single Sign-On in the current OracleAS Portal session (that is, the user logged in with a valid user name and password) and requested the portlet in the context of that session.

  • Weakly authenticated.

    A user who was previously strongly authenticated returns to view a page without an active OracleAS Portal session. A persistent cookie (maintained by the user's browser) indicates that in some previous session the user logged on with a valid user name and password.

  • Public or not authenticated.

    The user has not logged in within the context of the current OracleAS Portal session, and does not have a persistent cookie to indicate that such a state previously existed.

To incorporate these security services into your Java portlet, you simply need to update provider.xml and set the security level to strong, weak, or public. Place the following XML right above the </portlet> tag in provider.xml:

<securityManager class="oracle.portal.provider.v2.security.AuthLevelSecurityManager">
   <securityLevel>strong</securityLevel>
</securityManager>

After you make this change to provider.xml, refresh the provider.

The advantages of security methods are as follows:

  • Enable a portlet to produce different output depending on the level of authorization.

The disadvantages of security methods are as follows:

  • Most security manager implementations will use the authorization level or some other user specific element in an incoming message. A check of this type could be bypassed by an entity imitating an OracleAS Portal instance.

5.4.7.5.1 Viewing the Portlet

To demonstrate the behavior of the security manager added to your Java portlet, follow these steps:

  1. Ensure you are logged in to an OracleAS Portal instance with privileges to create pages and add portlets to a page.

  2. Create a new portal page, ensuring it is visible to PUBLIC.

  3. Add your Java portlet to the page.

  4. Make a note of the direct URL to your new Portal page.

  5. Now log out of the Portal instance by clicking the Logout link.

  6. Directly access the Portal page by entering the URL noted in Step 4 into your browser's address bar.

You will see the page created in Step 2 but not the portlet added in Step 3. When you added the portlet to the page, you were logged in and hence strongly authenticated. The PDK runtime detected this and allowed you to add the portlet. When you logged out and viewed the page, you were no longer strongly authenticated and hence the PDK Framework did not allow rendering of the portlet's contents.

If you log in again and view the page, you will see that the portlet is still there.

5.4.7.5.2 Implementing Your Own Security Manager

If your portlet requires special security arrangements which are not provided by the implementations shipped with the PDK, you will need to supply your own custom PortletSecurityManager controller class. To do this, simply extend the oracle.portal.provider.v2.security.PortletSecurityManager class and supply implementations for the two methods specified by the interface. Then simply replace the class attribute of the securityManager controller element in the XML provider definition with you new class name and configure child elements appropriately.

5.4.7.6 OracleAS Portal Server Security

One way to prevent unauthorized access to providers is to restrict access to the provider to known client machines at the server level. This method goes some way toward defending against denial of service attacks.

In Oracle Application Server, you achieve this goal by using the allow and deny directives in the httpd.conf file to control access to client machines based on their host names or IP addresses. If host names are used as discriminators, the server needs to look them up on its Domain Name Server (DNS), which adds extra overhead to the processing of each request. Using the IP address circumvents this problem, but the IP address of a remote client may change without warning.

The advantages of server security are as follows:

  • Limits access to the provider to trusted hosts only.

  • Simplifies configuration.

The disadvantages of server security are as follows:

  • OracleAS Web Cache does not have IP address checking capability. If OracleAS Web Cache sits in front of a provider, you have no protection from a client on any host sending show requests to OracleAS Web Cache.

  • Restricting access to certain IP addresses and host names may be circumvented by sending messages to a provider containing fake IP addresses and host names. This trick is difficult to perform effectively since return messages go to the machine whose IP address was copied, but it can still cause problems.

For more information on this topic, refer to the Oracle Application Server Portal Configuration Guide.

5.4.7.7 Message Authentication

PDK-Java supports message authentication so that access may be limited to a specified provider instance or group of provider instances. A provider is registered with a secret shared key known only to OracleAS Portal and provider administrators.

OracleAS Portal sends a digital signature, calculated using a Hashed Message Authentication Code (HMAC) algorithm, with each message to a provider. A provider may authenticate the message by checking the signature using its own copy of the shared key. This technique may be used in Secure Socket Layer (SSL) communication with a provider instead of client certificates.

OracleAS Portal calculates a signature based on user information, a shared key and a time stamp. The signature and time stamp are then sent as part of the SOAP message. The time stamp is based on UTC (coordinated universal time, the scientific name for Greenwich Mean Time) so that timestamps can be used in messages between computers in different time zones.

When the provider receives this message it generates its own copy of the signature. If the signatures agree, it will then compare the message time stamp with the current time. If the difference between the two is within an acceptable value the message is considered authentic and is processed accordingly.

A single provider instance cannot support more than one shared key because it could cause security and administration problems. For instance, if one copy of the shared key is compromised in some way, the provider administrator has to create a new key and distribute it to all of the OracleAS Portal clients, who then must update their provider definitions. The way around this problem is to deploy different provider services, specifying a unique shared key for each service. Each provider service has its own deployment properties file so that each service is configured independently of the others. The overhead of deploying multiple provider services within the same provider adapter is relatively small.

In a provider without OracleAS Web Cache in front of it, this use of the same signature cookie over the lifetime of a provider session implies a tradeoff between performance and the security provided by authenticating the requests. The signature cookie value is only calculated once after the initial SOAP request establishes the session with the provider. The shorter the provider session timeout, the more often a signature will be calculated providing greater security against a show request being resent illegally. However, the SOAP request required to establish a session incurs a time penalty.

In a provider using OracleAS Web Cache to cache show request responses, you have a similar tradeoff. Cached content is secured in the sense that incoming requests must include the signature cookie to retrieve it, but caching content for an extended period of time leaves the provider open to illegal show requests.

While the signature element provides protection against interception and resending of messages, it does nothing to prevent interception and reading of message contents. Messages are still transmitted in plain text. If you are concerned about the content of messages being read by unauthorized people, you should use message authentication in conjunction with SSL.

The advantages of message authentication are as follows:

  • Ensures that the message received by a provider comes from a legitimate OracleAS Portal instance.

The disadvantages of message authentication are as follows:

  • Causes administration problems if a provider serves more than one portal. Entails performance implications if made very secure by having a short session timeout.

For more information on this topic, refer to the Oracle Application Server Portal Configuration Guide.

5.4.7.8 HTTPS Communication

Normal communication between OracleAS Portal and a provider uses HTTP, a network protocol that transmits data as plain text using TCP as the transport layer. HTTPS uses an extra secured layer (SSL) on top of TCP to secure communication between a client and a server, making it difficult to intercept and read messages.

Each entity (for example, an OracleAS Web Cache instance) receiving a communication using SSL has a freely available public key and a private key known only to the entity itself. Any messages sent to an entity are encrypted with its public key. A message encrypted by the public key may only be decrypted by the private key so that, even if a message is intercepted by a felonious third party, it cannot be decrypted.

Certificates used to sign communications ensure that the public key does in fact belong to the correct entity. These are issued by trusted third parties, known as Certification Authorities (CA). They contain an entity's name, public key, and other security credentials and are installed on the server end of an SSL communication to verify the identity of the server. Client certificates may also be installed on the client to verify the identity of a client.

Oracle Wallet Manager manages public key security credentials. It generates public and private key pairs, creates a certificate request to a CA, and installs the certificate on a server.

For more information on this topic, refer to the Oracle Application Server Portal Configuration Guide.

5.4.7.8.1 Configuration of SSL

When a provider is registered from an OracleAS Portal instance, only one URL is entered, which means either HTTP or HTTPS may be used but not both.

Each port on each server that may be used to receive SSL messages must have a server side certificate installed (that is, the OracleAS Web Cache instance (if any)) in front of the Web provider and the server which hosts the provider. The certificate installed on a server port ensures that communication between two points is encrypted but does not authenticate the source of a message. Message authentication should be used as well to fully secure communication between a trusted OracleAS Portal instance and a provider.

For more information about SSL configuration for OracleAS Portal, refer to the Oracle Application Server Portal Configuration Guide.

5.4.7.9 LDAP (Oracle Internet Directory) Security

PDK-Java uses Portlet Security Managers for LDAP (Oracle Internet Directory) security. PDK-Java uses Oracle Internet Directory as a repository of users, groups, and permissions. It retrieves information about the logged-in user and determines whether the user has the required permissions to view the portlet and data within the portlet. By enabling Oracle Internet Directory security, your providers can:

  • Secure portlets based on groups.

  • Restrict access to the administrative functions of your portlets (using your own security manager).

  • Retrieve all of the user property information stored in the Oracle Internet Directory including first name, last name, title, email, telephone number, groups, and photo.

  • Create users and groups for OracleAS Portal.

By default, Oracle Internet Directory security is disabled. You must make a change in the deployment properties file for a specific provider to enable this feature. Enabling and using Oracle Internet Directory to secure your portlets can be done quickly and easily:

  1. Enable the Oracle Internet Directory manager in the deployment properties files (provider_name.properties).

    oidManager=true
    oidAdminClass=class_that_extends_oracle.portal.provider.v2.oid.OidInfo
    
    
  2. Provide the connection information for Oracle Internet Directory by extending the simple class called OidInfo.

  3. Provide a list of groups that can view your portlet in the provider definition file.

    <group>cn=group1,cn=groups,dc=us,dc=oracle,dc=com</group>
    
    

    Your provider connects to Oracle Internet Directory using the information provided to the OidInfo class by you. The portlet accesses Oracle Internet Directory using the credentials provided (for example, user name and password) and performs the specified tasks. We recommend that you create an Oracle Internet Directory user specifically for your provider connection with the minimum set of privileges needed to complete the tasks requested by your portlets. For example, if your portlet only checks group information, do not connect to the Oracle Internet Directory as an administrator.

5.4.7.9.1 Implementing Oracle Internet Directory Security

PDK-Java provides a set of default classes specifically for Oracle Internet Directory integration. These classes handle the connection from your portlets to Oracle Internet Directory, enable your portlets to be secured based on OracleAS Portal groups, and provide access to user property information from within Oracle Internet Directory. The classes used by your Web provider for Oracle Internet Directory integration:

  • oracle.portal.provider.v2.oid.OidInfo receives the Oracle Internet Directory connection information provided by the developer and connects to Oracle Internet Directory. When building your own portlets, you should extend this class to send secure connection details from the provider to Oracle Internet Directory.

  • oracle.portal.sample.v2.devguide.oid.UnsafeOidInfo is an extension of OidInfo and provides an easy way to test portlet security. This class is used by the Oracle Internet Directory samples in PDK-Java and parses the deployment properties file for the Oracle Internet Directory connection information (seen below). This class should only be used for testing and development, it is not safe to use in a production scenario.

  • oidManager is set to false by default. It must be set to true in provider_name.properties to enable Oracle Internet Directory. (If you have only one provider in your Web application, ensure that provider_name.properties is identical to _default.properties.) For example:

    serviceClass=oracle.webdb.provider.v2.adapter.soapV1.ProviderAdapter
    loaderClass=oracle.portal.provider.v2.http.DefaultProviderLoader
    showTestPage=true
    definition=providers/lab_provider/provider.xml
    autoReload=true
    oidManager=true
    oidAdminClass=oracle.portal.sample.v2.devguide.oid.UnsafeOidInfo
    oidHost=myhost.mydomain.com
    oidPort=oidPort
    oidUser=oidUser
    oidPasswd=oidPassword
    
    
  • oidAdminClass is set to the class that extends OidInfo. PDK-Java provides UnsafeOidInfo by default, but as the name suggests, this class should not be used in production scenarios.

    • oidHost is the machine where Oracle Internet Directory is hosted.

    • oidPort is the port used by the Oracle Internet Directory.

    • oidUser is the Oracle Internet Directory account.

    • oidPasswd is the Oracle Internet Directory password.

    For example:

    serviceClass=oracle.webdb.provider.v2.adapter.soapV1.ProviderAdapter
    loaderClass=oracle.portal.provider.v2.http.DefaultProviderLoader
    showTestPage=true
    definition=providers/lab_provider/provider.xml
    autoReload=true
    oidManager=true
    oidAdminClass=oracle.portal.sample.v2.devguide.oid.UnsafeOidInfo
    oidHost=myhost.mydomain.com
    oidPort=oidPort
    oidUser=oidUser
    oidPasswd=oidPassword
    
    
  • oracle.portal.provider.v2.security.GroupSecurityManager manages which groups have access to your provider and its portlets. It retrieves this information from the provider definition file and is portlet specific. Each portlet in a provider may have different group settings. There is no limit on the number of groups that can be set using this tag, but, since the Web provider parses and validates each group in turn, listing many groups may degrade performance.

  • <group> is the tag in provider.xml that handles group management. It lists the groups allowed to access the portlet. The group information here follows the same case sensitivity as the Oracle Internet Directory.


    Note:

    The following example refers to your portal_instance_id, which is specific to your installation. To find your instance identifier, refer to your Oracle Internet Directory Administrator's Guide.

    <securityManager class="oracle.portal.provider.v2.security.
        GroupSecurityManager">
          <group>cn=DBA,cn=portal_instance_id,cn=groups,
                 dc=us,dc=oracle,dc=com</group>
    </securityManager>
    
    

The advantages of Oracle Internet Directory security are as follows:

  • Offers a simple, powerful way to secure your portlets.

  • Secures data within your portlets based on the user's group membership.

  • Creates users and groups directly from your portlets exposed as Web providers.

The disadvantages of Oracle Internet Directory security are as follows:

  • Slightly degrades performance when authorizing your portlet through Oracle Internet Directory. There is a cost associated with obtaining group information from any LDAP server, but this cost only happens the first time a user accesses a portlet in a session.

  • Requires provider access to Oracle Internet Directory.

  • Assumes all OracleAS Portal instances served by the provider use the same Oracle Internet Directory instance.

For more information on securing your providers using Oracle Internet Directory or to set up the sample portlets secured using Oracle Internet Directory, review the technical note, Installing the OID Portlets.

5.4.7.9.2 Viewing Your Portlets

To demonstrate the behavior of the security manager added to your Java portlet, follow these steps:

  1. Ensure you are logged in to an OracleAS Portal instance as a user who is a member of the group specified in the <group> tag in provider.xml.

  2. Use an existing page or create a new one, ensuring it is visible to PUBLIC.

  3. Add your Java portlet to the page.

  4. Make a note of the direct URL to your new page.

  5. Click Logout.

  6. Directly access the page by entering the URL noted in Step 4 in your browser's address bar or login to OracleAS Portal using a user that is not part of the group listed in provider.xml.

You will see the page created in Step 2 but not the portlet added in Step 3. When you added the portlet to the page, you were logged in as a user authorized to view the portlet. The PDK runtime detected this and allowed you to add the portlet. When you logged out and viewed the page, you were no longer part of the group allowed to view the portlet and hence the PDK Framework did not allow rendering of the portlet's contents.

Figure 5-44 Page and Portlets for Developer

Shows page for a developer.
Description of the illustration pdg_java_oid_dev.gif

If you log in again and view the page, you will see that the portlet is still there.

Figure 5-45 Page and Portlets for Developer/Administrator

Shows page for a developer/administrator.
Description of the illustration pdg_java_oid_dev_admin.gif

5.4.8 Controlling the Export/Import of Portlet Customizations

The export/import facility of OracleAS Portal is a multi-purpose tool for moving your portal objects, such as portlets, between instances of OracleAS Portal. For example, you might use export/import to move objects from a development environment to a stage environment and then, finally, to a production environment. You might also use export/import to move pages and page groups between OracleAS Portal instances, or to move Web providers from one machine to another. For more information about export/import in general, please refer to the Oracle Application Server Portal Configuration Guide.

Because portlet default settings can be set by the administrator and then changed by the user, they require some special consideration when you import and export them. To simplify the transport process, OracleAS Portal provides default functionality that handles administrator customization data (that is, data created through Edit Defaults mode) for you. When a portlet is exported, the default customization data stored using PDK-Java's PreferenceStore mechanism is exported with the portlet by default. Hence, when the portlet is imported into a target instance of OracleAS Portal, this data is imported along with it. As a result, the portlet instance's default settings are maintained when the portlet is moved from one portal instance to another.Foot 3 

The aforementioned behavior is provided to you as a convenience and it requires no action on your part to leverage. You might, however, want to exercise more granular control over the exportation of customization data than that provided by the default functionality. To implement your own requirements for export/import, you can make use of the programming interface to augment or override the default handling of customizations.

The export/import functionality for customizations requires that your OracleAS Portal instance and provider are on Release 10.1.2. Export/import of customizations behaves the same regardless of the location of your provider:

  • in the default Oracle Application Server Containers for J2EE of the Oracle Application Server, where the OracleAS Portal instance is different.

  • in a separate Oracle Application Server Containers for J2EE, where the OracleAS Portal instance may be different, and the provider is the same but is not registered on the target OracleAS Portal instance.

5.4.8.1 Import/Export Programming Interface

The PDK-Java's preference store mechanism allows data to be persisted by any number of application entities. The following three entities are the ones that persist data for the purposes of export/import:

  1. The portlet instance is the portlet on a page with the default customizations made to it by the administrator. The API for the portlet instance is:

    • oracle.portal.provider.v2.PortletInstance

      • exportData

        public byte[] exportData
            (
                boolean exportUsers,
                String[] userNames,
                TransportLogger logger
            )    throws PortletException
        
        
      • importData

        public void importData
            (
                byte[] data,
                TransportLogger logger
            )
            throws PortletException
        
        
  2. The portlet definition is the base portlet without any customizations applied to it. You might think of the portlet definition as the version of the portlet that exists in the Portlet Repository before it is placed on a particular page for use. The API for the portlet definition is:

    • oracle.portal.provider.v2.PortletDefinition

      • exportData

        public byte[] exportData
            (
                ProviderInstance pi,
                boolean exportUsers,
                String[] userNames,
                TransportLogger logger  
            )
            throws PortletException
        
        
      • importData

        public void importData
            (
                ProviderInstance pi,
                byte[] data,
                TransportLogger logger
            )
            throws PortletException
        
        
  3. The provider instance is the entity that contains and communicates with a set of portlets. The API for the provider instance is:

    • oracle.portal.provider.v2.ProviderInstance

      • exportData

        public byte[] exportData
            (
                boolean exportUsers,
                String[] userNames,
                TransportLogger logger
            )
            throws ProviderException
        
        
      • importData

        public void importData
            (
                byte[] data,
                TransportLogger logger
            )
            throws ProviderException
        
        

By default, each of the above entities employs an instance of oracle.portal.provider.v2.transport.PrefStoreTransporter to transform the data from an oracle.portal.provider.v2.preference.PreferenceStore to a byte array for transport. For the default export/import behavior, though, only the portlet instance entity's customization data is exported and imported. If you have persisted data at the portlet definition or provider instance level, you may want to export that data as well. For example, a billing handle that you persisted at the ProviderInstance level may need to be exported.

To change the behavior of PrefStoreTransporter, you can override its default implementation. The example in Section 5.4.8.3.7, "Exporting by Reference Example" illustrates how you can override PrefStoreTransporter.

5.4.8.1.1 Logging Interface

To simplify troubleshooting of your export/import transactions, you can send messages to both the calling OracleAS Portal instance and the Web provider log. PDK-Java provides a transport logging class that enables you to add events to the log during export and import operations. In this way, you can better keep track of events that occur during the transport of portlet customizations. The log can be a valuable troubleshooting tool if you encounter unexpected behavior in your portlets during or after transport. For example, you can log events when incompatibilities between PDK-Java versions are found.

You log events using the logger object, an instance of the oracle.portal.provider.v2.transport.TransportLogger class provided for each of the methods mentioned above. You log events with the calling portal through the instance provided for each method. You record events in the Web provider log with the normal logging mechanism, oracle.portal.log.LogManager. The log levels for export/import are as follows:

  • TransportLogger.SEVERITY_INFO

  • TransportLogger.SEVERITY_WARNING

  • TransportLogger.SEVERITY_ERROR

5.4.8.2 Exporting Customizations Example

This example illustrates the most basic case where you build a portlet and accept the default behavior for the export of customizations. In the examples in Section 5.4.8.3.6, "Encrypting Customization Data Example" and Section 5.4.8.3.7, "Exporting by Reference Example", you will see how to enhance the security of your customizations during export and import. To implement the more basic form of exporting customizations, do the following:

  1. Create a stock portlet and implement the Show mode with the following MyStockPortletShowRenderer.java class. Note that this class does not incorporate any special code to enable export/import.

    package oracle.portal.sample.v2.devguide.tx;
    import java.util.StringTokenizer;
    import oracle.portal.provider.v2.PortletException;
    import oracle.portal.provider.v2.personalize.NameValuePersonalizationObject;
    import oracle.portal.provider.v2.render.PortletRenderRequest;
    import oracle.portal.provider.v2.render.PortletRendererUtil;
    import oracle.portal.provider.v2.render.http.BaseManagedRenderer;
    import java.io.PrintWriter;
    import oracle.portal.sample.v2.devguide.webservices.
        NetXmethodsServicesStockquoteStockQuoteServiceStub;
    public class MyStockPortletShowRenderer extends BaseManagedRenderer
    {
        private String pid = null;
        private String userdata;
        private String stockList;
        private String stockCode;
      public void renderBody(PortletRenderRequest request) throws PortletException
      {
        // Use the PrintWriter from the PortletRenderRequest
        PrintWriter out = null;
        NetXmethodsServicesStockquoteStockQuoteServiceStub ns = new
          NetXmethodsServicesStockquoteStockQuoteServiceStub();
        try
        {
          out = request.getWriter();      NameValuePersonalizationObject data = null;
          data = (NameValuePersonalizationObject)PortletRendererUtil.
             getEditDefaultData(request);
          stockList= data.getString("stock");
          if(stockList!=null) {
            StringTokenizer st = new  StringTokenizer(stockList,",");   
            out.println("<table border='0'>");
            out.println("<thead>");
            out.println("<tr>");
            out.println("<th width='20%'>");
            out.println("<p align='left'> Stock Code</p></th><th width='20%'>");
            out.println("<p align='left'> Quote</p>");
            out.println("</th>");
            out.println("</tr>");
            out.println("<thead>");
                while(st.hasMoreElements()) {    
                  stockCode= st.nextElement().toString();
                  out.println("<tr>");
                  out.println("<td width='20%'>");
                  out.println("<p align='left'>"+  stockCode + 
                     "</p></td><td width='20%'>");
                  out.println(ns.getQuote(stockCode));
                  out.println("</td>");
                  out.println("</tr>");
                }
            out.println("</table>");
          }
          else
          {
            out.println("<br> Click <b>Edit Defaults</b> to define stock codes.");     
          }
        }
        catch(Exception ioe)
        {
          throw new PortletException(ioe);
        }         
      }
    }
    
    
  2. Implement the Edit Defaults mode for your stock portlet with the following class, MyStockPortletEditDefaultsRenderer.java. This class enables the administrator to make and store default customizations, which are then exported according to the default behavior.

    package oracle.portal.sample.v2.devguide.tx;
    import oracle.portal.provider.v2.PortletException;
    import oracle.portal.provider.v2.http.HttpCommonConstants;
    import oracle.portal.provider.v2.render.PortletRenderRequest;
    import oracle.portal.provider.v2.render.http.BaseManagedRenderer;
    import oracle.portal.provider.v2.render.PortletRendererUtil;
    import oracle.portal.provider.v2.personalize.NameValuePersonalizationObject;
    import java.io.PrintWriter;
    import java.io.IOException;
    import oracle.portal.provider.v2.render.http.HttpPortletRendererUtil;
    public class MyStockPortletEditDefaultsRenderer extends BaseManagedRenderer 
    {
      public void renderBody(PortletRenderRequest request) throws PortletException
      {
        PrintWriter out = null;
        try
        {
          out = request.getWriter();
        }
        catch(IOException ioe)
        {
          throw new PortletException(ioe);
        }
        
        // Customize the portlet title and stock
        String actionParam = PortletRendererUtil.getEditFormParameter(request);
        PortletRenderRequest prr = (PortletRenderRequest)
            request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
        String action = request.getParameter(actionParam);
        String title = prr.getQualifiedParameter("myportlet_title");
        String stock = prr.getQualifiedParameter("myportlet_stock");
        NameValuePersonalizationObject data = null;
        try
        {
          data = (NameValuePersonalizationObject)
                  PortletRendererUtil.getEditDefaultData(request);
        }
        catch(IOException io)
        {
          throw new PortletException(io);
        }
        // Cancel automatically redirects to the page, so
        // will only recieve OK or APPLY
        if (action != null)
        {
          data.setPortletTitle(title);
          data.putString("stock",stock);
          try
          {
            PortletRendererUtil.submitEditData(request, data);
          }
          catch(IOException ioe)
          {
            throw new PortletException(ioe);
          }
          return;
        }
        // Otherwise just render the form
        title = data.getPortletTitle();
        stock = data.getString("stock");
        out.print("<table border='0'> <tr> ");
        out.println("<td width='20%'> <p align='right'>Title:</p></td>
                     <td width='80%'>");
        out.print("<input type='TEXT' name='" + 
                   HttpPortletRendererUtil.portletParameter(prr, "myportlet_title")
                   + "' value='" + title + "'>");
        out.println("</td> </tr>");  
        out.print("<tr> <td width='20%'> <p align='right'>Stock Codes:</p></td>
                   <td width='80%'>");
        out.print("<input type='TEXT' name='" + 
                   HttpPortletRendererUtil.portletParameter(prr, "myportlet_stock")
                   + "' value='" + stock + "'>");
        out.println("<br> For example use US Stock Codes separated by comma: 
                     <i> SUNW,IBM,ORCL</i>");
        out.print("</td> </tr>");
        out.println("</table>");
      }
    }
    
    
  3. Create the following class, NetXmethodsServicesStockquoteStockQuoteServiceStub.java, for your stock portlet:

    package oracle.portal.sample.v2.devguide.webservices;
    import oracle.soap.transport.http.OracleSOAPHTTPConnection;
    import org.apache.soap.encoding.SOAPMappingRegistry;
    import java.net.URL;
    import org.apache.soap.rpc.Call;
    import org.apache.soap.Constants;
    import java.util.Vector;
    import org.apache.soap.rpc.Parameter;
    import org.apache.soap.rpc.Response;
    import org.apache.soap.Fault;
    import org.apache.soap.SOAPException;
    import java.util.Properties;
    public class NetXmethodsServicesStockquoteStockQuoteServiceStub 
    {
      public NetXmethodsServicesStockquoteStockQuoteServiceStub()
      {
        m_httpConnection = new OracleSOAPHTTPConnection();
        m_smr = new SOAPMappingRegistry();
      }
      private String _endpoint = "http://64.124.140.30:9090/soap";
      public String getEndpoint()
      {
        return _endpoint;
      }
      public void setEndpoint(String endpoint)
      {
        _endpoint = endpoint;
      }
      private OracleSOAPHTTPConnection m_httpConnection = null;
      private SOAPMappingRegistry m_smr = null;
      public Float getQuote(String symbol) throws Exception
      {
        Float returnVal = null;
        URL endpointURL = new URL(_endpoint);
        Call call = new Call();
        call.setSOAPTransport(m_httpConnection);
        call.setTargetObjectURI("urn:xmethods-delayed-quotes");
        call.setMethodName("getQuote");
        call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
        Vector params = new Vector();
        params.addElement(new Parameter("symbol", String.class, symbol, null));
        call.setParams(params);
        call.setSOAPMappingRegistry(m_smr);
        Response response = call.invoke(endpointURL,
          "urn:xmethods-delayed-quotes#getQuote");
        if (!response.generatedFault())
        {
          Parameter result = response.getReturnValue();
          returnVal = (Float)result.getValue();
        }
        else
        {
          Fault fault = response.getFault();
          throw new SOAPException(fault.getFaultCode(), fault.getFaultString());
        }
        return returnVal;
      }
      public void setMaintainSession(boolean maintainSession)
      {
        m_httpConnection.setMaintainSession(maintainSession);
      }
      public boolean getMaintainSession()
      {
        return m_httpConnection.getMaintainSession();
      }
      public void setTransportProperties(Properties props)
      {
        m_httpConnection.setProperties(props);
      }
      public Properties getTransportProperties()
      {
        return m_httpConnection.getProperties();
      }
    }
    
    
  4. Create a Web provider through provider.xml for this portlet. Notice the use of the <preferenceStore> element to allow for the storing of customizations:

    <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>MyStockPortlet</name>
          <title>My Stock Portlet</title>
          <description>Simple Stock Portlet to show Export and Import 
                       feature of web providers</description>
          <timeout>80</timeout>
          <showEditToPublic>false</showEditToPublic>
          <hasAbout>false</hasAbout>
          <showEdit>false</showEdit>
          <hasHelp>false</hasHelp>
          <showEditDefault>true</showEditDefault>
          <showDetails>false</showDetails>
          <renderer class="oracle.portal.provider.v2.render.RenderManager">
             <renderContainer>true</renderContainer>
             <renderCustomize>true</renderCustomize>
             <autoRedirect>true</autoRedirect>
             <contentType>text/html</contentType>
             <showPage class="oracle.portal.sample.v2.
                              devguide.tx.MyStockPortletShowRenderer"/>
             <editDefaultsPage class="oracle.portal.sample.v2.devguide.tx.
                                      MyStockPortletEditDefaultsRenderer"/>
          </renderer>
          <personalizationManager class="oracle.portal.provider.v2.personalize.
                                         PrefStorePersonalizationManager">         <dataClass>oracle.portal.provider.v2.personalize.
                        NameValuePersonalizationObject
             </dataClass>
          </personalizationManager>
       </portlet>
    </provider>
    
    
  5. Register this export-enabled provider with the source OracleAS Portal instance. For more information about registering Web providers, refer to Section 5.4.2.5, "Registering and Viewing Your Portlet".


    Note:

    If the Web provider is running in a secured environment, remember to provide the proxy host and port while starting up Oracle Application Server Containers for J2EE. For example:
    java -Dhttp.proxyHost=www-proxy.us.oracle.com -Dhttp.proxyPort=80
         -jar oc4j.jar 
    

  6. Create two regions on a sample page and add My Stock Portlet to the first region. For information on creating regions and pages, refer to the Oracle Application Server Portal User's Guide.

  7. Edit the page and choose Edit Defaults for My Stock Portlet. Choose the stock codes SUNW,IBM,ORCL. For more information on how to edit defaults for a portlet on a page, refer to the Oracle Application Server Portal User's Guide.

  8. Add My Stock Portlet to a second region and again edit the defaults. for it Use a different stock code this time, MSFT.

  9. Export the page group containing this page. For instructions on how to export a page group, refer to Chapter 10, "Exporting and Importing Content," in the Oracle Application Server Portal Configuration Guide.

  10. Import the page group into a target OracleAS Portal instance. For instructions on how to import a page group, refer to Chapter 10, "Exporting and Importing Content," in the Oracle Application Server Portal Configuration Guide.

  11. View the page with My Stock Portlet in the target OracleAS Portal instance and ensure that the customizations were maintained.

5.4.8.3 Implementing Security for Export/Import

Transporting customizations can present a security concern if your portlet stores sensitive data and is not operating in a secured environment. At the provider and portlet level, OracleAS Portal provides several ways for you to secure the export and subsequent import of portlet customizations. To better secure portlets and providers for exportation and importation, you can take the following actions:

  • Securing Provider Communications. Using OracleAS Portal configuration options, you can secure the communications between providers and OracleAS Portal. This step in turn makes the export/import of portlets more secure.

  • Disabling Export/Import of Customizations. You can disable the export of all portlet customization data on a per Web application basis. This method provides the greatest security but only at a significant cost in functionality because it prevents administrators from retaining their default customizations when the portlet is moved.

  • Obfuscating Data for Transport (Automatic). By default, OracleAS Portal obfuscates but does not encrypt customization data before transporting it.

  • Encrypting Customization Data for Transport. You may want to encrypt customization data for transport if any of the following are true:

    • Your Web provider connection is not secured through HTTPS.

    • You want to ensure the data is secured during transit.

    • You want the data to remain secure while stored in the OracleAS Portal instance.

  • Exporting by Reference. Instead of including portlet customization data directly in the transport set, you can include it by reference in the transport set. Because the data itself is not present in the transport set, export by reference is the most secure way of transporting customizations.

5.4.8.3.1 Securing Provider Communications

If the security of exporting/importing portlets is of concern to you, you should configure OracleAS Portal to secure communications with your portlet providers. The chief mechanisms for securing provider communications in OracleAS Portal are:

  • Message authentication through a Hashed Message Authentication Code (HMAC) algorithm. For more information on message authentication for providers, refer to Section 6.1.7.8, "Message Authentication", in the Oracle Application Server Portal Configuration Guide.

  • HTTPS between providers and OracleAS Portal. For more information on HTTPS for provider communications, refer to Section 6.1.7.9, "HTTPS Communication", in the Oracle Application Server Portal Configuration Guide.


    Note:

    You cannot use certificates for the HTTPS communication with providers.

5.4.8.3.2 Disabling Export/Import of Customizations

The JNDI variable, oracle/portal/provider/global/transportEnabled, controls whether to allow the exportation and importation of customizations. If you set the variable to true, customizations are transported as part of export/import. If you set it to false, they are not transported. You can set JNDI variables for PDK-Java through Oracle Enterprise Manager 10g. If for some reason Oracle Enterprise Manager 10g is not available for the instance, you can set the values manually in orion-web.xml. For a full Oracle Application Server installation, this file is located in:

ORACLE_HOME/j2ee/OC4J_instance/application-deployments/jpdk\jpdk

For a standalone OC4J installation, this file is located in:

ORACLE_HOME/j2ee/home/application-deployments/jpdk/jpdk
5.4.8.3.3 Obfuscating Data for Transport (Automatic)

By default, customization data is encoded (Base64). This encoding ensures that data is obfuscated during transport. You do not need to take any actions to leverage Base64 encoding as it is provided by default. However, if you want greater security, you can encrypt the data. Refer to Section 5.4.8.3.4, "Encrypting Customization Data for Transport".

5.4.8.3.4 Encrypting Customization Data for Transport

By implementing the oracle.portal.provider.v2.security.CipherManager class for your provider, you can encrypt the customization data prior to exporting it. Upon import, the cipher manager is invoked again to decrypt the data. Refer to Section 5.4.8.3.6, "Encrypting Customization Data Example".


Note:

If you choose to encrypt your Web providers for export through the cipher manager, you must also devise your own key management strategy for the encryption algorithm.

5.4.8.3.5 Exporting by Reference

As mentioned previously, the default behavior for exportation of portlets is to include the actual customization data in the transport set. For a more secure transport, you can code your portlet such that the customizations are exported through pointer rather than by including the actual preference data. When the transport set is imported, the target OracleAS Portal instance sends the pointer back to the Web provider, which then has the opportunity to reassociate the actual data with the new portlet instance. Refer to Section 5.4.8.3.7, "Exporting by Reference Example".


Note:

When exporting across security zones, exporting by reference may not work effectively. In general, you should only employ export by reference when transporting within the same general security environment.

5.4.8.3.6 Encrypting Customization Data Example

To encrypt customization data in your Web provider, you need to create your own cipher manager and associate it with your portlet provider. This example provides a simple, insecure cipher manager for illustrative purposes only. To implement a secure implementation of the cipher manager for your production system, you would need to significantly extend this sample. Some of the issues you would need to consider for a production implementation are as follows:

  • Do not hold the key object in memory. Read it from a persistent store as necessary.

  • Use the provider's PreferenceStore API supported by a DBPreferenceStore to work in the clustered case.

  • On import, if the cipher manager instance obtained from provider.xml matches the class name returned in the SOAP message, that CipherManager instance is used to perform the decryption. Hence, the instance maintained in the portlet/provider definition may be configured using any applicable means (for example, tags in provider.xml or JNDI variable) and that configuration is reused on import.

To encrypt customization data in your Web provider, do the following:


Note:

The sample provided below is for illustrative purposes only. You would need to significantly enhance it for use in a production environment.

  1. Create a cipher manager class, InsecureCipherManager. This class would be used for encryption and decryption of customization data exported from or imported to a Web provider. A base64 encoded, hard coded secret key is used with the DES algorithm supplied by the default javax.crypto provider of the underlying Java Runtime Environment. As a result, this particular sample is insecure because the encoded key can be recovered by a malicious party simply by decompiling the byte code.


    Note:

    This sample makes use of the javax.crypto package, which is optional in Java 1.3 and must be installed manually. In Java 1.4, though, this package is present by default.

    package oracle.portal.sample.v2.devguide.tx;
    import java.io.IOException;
    import java.security.GeneralSecurityException;
    import javax.crypto.Cipher;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    import oracle.portal.provider.v2.ProviderException;
    import oracle.portal.provider.v2.security.CipherManager;
    import sun.misc.BASE64Decoder;
    public final class InsecureCipherManager implements CipherManager
    {
        /**
         * Base64 encoded external form of a javax.crypto.SecretKey which was
         * generated for the DES algorithm. This is completely insecure! Anyone
         * can decompile the bytecode and recostitue the key. A more secure
         * implementation would implement a key management policy in a
         * java.security.KeyStore.
         */
        private static final String sEncodedKey = "UTJds807Arw=";
        /**
         * Generated from the (insecure) encoded form in sEncodedKey.
         */
        private SecretKey mKey;
        /**
         * Transforms the input data to a more secure form, in a single operation,
         * using the DES cryptographic algorithm along with a statically defined
         * secret key.
         * @param toEncode the input data.
         * @return an encoded form of the input data.
         * @throws ProviderException if an error occurs during transform.
         */
        public final byte[] encode(byte[] toEncode) throws ProviderException
        {
            try
            {
                Cipher c = Cipher.getInstance("DES");
                c.init(Cipher.ENCRYPT_MODE, getSecretKey());
                return c.doFinal(toEncode);
            }
            catch (GeneralSecurityException gse)
            {
                throw new ProviderException(gse);
            }
            catch (IOException ioe)
            {
                throw new ProviderException(ioe);            
            }
        }
        /**
         * Transforms the input data to its original form, in a single operation,
         * using the DES cryptographic algorithm along with a statically defined
         * secret key.
         * @param toDecode the input data.
         * @return a decoded form of the input data.
         * @throws ProviderException if an error occurs during transform.
         */
        public final byte[] decode(byte[] toDecode) throws ProviderException
        {
            try
            {
                Cipher c = Cipher.getInstance("DES");
                c.init(Cipher.DECRYPT_MODE, getSecretKey());
                return c.doFinal(toDecode);
            }
            catch (GeneralSecurityException gse)
            {
                throw new ProviderException(gse);
            }
            catch (IOException ioe)
            {
                throw new ProviderException(ioe);            
            }
        }
        /**
         * Returns a <code>javax.crypto.SecretKey</code> deserialized from the
         * obuscated form in sEncodedKey. Note, this is highly insecure!!
         */
        private SecretKey getSecretKey()
            throws GeneralSecurityException, IOException
        {
            if (mKey == null)
            {
                DESKeySpec ks = new DESKeySpec((new BASE64Decoder()).decodeBuffer(
                    sEncodedKey));
                SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
                mKey = skf.generateSecret(ks);
            }
            return mKey;
        }
    }
    
    
  2. Modify your provider.xml to reference the cipher manager:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <?providerDefinition version="3.1"?>
    <provider class="oracle.portal.provider.v2.DefaultProviderDefinition">  
    <providerInstanceClass>net.mzyg.tx.TxProviderInstance</providerInstanceClass>
       <session>false</session>
       <passAllUrlParams>false</passAllUrlParams>
       <preferenceStore class="oracle.portal.provider.v2.
          preference.DBPreferenceStore">
          <name>prefStore1</name>
          <connection>java:comp/env/jdbc/PortletPrefs</connection>
       </preferenceStore>
    <cipherManager class="oracle.portal.sample.v2.devguide.tx.
       InsecureCipherManager"/>
    
5.4.8.3.7 Exporting by Reference Example

To export by reference rather than exporting the actual customization, do the following:

  1. Override the DefaultPortletInstance with the following ExportByRefDefaultPortletInstance:

    package oracle.portal.sample.v2.devguide.tx;
    import oracle.portal.provider.v2.DefaultPortletInstance;
    import oracle.portal.provider.v2.preference.PreferenceStore;
    import oracle.portal.provider.v2.transport.PrefStoreTransporter;
    public class ExportByRefDefaultPortletInstance extends DefaultPortletInstance
    {
      /**
       * Returns a {@link oracle.portal.provider.v2.transport.PrefStoreTransporter}
       * capable of carrying out transport operations such as export/import on
       * data applicable to {@link oracle.portal.provider.v2.PortletInstance} 
       * persisted in {@link oracle.portal.provider.v2.preference.PreferenceStore}.
       * This implementation returns an {@link ExportByRefPrefStoreTransporter}.
       * @param ps the {@link oracle.portal.provider.v2.preference.PreferenceStore}
       * containing the data to be transported.
       * @return a {@link oracle.portal.provider.v2.transport.PrefStoreTransporter}
       */
      protected PrefStoreTransporter getPrefStoreTransporter(PreferenceStore ps)
      {
          return new ExportByRefPrefStoreTransporter(ps);
      }
    }
    
    
  2. Create the ExportByRefPrefStoreTransporter class referenced in ExportByRefDefaultPortletInstance. This class implements an alternative preference store transporter that does not send preference data during the export operation. Instead, it writes the context path of the source preference to the stream. During the export, it reads the context path and uses that path to look up the preference data and copy it to the new instance. This method of exporting by reference assumes that the source and target providers have access to the same preference store. In fact, the best case for this example would be the situation where the source and target providers are the same.

    package oracle.portal.sample.v2.devguide.tx;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import oracle.portal.provider.v2.transport.PrefStoreTransporter;
    import oracle.portal.provider.v2.transport.TransportLogger;
    import oracle.portal.provider.v2.preference.Preference;
    import oracle.portal.provider.v2.preference.PreferenceStore;
    import oracle.portal.provider.v2.preference.PreferenceStoreException;
    public class ExportByRefPrefStoreTransporter extends PrefStoreTransporter 
    {
        public ExportByRefPrefStoreTransporter(PreferenceStore prefStore)
        {
            super(prefStore);
        }
       /**
         * Exports the context path of the supplied {@link
         * oracle.portal.provider.v2.preference.Preference} from the {@link
         * oracle.portal.provider.v2.preference.PreferenceStore}.
         * @param pref the source {@link
         * oracle.portal.provider.v2.preference.Preference}
         * @param out the <code>java.io.OutputStream</out> to which data will be
         * written.
         * @param logger
         */
       protected void exportPreference(Preference pref, OutputStream out,
            TransportLogger logger) throws PreferenceStoreException, IOException
        {
            // Get the context path of the preference we are exporting.
            String contextPath = pref.getContextPath();
            DataOutputStream dos = new DataOutputStream(out);
            // Write the context path in the export data. The import process
            // will use this context path to lookup this preference in the
            // preference store and copy it to the new context 
            dos.writeUTF(contextPath);
        }
        /**
         * Reads a context path from the stream and copies preference data
         * from that location into the {@link
         * oracle.portal.provider.v2.preference.PreferenceStore}.
         * @param pref the target {@link
         * oracle.portal.provider.v2.preference.Preference}
         * @param in the <code>java.io.InputStream</code> from which to read data.
         * @param logger
         */
        protected void importPreference(Preference pref, InputStream in,
            TransportLogger logger) throws PreferenceStoreException, IOException
        {
            // Read the context path to copy the value for this
            // preference from.
            DataInputStream dis = new DataInputStream(in);
            String contextPath = dis.readUTF();
            // Create preference object to copy from (identical to the 
            // target preference but with a different context path)
            Preference sourcePref = new Preference(contextPath, 
               pref.getName(), pref.getType(), (String)null);
            // Copy across the preference
            getPrefStore().copy(sourcePref, pref, true);
        }
    }
    
    
  3. Update provider.xml to include the following element for your portlet:

    <portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
    ...
    <portletInstanceClass>oracle.portal.sample.v2.devguide.tx.
         ExportByRefDefaultPortletInstance</portletInstanceClass>
    </portlet>
    

5.4.9 Enhancing Portlet Performance with Caching

In the previous sections of this chapter, you learned how to write fully-functional Java portlets using the PDK Framework. Once you complete 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. The overhead involved in retrieving data and generating the output for dynamic content can be significantly reduced by proxying requests through a local agent backed by a large, low-latency data store known as a cache. The cache agent responds to a request in one of two ways:

  • If a valid version of the requested content exists in the cache, the agent simply returns the existing cached copy, thus skipping the costly process of content retrieval and generation. This condition is called a cache hit.

  • If a valid version of the requested content does not exist in the cache, the agent forwards the request to its destination and awaits the return of the content. The agent returns the content to the requestor and stores a local copy in its cache for reuse if a subsequent request for the same content arises. This condition is called a cache miss.

Web providers generate dynamic content (that is, portlets) and they often reside remotely from the OracleAS Portal instance on which they are deployed. As such, caching might improve their performance. The architecture of OracleAS Portal lends itself well to caching, since all rendering requests originate from a single page assembling agent, known as the Parallel Page Engine (PPE), which resides on the middle tier. You can make the PPE cache the portlets rendered by your Web provider and reuse the cached copies to handle subsequent requests, minimizing the overhead your Web provider imposes on page assembly.

The Web provider can use any one of three different caching methods, depending upon which one is best suited to the application. The methods differ chiefly in how they determine whether content is still valid:

  1. Expiry-based Caching: When a provider receives a render request, it stamps its response with an expiry time. The rendered response remains in the cache and fills all subsequent requests for the same content until its expiry time passes. This caching scheme is perhaps the simplest and most performant because the test for cache validity requires very little overhead and does not involve any network round trips. Expiry-based caching suits applications where the content has a well-defined life span. For content with a less certain life span, however, expiry-based caching is less effective. Refer to Section 5.4.9.2, "Activating Caching" and Section 5.4.9.3, "Adding Expiry-Based Caching" for more information.

  2. Invalidation-based Caching: Invalidation-based caching works essentially the same way as expiry-based caching, except that the contents of the cache can expire or become invalid at any time. Invalidation of cache content is usually triggered by an event.

    For example, if you have a calendar portlet that shows your appointments for the day, the content for the portlet could be generated once, the first time you show the calendar for that day. The content remains cached until something happens to change your schedule for that day, such as the addition of an appointment, the deletion of an existing appointment, or a change of time for an appointment. Each of these change events can trigger an action in the calendar application. When such an event takes place, your calendar application can generate an invalidation request for any cached portlet content affected by the change. The next time you view a page containing your calendar portlet, the cache will not contain an entry. Your Web provider will be contacted to regenerate the new content with the modified schedule.

    This method is a very efficient way to cache content because the originator of the content (that is, your Web provider) is contacted only when new content needs to be generated, but you are not bound to a fixed regeneration schedule. Refer to Section 5.4.9.2, "Activating Caching" and Section 5.4.9.4, "Adding Invalidation Based Caching" for more information.

  3. Validation-based Caching: When a provider receives a render request, it stamps its response with a version identifier (or E Tag). The response goes into the cache, but, before the PPE can reuse the cached response, it must determine whether the cached version is still valid. It sends the provider a render request that includes the version identifier of the cached content. The provider determines whether the version identifier remains valid. If the version identifier is still valid, the provider immediately sends a lightweight response to the PPE without any content, which indicates the cached version can be used. Otherwise, the provider generates new content with a new version identifier, which replaces the previously cached version. In this form of caching, the PPE must always confirm with the provider whether the content is up to date. The validity of the cached copy is determined by some logic in the provider. The advantage of this approach is that the provider controls the use of the cached content rather than relying on a fixed period of time. Refer to Section 5.4.9.2, "Activating Caching" and Section 5.4.9.5, "Adding Validation-Based Caching" for more information.

5.4.9.1 Assumptions

  1. You have followed through and understood Section 5.4.2, "Building PDK-Java Portlets".

  2. You built a portlet using the wizard and successfully added it to a page.

5.4.9.2 Activating Caching

To use the caching features of OracleAS Portal in your Web providers, 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 providers, over HTTP.

Usually, your OracleAS Portal administrator takes care of the configuration details for caching.

For invalidation-based caching, you need to configure OracleAS Web Cache in front of the Web provider. Bear in mind that remote Web providers often do not have OracleAS Web Cache installed. For more information about OracleAS Web Cache, refer to the Oracle Application Server Web Cache Administrator's Guide.

Once you have installed and configured OracleAS Web Cache, ensure the following in the OracleAS Web Cache Manager:

  • Points to the host name and port of the Web provider.

  • Caching rules do not cause the caching of provider content. Content should be cached according to the surrogate control headers generated by the provider in its response.

5.4.9.3 Adding Expiry-Based Caching

Expiry-based caching is one of the simplest caching schemes to implement, and can be activated declaratively in your XML provider definition. You can set an expiry time for the output of any ManagedRenderer you utilize by setting its pageExpires property to the number of minutes you want the output to be cached for. For example, suppose we want portlet output to be cached for one minute.

  1. After you have used the Portlet Wizard to build a portlet as described in Section 5.4.2, "Building PDK-Java Portlets", edit the provider.xml file and set the pageExpires property tag of showPage to 1. This will set an expires entry of 1 minute for the portlet.

    By default the wizard generates a standard and compressed tag for showPage. You need to 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 1 minute. After the time has expired, the portlet displays the most current time and a new cache is set.

5.4.9.4 Adding Invalidation Based Caching

When using OracleAS Web Cache, requests for content are sent through HTTP and content is either returned from the cache or the HTTP request is forwarded to the originator of the content. When content is returned to OracleAS Web Cache, it is added to the cache before being returned to the requestor. Cache content is invalidated by sending invalidation requests directly to OracleAS Web Cache. PDK-Java uses the Java API for Web Cache (JAWC) to generate invalidation requests. This section describes how to configure OracleAS Web Cache and use the invalidation-based caching sample that comes with PDK-Java.

Not all requests sent to OracleAS Web Cache are cached. In order for the content to be cached, the content must include directives that tell OracleAS Web Cache to cache the content. Usually OracleAS Web Cache uses the URL associated with the request as the cache key, but you can specify additional keys by setting special HTTP headers, known as surrogate control headers, on the response.

To configure a Java portlet to use invalidation-based caching, you do the following:

  • Configure OracleAS Web Cache. Refer to Oracle Application Server Web Cache Administrator's Guide for more information.

  • Switch invalidation-based caching on at the provider servlet level.

  • Define the Invalidation Port.

  • Activate invalidation-based caching in the provider.xml file.

  • To have the portlet invalidate the cache, update the JSP code in your portlet to trigger an invalidation request.

5.4.9.4.1 Configuring the Provider Servlet

To enable invalidation-based caching, you must switch it on at the provider servlet level. The flag is set in an initialization parameter inside the PDK-Java Web application deployment descriptor, web.xml. For example:

<servlet-class>oracle.webdb.provider.v2.adapter.SOAPServlet</servlet-class>
    <init-param>
      <param-name>invalidation_caching</param-name>
      <param-value>true</param-value>
    </init-param>
</servlet>

If the flag is not defined here, then invalidation-based caching is switched off. The status of this flag can easily be checked by displaying the provider's test page. For example:

http://<provider_hostname>:<port>/jpdk/providers/webcache/MyWebPRovider

5.4.9.4.2 Defining the OracleAS Web Cache Invalidation Port

If you are using an Oracle Application Server installation type where PDK-Java was automatically pre-installed (for example, an OracleAS Portal and Wireless type installation), you should find that OracleAS Web Cache invalidation settings have already been preconfigured in MID_TIER_ORACLE_HOME/portal/conf/cache.xml. In this case, you can safely ignore the instructions in this section and proceed to Section 5.4.9.4.3, "Configuring the XML Provider Definition". Otherwise, you will need to configure the invalidation portlet for OracleAS Web Cache.

First, you need the username and password for the invalidation port(s) of the OracleAS Web Cache instance(s) associated with your application server. After you obtain those, use the provided oracle.webdb.provider.v2.cache.Obfuscate Java utility to convert the username and password into an obfuscated string of the format required by the JAWC API. In a default Oracle Application Server installation, the username for the invalidation port is usually invalidator and the password is usually the same as the application server administrator's password. For example, suppose you installed Oracle Application Server in D:\as904, with an invalidation port username of invalidator and a password of welcome. You would run the following command:


Note:

The command that follows assumes that pdkjava.jar is present in ORACLE_HOME/portal/jlib and jawc.jar is present in ORACLE_HOME/webcache/jlib, as required by the PDK-Java installation guide.

If you are using a standalone Oracle Application Server Containers for J2EE installation, you need to substitute in the path to the java executable an external Java 2 SDK installation.


D:\as904\jdk\bin\java -classpath D:\as904\portal\jlib\pdkjava.jar
  oracle.webdb.provider.v2.cache.Obfuscate invalidator:welcome

If successful, the command should print a hexadecimal string like the following:

0510198d5df8efd5779406342be2528aa0cccb179ea6b77baf49f019f5075a3a11

Now, use this information to create a JAWC configuration file, cache.xml, which specifies one or more OracleAS Web Cache instances and their invalidation ports. For example:

<?xml version="1.0"> 
<webcache> 
<invalidation
 host=cache.mycompany.com
 port=4001
authorization="0510198d5df8efd5779406342be2528aa0cccb179ea6b77baf49f019f5075a3a11"/>
</webcache>

You may have more than one OracleAS Web Cache defined, in which case the same invalidation request goes to each OracleAS Web Cache in the configuration file, for example:


Note:

The tag names connectionPool, invalidationConnection1, and invalidationConnection2 are user defined. A template file is supplied in the directory:
MID_TIER_ORACLE_HOME/j2ee/OC4Jinstance/applications/jpdk/jpdk/WEB-INF/
  providers/webcache

<?xml version="1.0"> 
<webcache>
<connectionPool>
<invalidationConnection1
  host=cache.mycompany.com
  port=4001
authorization="0510198d5df8efd5779406342be2528aa0cccb179ea6b77baf49f019f5075a3a11"/>
<invalidationConnection2
  host=cache.mycompany.com
  port=4002
authorization="0510198d5df8efd5779406342be2528aa0cccb179ea6b77baf49f019f5075a3a11"/>
</connectionPool>
</webcache>

JAWC finds this configuration file using the system property oracle.http.configfile. To set this system property for an Oracle Application Server Containers for J2EE instance within an Oracle Application Server installation, simply add an appropriate line to the oc4j.properties file for the particular instance in which PDK-Java is installed (for example, MID_TIER_ORACLE_HOME/j2ee/OC4Jinstance/config/oc4j.properties) and then restart that instance. For example:

oracle.http.configfile=fully_qualified_filename

If you are running Oracle Application Server Containers for J2EE standalone, you can specify the option in the command line you use to start it.

java -Doracle.http.configfile=<fully_qualified_filename> -jar oc4j.jar

Note:

Since the location of the cache configuration file is defined as a system property, only one cache may be defined per server instance. It is not possible to have two different Web Provider instances behind separate OracleAS Web Cache configurations.

5.4.9.4.3 Configuring the XML Provider Definition

Using a combination of tags in provider.xml, you can activate automatic invalidation-based caching for an entire portlet or some of its pages. To turn on automatic invalidation-based caching, you need to declare it as follows either at the level of individual pages or the renderer, to indicate that invalidation-based caching should be activated for all pages:

<useInvalidationCaching>true</useInvalidationCaching>

If your portlet supports customization (through the Edit or Edit Defaults modes), you may also want to declare <autoInvalidate>true</autoInvalidate> for your renderer. This declaration causes invalidation of all the cached content for the portlet when you click OK or Apply in Edit mode, thus causing new markup to be generated based on the customized settings.

The maximum time for holding the page in the cache is the minimum of the following:

  • Maximum expiry time from OracleAS Portal defined in the Cache tab of the Global Settings page.

  • Web Provider default (24 hours) if no maximum expiry time is specified by OracleAS Portal.

  • The time in minutes of the <pageExpires> tag, if present.

The following excerpt from provider.xml specifies that this portlet shall be cached for up to 5 minutes and shall be automatically invalidated upon customization:

<renderer class="oracle.portal.provider.v2.render.RenderManager">
 <contentType>text/html</contentType>
 <renderContainer>true</renderContainer>
 <autoRedirect>true</autoRedirect>
 <autoInvalidate>true</autoInvalidate>
 <showPage class="oracle.portal.provider.v2.render.http.ResourceRenderer">
  <resourcePath>/htdocs/invalidation/invalidation1.jsp</resourcePath>
  <useInvalidationCaching>true</useInvalidationCaching>
  <pageExpires>5</pageExpires>
 </showPage>
 <editPage class="oracle.portal.sample.v2.devguide.invalidation.
   InvalidationEditRenderer"/></renderer>

Note:

The pageExpires tag is also used for normal expiry based caching. These two forms of caching are mutually exclusive. Invalidation-based caching takes place in an OracleAS Web Cache instance located in the same place as the Web provider. Pages stored using expiry based caching are cached in the middle tier of OracleAS Portal.

5.4.9.4.4 Manually Invalidating the Cache

You may want the cached version of the portlet invalidated when a request is processed or information somewhere has been updated. In these cases, you may want to manually invalidate the cache.

The invalidation-based caching portlet sample included with PDK-Java contains a single portlet that displays the time the content was cached and a link to trigger an invalidation request. The first time a page request is made to the Web provider through the cache, the response is cached. Subsequent requests for the portlet content are fulfilled by returning content from OracleAS Web Cache. When you click the link at the bottom of the portlet an invalidation request is generated by the provider that removes the portlet from the cache. The next request for the portlet is forwarded to the provider and the provider generates a new portlet with the current time.

To perform invalidation calls to OracleAS Web Cache, first you need to have a handle to a ServletInvalidationContext object. You can get this handle by calling the static getServletInvalidationContext() method of the ServletInvalidationContextFactory class.

Once you have the handle, you need to specify the cache key. In the cache key, you need to specify whether you want to invalidate a particular portlet instance, all the instances of a portlet, or all the portlets managed by a provider. To perform this task, you use the methods of the ServletInvalidationContext class or the methods of its super class, InvalidationContext. This is where you can specify whether the portlet should be cached for this particular user (USER level). If there is no user specified in the cache key, then the cached content is returned to all users, which means you are using SYSTEM level caching.

In the sample code below, we are invalidating a portlet instance and calling the setFullProviderPath() and setPortletReference() methods. When the caching key is set, you call the invalidate() method on the InvalidationContext object that sends the invalidation message to OracleAS Web Cache.

ServletInvalidationContext inv = 
  ServletInvalidationContextFactory.getServletInvalidationContext();
inv.setFullProviderPath
  ((ServletPortletRenderRequest)pReq);
inv.setPortletReference
  (pReq.getPortletReference());
int num = inv.invalidate();

Review the Web cache sample provider for more information.

5.4.9.5 Adding Validation-Based Caching

Adding validation-based caching requires slightly more effort, but gives you explicit control over exactly which requests to your provider 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 need to 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(), you need to do the following:

  • Retrieve the cached version identifier set by the PPE 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, the appropriate header has to be set by calling the HttpPortletRendererUtil.useCachedVersion() method. It also instructs the RenderManager that it won't be 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 will be cached. It also indicates to the PPE 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, the portlet shows the new content. If the content has not changed, a cached version of the portlet is displayed.

5.4.10 Writing Multi-Lingual Portlets

This section shows you how to build a Java portlet that can be rendered in different languages. The language used in your portlet will depend upon on the language setting that has been chosen in the portal that is displaying it.

Once you have completed this section you will be able to write portlets that support as many or as few languages as you wish. You will also be able to convert your existing portlets to support multiple languages. Once a portlet is written to support multiple languages, it is easy to plug in new languages. The basic model for multi-lingual Java portlets is similar to the standard Java Internationalization model. If you already know about Java Internationalization, you should find this process very familiar.

5.4.10.1 Assumptions

  1. You have followed through and understood Section 5.4.2, "Building PDK-Java Portlets".

  2. You built a portlet using the wizard and successfully added it to a page.

5.4.10.2 Internationalizing Your Portlet

5.4.10.2.1 Providing Translations for Portlet Content

In Building PDK-Java Portlets, you created a portlet using the Java Portlet Wizard. The basic message created by the wizard is only available in one language and the text to be displayed is hard-coded in to the portlet's renderer class. To make your portlets available in multiple languages, you have to store such language dependent elements in their own resource bundles.

Creating Resource Bundles

For each language you want your portlet to be available in, you will need a resource bundle. You will also need to create a 'default' resource bundle that will be used when there is no resource bundle corresponding to the language setting chosen in the portal.

  • Create a Default Resource Bundle

    1. In Oracle JDeveloper, create a Java class called MyProviderBundle that extends ListResourceBundle from the java.util.package. The class should contain a multi-dimensional array of objects that holds key-value pairs representing each of the language dependent elements from your JSP show page. This implementation is demonstrated in the following code:

      package mypackage2;
      import java.util.ListResourceBundle;
      public class MyProviderBundle extends ListResourceBundle
      {
      public static String HELLO_MSG = "MyPortletHelloMessage";
      public static String INFO_MSG = "MyPortletInfoMessage";
      public Object[][] getContents()
      {
      return contents;
      }
      static private final Object[][] contents =
      {
      {HELLO_MSG, "Hello"},
      {INFO_MSG, "This is the show page of the portlet and it is being generated in the default language!"}
      };
      }
      
      
    2. Save MyProviderBundle.

  • Creating Resource Bundles for Other Supported Languages

    Now you must create a resource bundle class for each language you want your portlet to support. Each of these classes must be named the same as your default resource bundle class, but with a language code appended to the end. For example, if you want to support the French language, create a Java class named MyProviderBundle_fr. The language code fr is the same as the code that will be used by the locale object in the portal if the language setting is set to French (for more information on Locales, see the JavaDoc for java.util.Locale). When you change the language setting in OracleAS Portal, you change the value of the current locale object and therefore the locale object's language code. These language codes adhere to the ISO:639 codes for representation for names of languages.

    1. To create a French resource bundle, create a Java class named MyProviderBundle_fr, as described above.

    2. Using your default resource bundle as a template, replace the English language strings with their French equivalents. An example is given below:

      package mypackage2;
      
      import java.util.ListResourceBundle;
      public class MyProviderBundle_fr extends
      ListResourceBundle
      {
      public Object[][] getContents()
      {
      return contents;
      }
      static private final Object[][] contents =
      {
      {MyProviderBundle.HELLO_MSG, "Bonjour"},
      {MyProviderBundle.INFO_MSG, "Cette page est le 'show mode' de la portlet
          et est generee dans la langue par defaut."}
      };
      }
      
      
    3. Save MyProviderBundle_fr.

    4. Repeat steps 1 through 3 for every language that you wish to create a resource bundle for, updating the class name with the appropriate language code and the message strings with their equivalent in the appropriate language.

Updating Your Renderer

To make use of the resource bundles you just created, you need to edit the JSP show page and replace the hard-coded messages with references that will pickup the messages at run time from the resource bundle that corresponds most closely with the locale object of the portal.

  1. Open the JSP that represents your show page and change the following:

    <%@page contentType="text/html; charset=windows-1252"
       import="oracle.portal.provider.v2.render.PortletRenderRequest"
       import="oracle.portal.provider.v2.http.HttpCommonConstants"
       import="java.util.ResourceBundle"
    %>
    
    <%
     PortletRenderRequest pReq = (PortletRenderRequest)
       request.getAttribute(HttpCommonConstants.PORTLET_RENDER_REQUEST);
    
    <-- Get a resource bundle object for the current language. -->
    ResourceBundle b = ResourceBundle.getBundle("mypackage2.MyProviderBundle",pReq.getLocale());
    %>
    
    <--  Pull the message from the appropriate resource bundle. -->
    <P> <%= b.getString(mypackage2.MyProviderBundle.HELLO_MSG) %> 
       <%= pReq.getUser().getName() %>.</P>
    <P> <%= b.getString(mypackage2.MyProviderBundle.INFO_MSG) %></P>
    
    
  2. Save your JSP page.

Now you can refresh your portlet and view the changes.

To view the French greeting, you set the language in the Set Language portlet to French instead of English.

Notice that the text inside the portlet has changed, but the portlet title remains in the default language, English. You can also have the portlet set the appropriate portlet attributes (such as portlet name, portlet title, and portlet description) by pointing to a resource bundle from provider.xml.

5.4.10.2.2 Providing Translation for Portlet Attributes

In your provider's definition file, provider.xml, a number of attributes describing your portlet are defined such as the portlets name and description, these are used in places, for example in your portlet's title bar in Show mode and so should be translated, too. There are two different ways of providing these translations, which one you choose is up to you. Both of these methods are outlined below:

Method 1: Using Resource Bundles at the Provider Level

You can provide translations for your portlet attributes in your resource bundle(s), then specify that you want to use these resource bundles in provider.xml, specifying the keys you have used in your resource bundles. Using this method you can use the keys you want to, and as long as you use different keys for each corresponding attribute in your provider's various portlets you can have just one set of resource bundles that all of your provider's portlets can use.

  • Updating Your Resource Bundles

    1. Open your default resource bundle, MyProviderBundle.java.

    2. Add additional strings to your resource bundle that represent your portlet attributes and then add text for those strings:

      package mypackage2;
      
      import java.util.ListResourceBundle;
      public class MyProviderBundle extends ListResourceBundle
      {
      public static String HELLO_MSG = "MyPortletHelloMessage";
      public static String INFO_MSG = "MyPortletInfoMessage";
      public static String PORTLET_NAME = "FirstPortletName";
      public static String PORTLET_TITLE = "FirstPortletTitle";
      public static String PORTLET_SHORT_TITLE = "FirstPortletShortTitle";
      public static String PORTLET_DESCRIPTION = "FirstPortletDescription";
      public static String TIMEOUT_MESSAGE = "FirstPortletTimeoutMessage";
      
      public Object[][] getContents()
      {
      return contents;
      }
      static private final Object[][] contents =
      {
      {HELLO_MSG, "Hi"},
      {INFO_MSG, "This is the show page of the portlet and it is being generated
         in the default language!"},
      {PORTLET_NAME, "MyGlobalPortlet"},
      {PORTLET_TITLE, "My Global Portlet"},
      {PORTLET_SHORT_TITLE, "MyGlobalPortlet"},
      {PORTLET_DESCRIPTION, "My first ever Global portlet, using my
         MyPortletShowPage.jsp"},
      {TIMEOUT_MESSAGE, "Timed out waiting for MyGlobalPortlet"}
      };
      }
      
      
    3. Save MyProviderBundle.java.

    4. Open MyProviderBundle_fr.java. Change it so that it contains the French strings that match the strings declared in MyProviderBundle.

      package mypackage2;
      
      import java.util.ListResourceBundle;
      public class MyProviderBundle_fr extends ListResourceBundle
      {
      public Object[][] getContents()
      {
      return contents;
      }
      static private final Object[][] contents =
      {
      {MyProviderBundle.HELLO_MSG, "Bonjour"},
      {MyProviderBundle.INFO_MSG, "Cette page est le 'show mode' de la portlet
         et est generee en francais!"},
      {MyProviderBundle.PORTLET_NAME, "MaPremierePortlet"},
      {MyProviderBundle.PORTLET_TITLE, "Ma Portlet Multi-Langue"},
      {MyProviderBundle.PORTLET_SHORT_TITLE, "Ma Global Portlet"},
      {MyProviderBundle.PORTLET_DESCRIPTION, "Ma premiere portlet
         multi-langue, utilisant mon renderer"},
      {MyProviderBundle.TIMEOUT_MESSAGE, "Temps d'acces a la portlet 
         demandee expire"}
      };
      }
      
      
    5. Save MyProviderBundle_fr.java.

  • Updating provider.xml

    1. Open the XML provider definition file and update it to point to the resource bundle instead of using the hard-coded portlet attribute values.

      <portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
       <id>3</id>
       <resource>MyProviderBundle</resource>
       <nameKey>FirstPortletName</nameKey>
       <titleKey>FirstPortletTitle</titleKey>
       <ShortTitleKey>FirstPortletShortTitle</ShortTitleKey>
       <descriptionKey>FirstPortletDescription</descriptionKey>
       <timeout>10</timeout>
       <timeoutMessageKey>FirstPortletTimeoutMessage</timeoutMessageKey>
       <showEditToPublic>false</showEditToPublic>
       <hasAbout>true</hasAbout>
      

Method 2: Creating Resource Bundles at Portlet Level

PDK-Java defines a set of resource bundle keys that you can use for providing translations for your portlet attributes. Making use of these keys means that you don't have to specify the resource bundle keys in your provider.xml file, as we did in Method 1: Using Resource Bundles at the Provider Level. However, you do have to provide a separate set of resource bundles for each portlet in your provider as the keys you use for each portlet need to be the same, but their values will differ.

  • Updating Your Resource Bundles

    1. Open your default resource bundle, MyProviderBundle.java.

    2. Remove any changes you made from the previous section, and import oracle.portal.provider.v2.PortletConstants. You can then reference the following constants instead of the strings. You do not have to declare static strings when using PortletConstants:

      {PortletConstants.NAME, "MyGlobalPortlet"},
      {PortletConstants.TITLE, "My Global portlet"},
      {PortletConstants.SHORTTITLE, "MyGlobalPortlet"},
      {PortletConstants.DESCRIPTION, "My first ever Global portlet"},
      {PortletConstants.TIMEOUTMSG, "Timed out waiting for MyGlobalPortlet"}
      
      
    3. Save MyProviderBundle.java.

    4. Open MyProviderBundle_fr.java. Remove the portlet attributes added in the previous section, import oracle.portal.provider.v2.PortletConstants, and reference the constants instead of the strings.

      {PortletConstants.NAME, "MaPremierePortlet"},
      {PortletConstants.TITLE, "Ma Portlet Multi-Langue"},
      {PortletConstants.SHORTTITLE, "Ma Global Portlet"},
      {PortletConstants.DESCRIPTION, "Ma premiere portlet multi-langue,
         utilisant mon renderer"},
      {PortletConstants.TIMEOUTMSG, "Temps d'acces a la portlet demandee
         expire"}
      
      
    5. Save MyProviderBundle_fr.java.

  • Updating provider.xml

    1. In provider.xml, you need to use only one tag instead of one tag for each string as you did in Method 1: Using Resource Bundles at the Provider Level. Add the tag between the portlet id and the timeout number value.

      <resource>mypackage2.MyProviderBundle</resource>
      
      

    For more information on Java Internationalization see the Internationalization trail of the Java Tutorial.

5.4.10.3 Viewing the Portlet

Once you have updated your provider and deployed it to Oracle Application Server Containers for J2EE, refresh the provider and portal page containing your portlet. To see your resource bundles working, add the "Set Language" portlet to your page and try changing the language setting to French. Remember that the default resource bundle is English, and that selecting any other language that doesn't have a corresponding resource bundle will result in the portlet being displayed in English.

5.5 Building Struts Portlets with Oracle JDeveloper

This section describes the framework for building Struts portlets with Oracle JDeveloper for use in OracleAS Portal. You will learn how to build a Struts portlet from an existing application by adding the Struts Tag Library from the Oracle Application Server Portal Developer Kit (version 9.0.4.0.2 or higher) to Oracle JDeveloper, then use the Oracle PDK Java Portlet wizard to create the Java portlet itself.

5.5.1 OracleAS Portal and the Apache Struts Framework

This section discusses the use of the Apache Struts with OracleAS Portal. Struts is an implementation of the Model-View-Controller (MVC) design pattern.

5.5.1.1 Model View Controller Overview

Database applications undertake several distinct tasks:

  • Data access

  • Business logic implementation

  • User interface display

  • User interaction

  • Application (page) Flow

The MVC (Model View Controller) architecture provides a way of compartmentalizing these tasks, based on the premise that activities, such as data presentation, should be separate from data access. This architecture enables you to easily plug a data source to the application without having to rewrite the user interface. MVC allows the logical separation of an application into three distinct layers: the Model, the View, and the Controller.

The Model

The Model is the repository for the application data and business logic. One facet of the Model's purpose is to retrieve data from and persist data to the database. It is also responsible for exposing the data in such a way that the View can access it, and for implementing a business logic layer to validate and consume the data entered through the View. At the application level, the Model acts as the validation and abstraction layer between the user interface and the business data that is displayed. The database server itself is simply a persistence layer for the Model.

The View

The View is responsible for rendering the Model data using JSPs. The View code does not include a hardcoded application or navigation logic, but may contain some logic to carry out tasks like displaying conditional data based on a user role. When an end user executes an action within the HTML page that the View renders, an event is submitted to the Controller. The Controller then determines the next step.

The Controller

The Controller is the linchpin of the MVC pattern. Every user action carried out in the View is submitted through the Controller. The Controller then performs the next action, based on the content of the request from the browser.

The Controller can be driven in several different ways. For example, you can use URL arguments to route the requests to the correct code,. The MVC pattern itself determines the function of the Controller, not how it should work.

Benefits

The MVC architecture provides a clear and modular view of the application and its design. By separating the different components and roles of the application logic, it allows developers to design applications as a series of simple and different components: the Model, the View, and the Controller. This pattern should help to create applications that are easier to maintain and evolve. For example, once you create one view, you can easily create another view using the same business logic. Because of the ease and reusability, the MVC pattern is the most widely used pattern in the context of Web-based application development.

The following diagram shows how the MVC pattern applies to a conventional thin-client Web application:

5.5.1.2 Apache Struts Overview

The Apache Struts framework (http://struts.apache.org) is one of the most popular frameworks for building Web applications, and provides an architecture based on the JSP Model 2 approach of the MVC design paradigm. In the Model 2 approach, the end user requests are managed by a servlet that controls the flow, and uses components such as JavaBeans, EJBs, or ADF Business Components to access and manipulate the data. It then uses JSPs to render the application content in a Web browser. This model differs from JSP Model 1, where the JSPs managed the browser request and data access.

The Struts framework provides its own HTTP Servlet as a controller component. The Struts framework is driven by an XML configuration file that contains the page flow of the application. Struts does not provide the Model, but allows the developers to integrate it to any data access mechanism, for example EJBs, TopLink, ADF Business Components, or JDBC. The Struts View by default uses JavaServer Pages (JSP), including the Java Standard Tag Library (JSTL) and JavaServer Faces (JSF). Struts provides a set of JavaBeans and JSP tags to help you use the different components of the MVC.


Note:

For more information about JSTL and JSF, see the FAQ on the Apache Software Foundation Web site (http://jakarta.apache.org/struts/faqs/kickstart.html).

5.5.1.3 OracleAS Portal Integration with Struts

The Oracle Application Server Portal Developer Kit contains numerous examples and documents regarding the usage of the OracleAS Portal APIs, such as personalization and caching. The integration of the application flow and business logic is not part of the portlet APIs. By using the Struts framework, however, you can leverage the MVC architecture to create and publish applications within your enterprise portal.

5.5.1.3.1 Oracle Struts Portlet

To create a portlet using the Struts framework, or to generate a portlet from an existing Struts application, you must deploy all the components in the J2EE container. In the context of OracleAS Portal, the Struts application is called by the PPE, and not by the browser as compared to a standalone Struts application. When a request is made, Oracle Parallel Page Engine (PPE), calls the Struts portlet that then forwards the request to the Apache Struts Controller servlet.

Figure 5-49 Integrating Struts Applications with OracleAS Portal

Shows integration of struts with OracleAS Portal.
Description of the illustration pdg_java_struts3.gif

The following code shows a portion of the provider 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 tag defines the business logic that will be executed in the Show mode of the portlet. The showPage of the Struts portlet contains two important components:

  1. The renderer class (oracle.portal.provider.v2.render.http.StrutsRenderer), which receives the portlet request from the PPE and acts as a proxy to forward the request to the Struts Action Servlet.

  2. The defaultAction tag, which defines the Struts action that will be used by default when the portlet is called for the first time.

The Oracle Application Server Portal Developer Kit enables you to easily develop a view (Portal View) of your Struts application. This view enforces a consistent look and feel of your Struts portlet using Portal styles, and allows the end user to use the application within the portal.

To create a Struts portlet, you must use the OracleAS Portal JSP tags, which are extensions of the default Struts JSP tags. This development process is similar to that of creating a standalone Struts application. To learn how to build a Struts portlet, refer to Section 5.5.2.1, "Creating a Struts Portlet". Also, since the portlet and struts application must also be in the same Servlet Context, you must create a single Web application that contains both elements. To learn how to easily create this Web application in Oracle JDeveloper, refer to the next section, Section 5.5.2.1, "Creating a Struts Portlet".

5.5.1.4 Summary

Apache Struts has become the de facto standard for developing MVC-based J2EE applications, because it offers a clean and simple implementation of the MVC design paradigm. This framework enables you, as the portlet developer, to separate the different components of an application, and to leverage the Struts controller to easily publish an existing Struts application to OracleAS Portal without completely changing the existing business logic.

The Oracle Application Development Framework (ADF) can use the Struts action servlet as a controller, or use its own controller (the ADF Controller or ADFc). This framework enables you to use the same approach to build Struts portlets as well as ADF portlets.


Note:

For more information on the Oracle Application Server Portal Developer Kit, see Portal Center (http://portalcenter.oracle.com).

5.5.2 Creating a Struts Portlet

OracleAS PDK (version 9.0.4.0.2) introduced new 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. To learn more about the Apache Struts framework, refer to Section 5.5.1, "OracleAS Portal and the Apache Struts Framework".

The PDK-Java extensions described in this article are compliant to the 1.1 production version of the Apache Struts project. Oracle JDeveloper version 9.0.3.x contains by default the Apache Struts version 1.1b2 (1.1 Beta 2). If you want to use Oracle JDeveloper 9.0.3.x to build Struts applications and portlets, you must upgrade the Oracle JDeveloper Struts libraries to the production version of Struts. Apache Struts 1.1 production is embedded with Oracle JDeveloper 10g (9.0.4) and higher.

This section contains the following steps:

5.5.2.1 Creating a Struts Portlet

To publish a part of an existing Struts application as portlet, you must first create a new view that will serve as the Portal View of your application. This view will use existing objects (Actions, ActionForm, and so on) with a new mapping and new JavaServer Pages.

In this example, you will create a portlet that enables you to add a new entry to a Web Logger (Blog).

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>

5.5.2.1.1 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 will redirect 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.

5.5.2.1.2 Creating 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 be sure that the portlet:

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

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

  • Renders portal-aware links and forms. This is necessary to ensure that your Struts portlet renders its content inline, thus keeping your users within the context of the portal page by rendering the requested content within the same portlet container.

To achieve inline rendering in your Struts portlet, you must use OracleAS PDK tags:

<pdk-struts-html:form action="/portal/saveNewBlog.do">
...
...
</pdk-struts-html:form>

During the rendering of the portlet, one of the JSP tags (for example, the pdk-struts-html:form tag), submits the form to the Parallel Page Engine (PPE), which then sends the parameters to the Struts portlet. The Struts controller executes the logic behind these actions and returns the next JSP to the portlet within the portal page.

The PDK contains all the Struts tags, and extends all the tags that are related to URLs. The following is a list of the PDK extended tags:

  • form: creates an HTML form and embeds the portal page context in the form to ensure inline rendering

  • link and rewrite: create a link to the portal page, and are required for inline rendering

  • img: creates an absolute link that points to the Web provider. If you want to use this tag in the context of Internet Web sites that have firewalls, you must make sure the provider is directly accessible from the Internet. If it is not possible, you can deploy the images to the OracleAS Portal middle tier and use the Apache Struts image link to generate a relative link (relative to the portal, not to the application).


    Note:

    You can register the OracleAS 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.

5.5.2.1.3 Creating a Portlet

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

To create a portlet:

  1. In Oracle JDeveloper, open the OracleAS PDK Java Portlet Wizard.


    Note:

    For more information on opening the wizard, see Section 5.4.2.1, "Creating a Portlet and Provider".

  2. For the implementation style of the show page, select Java Class.

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

  4. For the class name, enter StrutsRenderer.

  5. The Java Portlet Wizard generates the skeleton of the portlet renderer class, StrutsRenderer, for you. Since 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 select the Erase from Disk option in the File menu of Oracle JDeveloper.

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

    At the provider level:

    • Enable session handling, because Struts applications use session management:

      <session>true</session>
      
      
    • Enable the passing of URL parameters, so that all parameters from any form submission can be passed to the Struts controller:

      <passAllUrlParams>true</passAllUrlParams>
      
      

    At the portlet level:

    • 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>
      
      
5.5.2.1.4 Extending the portlet to add Portal Business Logic

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

5.5.2.2 Registering the Provider

Now that your portlet is ready to be used by OracleAS Portal, you must make it accessible to OracleAS Portal by registering it. When your register your provider, make sure the session information is passed to your Struts portlet by specifying the provider login frequency as "Once per user session."

5.5.2.3 Summary

Oracle Application Server enables you to easily create Struts portlets using Oracle JDeveloper and publish existing Struts applications to OracleAS Portal. For more information on using the Oracle JDeveloper Java Portlet wizards, refer to the beginning of this chapter. For more information on using OracleAS Portal, refer to the Oracle Application Server Portal User's Guide and the OracleAS Portal Online Help.



Footnote Legend

Footnote 1: The Java Portlet Specification 1.0 arose from Java Specification Request 168 and the JSR168 Expert Group.
Footnote 2: The examples in this chapter typically use a port of 8888, which is the default port. Of course, you may choose to use different port numbers in your own installation.
Footnote 3: User customization data for OracleAS Portal objects is never exported. This restriction applies to portlets as well as other objects, such as pages.