6 Adding Portlets and Navigation Controls

In the Administration Console, all content is contained within portlets, so even the most minimal extension must define a portlet (and content for the portlet). You can add your portlet directly to the desktop, but if you want the portlet to display as a tab or subtab in the ContentBook, you must define books or pages to contain it. Your extension can also add a node to the NavTreePortlet, which enables users to navigate to your portlet directly from the desktop.

This section describes how to add portlets, UI controls, and NavTreePortlet nodes to the Administration Console.

Figure 6-1 illustrates the process. The steps in the process, and the results of each are described in Table 6-1. Subsequent sections detail each step in the process.

Figure 6-1 Adding Portlets and Navigation Controls Development Overview

Description of Figure 6-1 follows
Description of "Figure 6-1 Adding Portlets and Navigation Controls Development Overview"

Table 6-1 Model MBean Development Tasks and Results

Step Description Result

1. Define a Portlet.

Create an XML file to define a portlet that the portal framework can instantiate. A portlet definition includes instructions on which type of data to load: JSPs, Struts Actions, or Beehive Page Flows.

The portal's Look and Feel determines whether the portlet provides borders and minimize/maximize controls.

A .portlet XML file.

2. Define UI Controls (Optional).

If you want your portlet to display in a tab, subtab, or in some other location within ContentBook, create an XML file that defines a page or book.

A .book XML file.

3. Specify a Location for Displaying Portlets or UI Controls.

Create an XML file that describes whether you want your portal to display next to a labeled UI control or to replace the control.

A netuix-extension.xml file.

4. Add Nodes to the NavTreePortlet (Optional).

You can create a link from the NavTreePortlet to any book or page in your extension.

WebLogic Server provides default support for appending control names to the end of the existing navigation tree. If you want to insert nodes in specific locations, or if you want to create a node tree, you create your own Java classes that describe the node and node location.

Additional entries in the .book XML file.

Optionally, Java classes that give you more control over the node that you are adding.

5. Archive and deploy the extension.

See Chapter 9, "Archiving and Deploying Console Extensions."

A WAR file that contains your extension.


Define a Portlet

You define a portlet in an XML file. The portlet definition includes instructions on which type of data to load: JSPs, Struts Actions, or Beehive Page Flows. The following sections describe how to define a portlet:

For more information about portlet XML files, see the entry in Portal Support Schema Reference.

Define a JSP Portlet

To define a portlet that loads a JSP:

  1. Copy the code from Example 6-1 and paste it into a new text file in root-dir/portlets (see Create a Directory Tree for the Extension).

    Consider using the following naming convention:

    content-name.portlet 
    

    where content-name is the name of a JSP file that the portlet contains. For example, if the portlet contains a JSP file named monitorEJB.jsp, then name the portlet XML file monitorEJB.portlet.

  2. Replace the values in Example 6-1 as follows:

    • Label. Provide a unique identifier that the portal framework uses to identify this portlet.

    • (optional) Title. Provide a default title that this portlet displays if its title bar is visible. See Displaying a Title Bar for a Portlet.

    • URI. Specifies the absolute path and file name of the JSP that the portlet contains starting from the root of the extension.

    For example:

    /ext_jsp/monitorEJB.JSP 
    

You must precompile JSPs before deploying your extension.

Example 6-1 Template for a Portlet XML File that Loads a JSP File

<?xml version="1.0" encoding="UTF-8"?>
<portal:root xmlns:html="http://www.w3.org/1999/xhtml-netuix-modified/1.0.0"
   xmlns:portal="http://www.bea.com/servers/netuix/xsd/portal/support/1.0.0"
   xmlns:netuix="http://www.bea.com/servers/netuix/xsd/controls/netuix/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.bea.com/servers/netuix/xsd/portal/
      support/1.0.0 portal-support-1_0_0.xsd">
   <netuix:portlet definitionLabel="Label" title="Title" >
      <netuix:content>
         <netuix:jspContent contentUri="URI"/>
      </netuix:content>
   </netuix:portlet>
</portal:root>

Define a Struts Portlet

Instead of encapsulating your extension's business logic and navigation logic in JSP files, you can use the Apache Struts framework. See Create Struts Artifacts for Tables and Forms.

To create a portlet that loads (forwards to) a Struts Action:

  1. Copy the code from Example 6-2 and paste it into a new text file in root-dir/portlets (see Create a Directory Tree for the Extension).

    Consider using the following naming convention:

    action-name.portlet 
    

    where action-name is the name of the Struts Action to which the portlet forwards.

  2. Replace the values in Example 6-2 as follows:

    • Label. Provide a unique identifier that the portal framework uses to identify this portlet.

    • (optional) Title. Provide a default title that this portlet displays if its title bar is visible. See Displaying a Title Bar for a Portlet.

    • Struts-module. Specifies the Struts module that defines a Struts Action.

      You must create your own Struts module to define the Actions and ActionForms that your Administration Console extension uses; the default Struts module is reserved for Oracle Actions and ActionForms. Each module includes its own, uniquely named configuration file. For information about Struts modules, see the Apache Struts User Guide at http://struts.apache.org/struts-doc-1.2.x/userGuide/index.html.

      For example, if you specify "myModule" for Struts-module, the Struts controller servlet looks in the following location for the action:

      root-dir/WEB-INF/struts-auto-config-myModule.xml 
      
    • action-path. Specifies the path to a Struts Action that is defined in your Struts module.

    • refresh-action-path. Specifies the Action to invoke on subsequent requests for this portlet (for example, the user agent refreshes the document).

Note that this .portlet does not specify the name of a JSP. Instead, typically the Struts Action mapping forwards to a specific JSP upon successful operation.

Example 6-2 Template for a Portlet XML File that Forwards to a Struts Action

<?xml version="1.0" encoding="UTF-8"?>
<portal:root xmlns:html="http://www.w3.org/1999/xhtml-netuix-modified/1.0.0"
   xmlns:portal="http://www.bea.com/servers/netuix/xsd/portal/support/1.0.0"
   xmlns:netuix="http://www.bea.com/servers/netuix/xsd/controls/netuix/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.bea.com/servers/netuix/xsd/portal/
      support/1.0.0 portal-support-1_0_0.xsd">
   <netuix:portlet definitionLabel="Label" title="Title" >
     <netuix:strutsContent module="Struts-module"
          action="action-path"
          refreshAction="refresh-action-path"/>
   </netuix:portlet>
</portal:root>

Define a Page Flow Portlet

To define a portlet that loads a Beehive Page Flow:

  1. Copy the code from Example 6-3 and paste it into a new text file in root-dir/portlets (see Create a Directory Tree for the Extension).

    Consider using the following naming convention:

    pageFlow-name.portlet 
    

    where pageFlow-name is the name of the Page Flow that the portlet loads (forwards to). For example, if the portlet forwards to a Page Flow named myPageFlow.jpf, then name the portlet XML file myPageFlow.portlet.

  2. Replace the values in Example 6-3 as follows:

    • Label. Provide a unique identifier that the portal framework uses to identify this portlet.

    • (optional) Title. Provide a default title that this portlet displays if its title bar is visible. See Displaying a Title Bar for a Portlet.

    • URI. Specifies the absolute path and file name of the JPF file that defines the Page Flow. The URI must be absolute starting from the root-dir/WEB-INF/classes directory.

      For example, if your JPF file is root-dir/WEB-INF/classes/com/mycompany/extension/pageflows/myPageFlow.jpf, specify the following value

      /com/mycompany/extension/pageflows/myPageFlow.jpf

    • Action. Specifies the absolute path and file name of the JPF file that defines the Page Flow.

Example 6-3 Template for a Portlet XML File that Forwards to a Page Flow

<?xml version="1.0" encoding="UTF-8"?>
<portal:root xmlns:html="http://www.w3.org/1999/xhtml-netuix-modified/1.0.0"
   xmlns:portal="http://www.bea.com/servers/netuix/xsd/portal/support/1.0.0"
   xmlns:netuix="http://www.bea.com/servers/netuix/xsd/controls/netuix/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.bea.com/servers/netuix/xsd/portal/
      support/1.0.0 portal-support-1_0_0.xsd">
   <netuix:portlet definitionLabel="Label" title="Title" >
      <netuix:content>
          <netuix:pageflowContent
                 contentUri="URI"
                 action="Action"/>
                 refreshAction="refresh-Action"/>
      </netuix:content>
   </netuix:portlet>
</portal:root>

Displaying a Title Bar for a Portlet

If you plan to locate a portlet on the Administration Console desktop (within a placeholder on the "page" page), configure the portlet to display a title bar. If you locate a portlet in the ContentBook, do not display a title bar.

To display a title bar:

  1. In the portlet's .portlet XML file, provide a value for the title attribute of the netuix:portlet element. To display a localized value, see Localizing a Portlet Title.

  2. Include the following element as a child of the netuix:portlet element:

    <netuix:titlebar/> 
    

    To enable the portlet to be minimized and maximized, include the following stanza instead of the empty <netuix:titlebar/> element:

    <netuix:titlebar>
         <netuix:minimize/>
         <netuix:maximize/>
    </netuix:titlebar>
    

Example 6-4 defines a portlet that displays a title bar. The portlet can be minimized or maximized and the title value comes from a message bundle.

Example 6-4 Example: Portlet that Displays a Localized Title

<?xml version="1.0" encoding="UTF-8"?>
<portal:root xmlns:html="http://www.w3.org/1999/xhtml-netuix-modified/1.0.0"
   xmlns:portal="http://www.bea.com/servers/netuix/xsd/portal/support/1.0.0"
   xmlns:netuix="http://www.bea.com/servers/netuix/xsd/controls/netuix/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.bea.com/servers/netuix/xsd/portal/
      support/1.0.0 portal-support-1_0_0.xsd">
   <netuix:portlet definitionLabel="medrecEAR.Monitor.Portlet" 
       title="medrecMBean.myPortlet.title" 
       backingFile="com.bea.medrec.extension.utils.DesktopViewBacking">
      <netuix:titlebar>
          <netuix:minimize/>
          <netuix:maximize/>
      </netuix:titlebar>
      <netuix:content>
         <netuix:strutsContent module="/medrecMBean"
              action="RetrieveCustomMBeansAction"
               refreshAction="RetrieveCustomMBeansAction"/>
      </netuix:content>
   </netuix:portlet>
</portal:root>

Localizing a Portlet Title

By default, the portlet displays the literal value that you enter in the <netuix:portlet> element's title attribute. To enable this title to be localized:

  1. Create a Java class that retrieves the value of the title attribute, scans a property file for a key that matches the title attribute value, and returns the value of the property key.

    For example, if you specify title="myPortlet.title", the Java class looks through your message bundle for myPortlet.title=MyCompany's Portlet and returns MyCompany's Portlet as the text to be displayed.

    See Create a Backing Class for Localizing Portlet Titles.

  2. In the .portlet file, include the following attributes in the <netuix:portlet> element:

    • title. Specify the key for a property that you have defined in your message bundle.

    • backingFile. Specify the fully-qualified name of a Java class that you created in the previous step.

    For example:

    <netuix:portlet definitionLabel="myPortlet" title="myPortlet.title"
          backingFile="com.mycompany.extension.utils.MyPortletBacking"> 
    
Create a Backing Class for Localizing Portlet Titles

A backing class is a Java class that interacts directly with the portal framework APIs. To create a backing class that retrieves localized portlet titles:

  1. Extend com.bea.netuix.servlets.controls.content.backing.AbstractJspBacking.

  2. Implement the AbstractJspBacking.preRender(HttpServletRequest request, HttpServletResponse response) method.

    See AbstractJspBacking.preRender() in the Java API Reference for Oracle WebLogic Portal.

    In your implementation of this method:

    1. Get the locale from the HttpServletRequest object.

      Use the following API:

      javax.servlet.http.HttpServletRequest.getSession().getAttribute(
         "org.apache.struts.action.LOCALE") 
      
    2. Get the message bundle.

      Use the following API:

      org.apache.struts.util.MessageResources.getMessageResources(
          "myBundle"); 
      

      where myBundle is the name of your message bundle. (See Creating a Message Bundle.)

    3. Get the value of the portlet's title property.

      Use the following APIs:

      PortletBackingContext bctx =
           PortletBackingContext.getPortletBackingContext(
               HttpServletRequest req);
      MessageResources.getMessage(locale, bctx.getTitle()); 
      

      where locale is the locale that you retrieved from the HttpServletRequest object.

    4. Reset the value of the portlet's title property to the localized value that you retrieved in the previous step.

      Use the following API:

      PortletBackingContext.getTitle(String title) 
      

      where title is the value that you retrieved from the message bundle.

Example 6-5 Example: Backing Class for Localizing a Portlet Title

package com.bea.medrec.extension.utils;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.util.MessageResources;
import com.bea.netuix.servlets.controls.content.backing.AbstractJspBacking;
import com.bea.netuix.servlets.controls.portlet.backing.PortletBackingContext;
public class DesktopViewBacking extends AbstractJspBacking {
   public boolean preRender(HttpServletRequest req, HttpServletResponse res) {
      // Get the PortletBackingContext for current portlet. The 
      // PortletBackingContext contains properties and methods 
      // for the current portlet.
      PortletBackingContext bctx =
         PortletBackingContext.getPortletBackingContext(req);
      if (bctx != null) {
         // If title does not contain a period, assume it's preLocalized
         // or follow the format for a key
         if (bctx.getTitle().indexOf(".")!=-1){
            // Get the locale from the HTTPServletRequest
            Locale locale = (Locale) req.getSession().getAttribute(
               "org.apache.struts.action.LOCALE");
            // Find the message bundle named "medrecMBean"
            MessageResources messages =
               MessageResources.getMessageResources("medrecMBean");
            // Get the value of the portlet's "title" property
            String msg = messages.getMessage(locale, bctx.getTitle());
            // Reset the value of the "title" property with the
            // localized value.
            bctx.setTitle(msg);
         }
      }
      return true; 
   }
}

Define UI Controls (Optional)

If you want to add tabs or subtabs to the Administration Console, you must define a book or page UI control that conforms to the existing hierarchy:

  • To create a top-level tab (such as a sibling of Domains: Configuration), you create a book that contains one or more pages. Each page contains a portlet.

  • To create a subtab of an existing tab (such as a sibling of Domains: Configuration: General), you create a page that contains a portlet.

Save the definitions of your books and pages in one or more portal book (.book) files. Create one .book file for each hierarchical grouping of controls. For example, create one .book file for a book that creates a top-level tab and its subtabs. Create another .book file for a page that adds a subtab to an existing WebLogic Server tab. The root element of a.book file (portal:root) can have only one direct child element; the child element can have multiple children.

The following sections describe creating books and pages:

Create a Tab That Does Not Contain a Subtab

To create a portal book (.book) XML file that defines a tab and no subtabs (such as Domains: Notes):

  1. Copy the code from Example 6-6 and paste it into a new text file.

    For example, root-dir/controls/MyApp.book

    where root-dir is your development directory. For more information, see Chapter 3, "Setting Up a Development Environment."

  2. Replace the values in Example 6-6 as follows:

    • Page-Label. Provide a unique identifier that the portal framework and WebLogic Server JSP tags use to forward requests to the page.

    • Page-Title. Provide either the text that users see as the name of the tab or a key in a message bundle that you have created.

      If the value that you specify contains a "." (period), the Administration Console assumes that this value is a key and attempts to look up the value from your message bundle. For example, if you specify My.Tab, the Administration Console looks up the value of a property whose key is My.Tab. If it cannot find such a value, it displays null as the tab name. If you specify My Tab as the value, then the Administration Console displays My Tab.

    • Bundle. Specify the name of a message bundle that you have created. This bundle is used only if the value of the title attribute in the netuix:page element contains a ".". See Create and Use a Message Bundle in Your JSPs.

    • Portlet-Instance-Label. Provide a unique identifier that the portal framework and WebLogic Server JSP tags use to forward requests to the portlet instance.

    • Portlet-URI. Specify the path and file name of a portlet file that you created (see Define a Portlet). The path must be relative to the root of the portal Web application.

      For example:

      /portlets/monitorEJB.portlet 
      

Note that Example 6-6 defines a page, not a book, so the Administration Console Look and Feel will render the page as a tab with no subtabs.

Example 6-6 Template .book File that Creates a Tab with No Subtabs

<?xml version="1.0" encoding="UTF-8"?>
<portal:root
   xmlns:netuix="http://www.bea.com/servers/netuix/xsd/controls/netuix/1.0.0"
   xmlns:html="http://www.w3.org/1999/xhtml-netuix-modified/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:portal="http://www.bea.com/servers/netuix/xsd/portal/support/1.0.0"
   xsi:schemaLocation="http://www.bea.com/servers/netuix/xsd/portal/support
      /1.0.0 portal-support-1_0_0.xsd">
   <netuix:page markupName="page" markupType="Page"
      definitionLabel="Page-Label" title="Page-Title"
      skeletonUri="/framework/skeletons/default/wlsworkspace/
         page_content.jsp">
         <netuix:meta name="skeleton-resource-bundle" content="Bundle"/>
         <netuix:content>
            <netuix:gridLayout columns="1" markupType="Layout"
               markupName="singleColumnLayout">
            <netuix:placeholder flow="vertical" markupType="Placeholder"
               markupName="singleColumn_columnOne">
               <netuix:portletInstance markupType="Portlet"
                  instanceLabel="Portlet-Instance-Label"
                  contentUri="Portlet-URI"/>
            </netuix:placeholder>
         </netuix:gridLayout>
      </netuix:content>
   </netuix:page>
</portal:root>

Create a Tab That Contains Subtabs

To create a portal book (.book) XML file that defines a tab and one or more subtabs:

  1. Copy the code from Example 6-7 and paste it into a new text file. Save the file in a directory below root-dir.

    For example, root-dir/controls//MyApp.book

    where root-dir is your development directory. For more information, see Chapter 3, "Setting Up a Development Environment."

  2. To define the tab, replace the values in Example 6-7 as follows:

    • Book-Label. Provide a unique identifier that the portal framework and WebLogic Server JSP tags use to forward requests to the book. This is the same type of label that WebLogic Server provides for many of its UI controls. See Extension Points in the Administration Console.

    • Book-Title. Provide either the text that users see as the name of the tab or a key in a message bundle that you have created.

      If the value that you specify contains a "." (period), the Administration Console assumes that this value is a key and attempts to look up the value from your message bundle. For example, if you specify My.Tab, the Administration Console looks up the value of a property whose key is My.Tab. If it cannot find such a value, it displays null as the tab name. If you specify My Tab as the value, then the Administration Console displays My Tab.

  3. To define the first subtab, replace the values in Example 6-7 as follows:

    • Page-Label. Provide a unique identifier that the portal framework and WebLogic Server JSP tags use to forward requests to the page.

    • Page-Title. Provide either the text that users see as the name of the subtab or a key in a message bundle that you have created.

      If the value that you specify contains a "." (period), the Administration Console assumes that this value is a key and attempts to look up the value from your message bundle.

    • (optional) Metadata-Type and Metadata-ID. If you want to use the Administration Console's <wl:column-dispatch> JSP tag to create a hypertext link that forwards to this page, include a <netuix:meta> element and supply values for Metadata-Type and Metadata-ID. See Create a Table Column for Navigating to Other Pages.

    • Portlet-Instance-Label. Provide a unique identifier that the portal framework and WebLogic Server JSP tags use to forward requests to the portlet instance.

    • Portlet-URI. Specify the path and file name of a portlet file that you created (see Define a Portlet). The path must be relative to the root of the portal Web application.

    For example:

    /portlets/monitorEJB.portlet 
    
  4. To create additional subtabs, add netuix:page elements as siblings to the netuix:page element in Example 6-7.

For more information about portal book XML files, see the Portal Support Schema Reference.

Note the use of the following elements in the .book file:

  • netuix:singleLevelMenu renders one subtab for each page in the book. The book's parent UI control (which Example 6-7 assumes is provided by WebLogic Server) is responsible for generating a top-level tab for the book.

  • netuix:meta name="breadcrumb-context" content="handle" adds the page's title to the history of visited pages (breadcrumbs) after a user has visited the page. The breadcrumbs display on the desktop above ContentBook.

Example 6-7 Template for a .book File That Defines a Top-Level Tab with Subtabs

<?xml version="1.0" encoding="UTF-8"?>
<portal:root
   xmlns:netuix="http://www.bea.com/servers/netuix/xsd/controls/netuix/1.0.0"
   xmlns:html="http://www.w3.org/1999/xhtml-netuix-modified/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:portal="http://www.bea.com/servers/netuix/xsd/portal/support/1.0.0"
   xsi:schemaLocation="http://www.bea.com/servers/netuix/xsd/portal/support
      /1.0.0 portal-support-1_0_0.xsd">
   <netuix:book markupName="book" markupType="Book"
      definitionLabel="Book-Label" title="Book-Title">
      <netuix:singleLevelMenu markupType="Menu" markupName="singleLevelMenu"
         skeletonUri="singlelevelmenu_children.jsp"/>
      <netuix:meta name="skeleton-resource-bundle" content="Bundle"/>
      <netuix:content>
         <netuix:page markupName="page" markupType="Page"
            definitionLabel="Page-Label" title="Page-Title"
            skeletonUri="/framework/skeletons/default/wlsworkspace/
               page_content.jsp">
            <netuix:meta name="Metadata-Type" content="Metadata-ID"/>
            <netuix:meta name="breadcrumb-context" content="handle"/>
            <netuix:meta name="skeleton-resource-bundle" content="Bundle"/>
            <netuix:content>
               <netuix:gridLayout columns="1" markupType="Layout"
                  markupName="singleColumnLayout">
                  <netuix:placeholder flow="vertical" markupType="Placeholder"
                     markupName="singleColumn_columnOne">
                     <netuix:portletInstance markupType="Portlet"
                        instanceLabel="Portlet-Instance-Label"
                        contentUri="Portlet-URI"/>
                  </netuix:placeholder>
               </netuix:gridLayout>
            </netuix:content>
         </netuix:page>
         <!-- Add additional netuix:page elements here -->
      </netuix:content>
   </netuix:book>
</portal:root>

Create a Subtab

To create a subtab that you can add to an existing WebLogic Server tab:

  1. Create a .book file that defines a page UI control. See Example 6-6.

  2. In your netuix-extension.xml file, specify the WebLogic Server book UI control that you want to contain your subtab. See Add a Tab or Subtab to ContentBook.

Create a Control Without Tabs or Subtabs

There is no requirement for books and pages in ContentBook to be accessible by tab or subtab. Many WebLogic Server pages that display summary tables are accessible from the NavTreePortlet but not from the tabbed interface (see Figure 2-5).

Any of the code listings in the previous sections can be located in a parent control that does not render tabs or subtabs for its children. See Specify a Location for Displaying Portlets or UI Controls.

Specify a Location for Displaying Portlets or UI Controls

All locations for displaying your portlets or UI controls must be specified as relative to existing controls in the Administration Console. For example, you can specify that your portlet displays on the desktop below the System Status portlet.

To specify a location for displaying a portlet or UI control:

  1. Create an XML file named netuix-extension.xml and save it in

  2. root-dir/WEB-INF

  3. where root-dir is your development directory. For more information, see Chapter 3, "Setting Up a Development Environment."

    A NetUI Extension XML file (netuix-extension.xml) is the deployment descriptor for your extension. It declares each parent UI control in your extension and the location in which you want it to display (see Example 6-8). For more information, see the NetUI Extensions Schema Reference.

  4. Create a <weblogic-portal-extension> root element.

  5. (Optional) Create a <provider-info> element to describe your extension.

    This element is for your information only. The portal framework does not use the data in this element.

  6. Add the following element:

  7. <portal-file>/console.portal</portal-file>

    This required element specifies the name and relative location of the Administration Console's .portal file, which is the portal that you are extending.

  8. Do one of the following:

Add a Portlet to the Desktop

To add a portlet to the Administration Console desktop, create the following stanza in your netuix-extension.xml file (see Example 6-8):

<page-extension>
   <page-location>
      <parent-label-location label="page"/>
      <page-insertion-point layout-location="layout"
         placeholder-position="0"/>
   </page-location>
   <portlet-content
      content-uri="portlet-URI" title="title"
      orientation="top" default-minimized="false"
      instance-label="portlet-instance-label"/>
</page-extension> 

where:

  • layout is one of the following values:

    • 0 (zero) if you want the portlet to display in the left side of the Administration Console.

      Extension portlets always display at the top of the left column.

    • 1 (one) if you want the portlet to display in the right side.

      Extension portlets always display at the bottom of the right column.

  • portlet-URI is the path and file name of your .portlet file. The path must be relative to the root of the portal Web application.

  • title is the title that displays in the portlet's title bar. If you specify a null value, the portal framework uses the title that you defined in the .portlet file.

  • portlet-instance-label is a unique identifier that the portal framework and WebLogic Server JSP tags use to forward requests to the portlet instance.

Add a Tab or Subtab to ContentBook

To add a control that renders a tab, create the following stanza in your netuix-extension.xml file (see Example 6-8):

<book-extension> 
   <book-location>
      <parent-label-location label="Admin-Console-Book-Label"/>
      <book-insertion-point action="append"/>
   </book-location> 
   <book-content content-uri="book-URI"/>
</book-extension> 

where:

  • Admin-Console-Book-Label is the definitionLabel of an Administration Console book control that renders tabs for its child books.

  • book-URI is the path and file name of your .book file that defines the book control for your tab (and optional subtabs). The path must be relative to the root of the portal Web application.

To add a control that renders a subtab in an existing tab, create the same stanza as the previous step, where:

  • Admin-Console-Book-Label is the definitionLabel of an Administration Console book control that renders subtabs for its child pages.

  • book-URI is the path and file name of your .book file that defines the page control for your subtab. The path must be relative to the root of the portal Web application.

Example: Specifying Locations for Portlets and UI Controls

Example 6-8 is a netuix-extension.xml file that adds a tab to the WebLogic Sever Domain tabs, a subtab to the Domain: Configuration tab, and a portlet to the console desktop.

Example 6-8 Example netuix-extension.xml File

<?xml version="1.0" encoding="UTF-8"?>
<weblogic-portal-extension
   xmlns="http://www.bea.com/servers/portal/weblogic-portal/8.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.bea.com/servers/portal/weblogic-portal/
      8.0 netuix-extension-1_0_0.xsd">
   <provider-info>
      <title>My Extension</title>
      <version>1.0</version>
      <description>Inserts a portlet on the desktop, a tab next to
           Domains:Configuration, and a subtab under Domains: Configuration.
      </description>
      <author>Me</author>
      <last-modified>02/03/2005</last-modified>
      <support-url>http://www.mycompany/support/index.jsp</support-url>
   </provider-info>
   <portal-file>/console.portal</portal-file>
   <!--Adds a tab to the Domain tabs -->
   <book-extension> 
      <book-location>
         <parent-label-location label="CoreDomainConfigGeneralBook"/> 
         <book-insertion-point action="append"/>
      </book-location> 
      <book-content content-uri="/controls/page.book"/>
   </book-extension>
<!-- Adds a subtab to the Domain: Configuration tab-->
   <book-extension>
      <book-location>
         <parent-label-location label="DomainconfigTabPage"/> 
         <book-insertion-point action="append"/>
      </book-location> 
      <page-content content-uri="/controls/notespage.book"/>
   </book-extension>
   <!--Adds a portlet to the console desktop -->
   <page-extension>
      <page-location>
         <parent-label-location label="page"/>
         <page-insertion-point layout-location="0" placeholder-position="0"/>
      </page-location>
      <portlet-content content-uri="/portlets/desktop/desktop_view.portlet"
         title="My App Status" orientation="top" default-minimized="false"
          instance-label="PortletExtensionInstanceLabel"
      />
   </page-extension>
</weblogic-portal-extension>

Add Nodes to the NavTreePortlet (Optional)

The Domain Structure portlet (NavTreePortlet) contains a tree control that you can use to navigate to content in the Administration Console. Each node in the tree is a link to a UI page control. Nodes can also contain subnodes.

Your extension can add a single node at any location in the tree. It can also add a node that contains other nodes (node tree) at any location. For example, your extension can add a node or a node tree to the root of the existing navigation tree. In addition (or instead), it can add a node or node tree to the Environments node. (See Figure 6-2.)

Figure 6-2 Example: Adding Nodes or Node Trees

Description of Figure 6-2 follows
Description of "Figure 6-2 Example: Adding Nodes or Node Trees"

The following sections describe adding nodes to the NavTreePortlet:

Append a Single Node to the Root of the Existing Tree

To append a node that links to one of your page controls, add the following attribute and attribute value to the netuix:page element in the control's .book file:

backingFile="com.bea.console.utils.NavTreeExtensionBacking"

For example, if you want to add a link to a page that you have created, in the .book file that defines your page, add the backingFile attribute:

<netuix:page definitionLabel="MyAppTableBook" title="My Page" 
   markupName="page"
   markupType="Page" 
   backingFile="com.bea.console.utils.NavTreeExtensionBacking"
> 

The NavTreePortlet displays the value of the page element's title attribute as the link text. See Figure 6-3.

If the title attribute value is a key in your message bundle, the NavTreePortlet displays the localized value mapped to the key. Specify a message bundle name by adding metadata to the page configuration. Add a <netuix:meta> element as a child to <netuix:page>, for example:

<netuix:page definitionLabel="MyAppTableBook" title="My Page">
  <netuix:meta name="skeleton-resource-bundle" content="3rdbundlename" />
...
</netuix:page>

Figure 6-3 Append a Node to the Root of the Existing Tree

Description of Figure 6-3 follows
Description of "Figure 6-3 Append a Node to the Root of the Existing Tree"

Append or Insert Nodes or Node Trees

If you want to control the location in which your node is added to the NavTreePortlet, or if you want to add a node tree, implement your own NavTreeExtensionBacking backing class.

The following sections describe appending or inserting nodes or node trees:

Create a NavTreeBacking Class

To create a NavTreeBacking class (see Example 6-9):

  1. Extend com.bea.console.utils.NavTreeExtensionBacking.

    This class is already available in the WebLogic Server runtime environment. However, for support in your development and compiling environment, you must add the following JARs to your environment's classpath:

    WL_HOME/server/lib/consoleapp/webapp/WEB-INF/lib/console.jar

    WL_HOME/server/lib/consoleapp/webapp/WEB-INF/lib/netuix_servlet.jar

    where WL_HOME is the location in which you installed WebLogic Server.

  2. Override the NavTreeExtensionBacking.getTreeExtension(

  3. PageBackingContext ppCtx, String extensionUrl, HttpServletRequest request) method.

    In your implementation of this method:

    1. Construct a com.bea.jsptools.tree.TreeNode object for the parent node.

      Use the following constructor:

      TreeNode(String nodeId, String nodeName, String nodeUrl)
      

      where:

      nodeId is the value of the control's definitionLabel. You can use PageBackingContext.getDefinitionLabel() to get this value. Alternatively, you can enter the definitionLabel value that is in the control's .book file.

      nodeName is the text that you want to display in the NavTreePortlet. You can create a String object that contains the text or use PageBackingContext.getTitle() to get this value from the page's .book file.

      nodeURL is a URL to the control. Supply extensionUrl as the value of this parameter.

    2. If you want to add a tree of nodes, construct additional TreeNode objects as children of the parent TreeNode.

      For each child node, use the following constructor:

      TreeNode(String nodeId, String nodeName, 
         String nodeUrl, TreeNode parent)
      

      where:

      nodeId is the value of the control's definitionLabel. You can not use PageBackingContext.getDefinitionLabel() to get this value because the PageBackingContext available to this method is for the parent node. Instead, you must enter the definitionLabel value that is in the control's .book file.

      nodeName is the text that you want to display in the NavTreePortlet.

      nodeURL is a URL to the control. Supply the following value:

      /console/console.portal?_nfpb=true&_pageLabel=definitionLabel 
      

      where definitionLabel is the definitionLabel of the page to which you want to link.

      parent is any TreeNode that you have constructed. You can create multiple levels in your node tree by specifying a parent that is a child of node higher up in the hierarchy.

    3. Pass the parent TreeNode object to the constructor for com.bea.console.utils.NavTreeExtensionEvent.

      Use the following constructor:

      NavTreeExtensionEvent(String pageLabel, String url, 
         String parentPath, TreeNode node, int ACTION) 
      

      where:

      pageLabel is the same nodeID value that you used when constructing the TreeNode object for the parent node.

      url is the same nodeURL value that you used when constructing the TreeNode object for the parent node.

      parentPath is the name of the node under which you want your node to display. Use / (slash) to represent the root of the navigation tree in the NavTreePortlet.

      For example, if you want your node or node tree to display at the top level, specify /. If you want your node to display as a child of Environments, specify /Environments.

      node is the parent TreeNode that you created in step a.

      ACTION is NavTreeExtensionEvent.APPEND_ACTION. For information about other possible actions, see NavTreeExtensionEvent in the WebLogic Server Administration Console API Reference.

    4. Return the NavTreeExtensionEvent object that you constructed.

  4. Save the compiled class in a package structure under your extension's WEB-INF/classes directory.

Example 6-9 Example NavTreeExtensionBacking Class

package com.mycompany.consoleext;
import com.bea.netuix.servlets.controls.page.PageBackingContext;
import com.bea.jsptools.tree.TreeNode;
import com.bea.console.utils.NavTreeExtensionBacking;
import com.bea.console.utils.NavTreeExtensionEvent;
public class CustomNavTreeExtension extends NavTreeExtensionBacking {
   public NavTreeExtensionEvent getTreeExtension(PageBackingContext ppCtx,
      String extensionUrl){
     /*
      * Construct a TreeNode for the control that has invoked this method.
      */
      TreeNode node = new TreeNode(ppCtx.getDefinitionLabel(),
         ppCtx.getTitle(),extensionUrl);
     /*
      * Construct a child TreeNode.
      */
      TreeNode node1 = new TreeNode("MyAppGeneralTabPage",
         "MyApp General",
         "/console/console.portal?_nfpb=true&_pageLabel=MyAppGeneralTabPage",
           node);
     /*
      * Add the parent node (which includes its child) below the
      * Environment node in the NavTreePortlet.
      */
      NavTreeExtensionEvent evt =
        new NavTreeExtensionEvent(ppCtx.getDefinitionLabel(),extensionUrl,
        "/Environment",node);
      return evt;
   }
}

Invoke the NavTreeBacking Class

To invoke the NavTreeBacking class and start the process described in Example: How a NavTreeExtensionBacking Class Adds a Node Tree to the NavTreePortlet:

  1. Determine which UI page control you want to add as the parent node.

    Only page controls can be added as nodes to the NavTreePortlet.

  2. Add the following attribute and attribute value to the control's netuix:page element in the control's .book file:

    backingFile="your-NavTreeBacking-class" 
    

    where your-NavTreeBacking-class is the fully-qualified name of the class you created in step 1.

Example: How a NavTreeExtensionBacking Class Adds a Node Tree to the NavTreePortlet

The following example describes how a NavTreeExtensionBacking class adds the node tree illustrated in Figure 6-4:

  1. As the portal framework loads your extension, it parses your extension's .book files and finds a netuix:page element.

    For example:

    <netuix:page definitionLabel="MyAppTablePage" title="My App" 
       markupName="page"
       markupType="Page" 
       backingFile="com.mycompany.utils.MyNavTreeExtension"
    >
    
  2. The portal framework instantiates a com.bea.netuix.servlets.controls.page.PageBackingContext object, which is an in-memory representation of the page UI control. The object contains properties that describe the page control's title and definitionLabel among other data.

  3. When the portal framework encounters the backingFile attribute in the netuix:page element, it initializes the specified class (MyNavTreeExtension) and passes your page's PageBackingContext object to the class constructor. It also passes a String object that contains the page control's URI.

  4. The MyNavTreeExtension class does the following:

    1. It retrieves the title and definitionLabel values from the PageBackingContext object.

    2. It constructs a com.bea.jsptools.tree.TreeNode object and passes the title and definitionLabel values along with the page control's URI to the constructor.

    3. It constructs two additional TreeNode objects for two pages whose titles are "Monitor EJBs" and "Log Messages."

      Because there is no way to retrieve the PageBackingContext objects or the URIs for these two pages, the values must be hard-coded in the MyNavTreeExtension class.

      To make the pages into child nodes of the "My App" page node, the MyNavTreeExtension class uses a form of the TreeNode constructor that accepts the name of a parent node. For example:

      TreeNode childnode1 = new TreeNode("MyAppMonitorEJB",
        "Monitor EJBs",
        "/console/console.portal?_nfpb=true&_pageLabel=MyAppMonitorEJB",
        node);
      
    4. It constructs and returns a com.bea.console.utils.NavTreeExtensionEvent object.

      The NavTreeExtensionEvent object describes the TreeNode objects that you constructed and indicates the location in the existing navigation tree at which you want to append your node tree.

  5. The NavTreePortlet listens for NavTreeExtensionEvent objects. As the portlet initializes its tree, it appends nodes as specified by any NavTreeExtensionEvent objects that are broadcast.

Figure 6-4 Example: Adding a Node Tree to the NavTreePortlet

Description of Figure 6-4 follows
Description of "Figure 6-4 Example: Adding a Node Tree to the NavTreePortlet"

Navigating to a Custom Security Provider Page

If you created a custom security provider and used WebLogic MBeanMaker to create MBeans to manage your provider, the Administration Console automatically generates pages to display the provider's configuration data. It also generates a link to your provider pages from the Security: Providers table.

However, you can create your own pages to customize this display. If you create your own pages, you need to redirect the link in the Security: Providers table from the pages that the Administration Console generates to your custom pages.

To redirect the link, include the following element as a child of your page's <netuix:page> element:

<netuix:meta type="configuration" content="MBean-class-name"/> 

where MBean-class-name is the fully qualified name of your provider's MBean class.

For example:

<netuix:page markupName="page" markupType="Page"
   definitionLabel="SimpleSampleAuthorizerAuthorizerConfigCommonTabPage"
   title="tab.common.label"
   skeletonUri="/framework/skeletons/default/wlsworkspace
      /page_content.jsp">
   <netuix:meta name="configuration"
   content="examples.security.providers.authorization.simple.
      SimpleSampleAuthorizerMBean"/>
   <netuix:content>
...