Sun Java System Portal Server 7 Developer's Guide

Chapter 6 Overview of Implementing a Custom Provider

This chapter contains the following sections:

Overview of Defining a Custom Provider

Before developing a custom provider, determine whether there is an existing Provider that can access the type of content you are targeting. For example, if you are trying to fetch content from a JSP page, you can create a channel based on the the pre-built JSP provider and configure it to access your JSP page. If none of the APIs can be used as is, determine whether or not the content can be presented by authoring a new provider by extending a provider base class (such as the ProviderAdapter or ProfileProviderAdapter).

To develop a provider, you must start by:

Defining Specific Requirements and Functionality

Before beginning to develop a provider, determine the application specific requirements, content source, and properties of the provider.

Application Specific Requirements

Determine the nature of the provider. Will this provider be a building block provider or will this be a content provider? The content providers are special purpose providers and the building block providers are general purpose providers. For example, the bookmark channel is special purpose, where XMLProvider is general purpose. That is, the XMLProvider can be used, in general, to connect to an XML source and translate it via XSLT to some markup language.

Determine if the content made available via this provider will be:

Presentation Method

Determine whether the provider will fetch content from template files or JSPs. This will determine the logistics of the getTemplate() method.

Channel template files are stored in a directory based on the name of the channel, or the name of the provider that is used by the channel. The channel directory for the provider is created under the template root directory. By default, this will be:

PortalServer-DataDir/portals/portal-ID/desktop/desktoptype/channeldirectory/templatefiles

The JSPs and templates for desktop type default are stored under PortalServer-DataDir/portals/portal-ID/desktop/default directory. Storing the files in the PortalServer-DataDir/portals/portal-ID/desktop/default directory allows the files to be shared. That is, when the Desktop service uses the comma-separated string (as an ordered Desktop type list) in the Desktop type attribute to lookup, it starts at the first element in the list and each element represents a sub directory under the Desktop template base directory. If a template is not found in the first directory (or the first string in the desktop type attribute), then it proceeds to the next one in the list. This continues until the item is found (or not), for all Desktop type elements in the list. If the default directory is not included in the list, it will be added at the end of the list implicitly.

The directory search order for the template and JSP files is as follows:

desktoptype_locale/channelname/clientPath
desktoptype_locale/provider/clientPath
desktoptype_locale/channelname
desktoptype_locale/provider
desktoptype_locale/clientPath
desktoptype_locale
desktoptype/channelname/clientPath
desktoptype/provider/clientPath
desktoptype/channelname
desktoptype/provider
desktoptype
default_locale/channelname/clientPath
default_locale/provider/clientPath
default_locale/channelname
default_locale/provider
default_locale
default/channelname/clientPath
default/provider/clientPath
default/channelname
default/provider
default/clientPath
default
templateroot

Where

If there is no clientPath specified, then the directory search order is as follows:

desktoptype_locale/channelname
desktoptype_locale/provider
desktoptype_locale
desktoptype/channelname
desktoptype/provider
desktoptype
default_locale/channelname
default_locale/provider
default_locale
default/channelname
default/provider
default
templateroot

Note –

If the channel display profile is defined inside a container display profile definition, the lookup for the channel will be desktoptype/containername/channelname/clientPath.


Provider-specific Properties

In the display profile, properties contain configuration information for the provider and the provider’s channels. A provider can define any number of specific properties. See Properties in Display Profile and Technical Reference Guide for more information.

Also, a provider can have more than one properties file, which is actually a JavaTM resource bundle file that enables localization of on-screen images or text. See Properties in Resource bundle for more information.

Properties in Display Profile

The display profile document defines a Provider. The definition of a Provider associates the Provider with the class file that implements its behavior. A Provider definition includes a number of properties, mandatory and provider-specific.

Provider specific properties are defined in the display profile. Provider specific properties are defined in the display profile within the <Properties></Properties> tag for the provider. The following is the structure of the properties in the display profile:


<Properties>
    <Collection>
        ...subset of property definitions
    </Collection>
    <Integer>...</Integer>
    <String>...</String>
    <Boolean>...</Boolean>
</Properties>

Typically, the custom provider will not modify the required properties. When properties are updated, they are set in the user’s display profile by the administrator via the administration console. However, values can only be set on existing properties.

If the provider class does not extend the ProfileProviderAdapter and implements the Provider interface, then the get*Property() methods cannot be used directly, and the display profile properties are not accessible. If the provider class implements the Provider interface directly, then no properties are required. Properties must be hardcoded return values or can come from another source such as a database. However, some provider properties are required if the provider implementation extends ProviderAdapter or ProfileProviderAdapter.

The following is a list of the mandatory properties for a provider. The mandatory properties described below are for a provider extending the ProviderAdapter or the ProfileProviderAdapter classes. If you are implementing the Provider interface directly, you can avoid the use of the display profile and the required properties outlined below.

title

Title of the Provider

description

Description of the Provider

refreshTime

Time interval for cached content

isEditable

Can the Provider be edited

editType

Type of edit form to use

width

Width of the Provider

helpURL

URL of a help page for this Provider

See Technical Reference Guide for detailed information on the Display Profile properties.

Channel definitions that use a provider can overwrite the properties of that provider. At runtime, channel property values can be affected by the display profile merge process. See Technical Reference Guide for detailed information on the display profile merge process.

Properties in Resource bundle

Strings defined in the provider’s resource bundle properties file are displayed on the user’s Desktop and they are not the channel’s properties (such as the channel title). Strings are defined in the resource bundle to enable localization.

Typically, resource bundle includes properties that do not need to be customized by the administrator or the end-user. For example, properties that need to be localized, are read-only at runtime, and properties that do not change per channel should be included in a resource bundle. Properties that need to be localized, are settable, and properties that change per channel should be in the display profile.

By default, a provider’s resource bundle properties file is stored in PortalServer-base/web-src/WEB-INF/classes directory. Note that you can change the file here, but you must re-deploy the portal web application for the changes to take effect.

Resource bundles that are needed by the custom providers should be copied into the provider class base directory (see Provider Class File for more information.) Resource bundles should be placed as individual files and cannot exist inside the JAR file under the provider class base directory.

Resource bundles are given a base name that equals to the name of the display profile provider definition that they are associated with. Typically, this is the class name of the Java class file that implements the provider.

To get the name of the resource bundle in your custom provider, call ProviderContext.getProviderName(). This value can then be used as the baseName argument to ResourceBundle.getBundle(). If you are extending ProviderAdapter, simply call getResourceBundle().

Developing the Provider Class File

This section includes information on the requirements for developing a provider’s class file. It contains:

Provider Class File Location

The provider classes must be deployed in the provider class base directory specified in the file PortalServer-DataDir/portals/portal-ID/config/desktopconfig.properties. By default, the provider class base directory is PortalServer-DataDir/portals/portal-ID/desktop/classes.

For hot deployment, the JAR file has to be dropped in the directory mentioned in providerClassBaseDir variable in the desktopconfig.properties file.

Provider Class File

The custom provider classes and all other custom classes that the provider classes reference can be bundled into a JAR file and placed in the provider class base directory. They can also exist as .class files in the provider class base directory.

If a class exists in a file and is also present in a JAR file under the provider class base directory, the class existing as a file under the provider class base directory is given the first preference. Once the class is found as a file, no attempt is made to check for its existence in a JAR file.

If a class file exists in two JAR files under the provider class base directory, the class is picked up from one of them at runtime. Do not duplicate classes in multiple JAR files.

When compiling the class file, the Servlet 2.2 API (servlet.jar) and PAPI (PortalServer-base/sdk/desktop/desktopsdk.jar) are required in the CLASSPATH. That is, when compiling a *Provider.java file, you must type:

javac -d PortalServer-DataDir/portals/portal-ID/desktop/classes -classpath PortalServer-base/sdk/desktop/desktopsdk.jar:AccessManager-base/lib/servlet.jar *Provider.java

Provider Class Loader

To support hot deployment of Provider classes the Portal Server has a Provider classloader implementation that can pickup changes to custom classes in the Provider Classloader directory. The provider class loader in the Portal Server software is used to load the classes.

A Provider Classloader instance loads all custom provider classes and resource bundles. When a class in the Provider Classloader directory changes, the Provider classloader and all the classes it loaded are discarded; a new Provider Classloader object is created and this one reloads all the custom classes.

In order to upload a new version of a custom provider class without restarting the server, if the original class existed in a JAR file, rebuild the JAR with the new version of the class file and copy the JAR into the provider class base directory. Or, Just copy the new version of the class as a file into the provider class base directory.

In order to reload a property file, that is being used by a custom provider, with a modified property inside a resource bundle in the provider class base directory without restarting the server, change the last modified time on the custom provider class. If the custom provider class exists:

The presence of the provider class loader has an impact on the design of a multi-channel application in the Desktop. When an object reference is cast from one type to another, not only does the class of the variable need to match the class of the object, the two associated class loaders have to be the same too. This constraint can show up when objects are being passed between different channels in the Desktop.

For example, consider a portal application that uses two providers, one for a container and the other for several leaf channels. Call these providers HeadlineContainerProvider and HeadlineProvider. The container provider performs some common processing for the leaf channels, and then the leaf channels access the container object to get the results of that processing. One way to implement this would be to have the HeadlineContainerProvider put a reference to itself into the request object. For example, in the HeadlineContainerProvider.getContent(), do:

request.setAttribute("HeadlineContainer", this);

Then, in the HeadlineProvider.getContent() method, do:

HeadlineContainerProvider hcp = (HeadlineContainerProvider)request.getAttribute("HeadlineContainer");

This example will compile, but when the desktop loads and runs this code, the HeadlineProvider will cause a ClassCastException on this second statement. The reason is that the HeadlinerContainerProvider object is loaded by one provider class loader object and the HeadlineProvider object is loaded by a different class loader object. The class loader for HeadlineProvider also loads HeadlineContainerProvider because HeadlineProvider references HeadlineContainerProvider. So we have:

The HeadlineContainerProvider class is also loaded by loader2 because of the reference to it in the HeadlineProvider code. The cast is from the object container1 (loaded by loader1) to the variable hcp (of type HeadlineContainerProvider loaded by loader2). Thus the cast fails because the class loaders are not the same.

To understand a case where the classes could actually be different, consider the case where container1 is loaded at time 0, and channel1 is loaded at time 10, but the HeadlineContainerProvider class files was updated on disk at time 5. This means that channel1 will be running with a different version of the HeadlineContainerProvider class than that being used for container1. The case must fail because the class versions are different.

To implement this type of application, an alternate solution is to pass an object as a request or session property that has a class that is not in the PortalServer-DataDir/portals/portal-ID/desktop/classes directory, such as String, Set, or Hashmap. These classes are never reloaded except when the server restarts. The data that you store in that object becomes a contract between different versions of the classes that use that object.

Creating XML Fragments for Display Profile

A provider must be defined in the display profile before it can be used. This definition associates the provider with its class file implementation and includes the provider’s properties. That is, the provider’s display profile fragment should include default values for all the properties that are used in the provider.java file. For example, if the provider.java file contains getStringProperty(“color”), the provider’s display profile fragment should include a default value for color.

The provider’s XML fragment in the display profile must adhere to the following structure:


<DisplayProfile>
    <Providers>
        <Provider name=”
         providername”
            class=”
         provider class name”>
            <Properties>...</Properties>
        </Provider>
    </Providers>
</DisplayProfile>

The provider definition is the template that decides the properties for the provider’s channels. However, the display profile definition for the channel ultimately decides the values for the channel’s properties. When a channel sets a property, the property is set in the channel and not in the provider’s properties. When defining channel properties in the display profile, include only those properties where the provider defaults are not applicable.

The provider’s channel XML fragment in the display profile must adhere to the following structure:


<DisplayProfile>
    <Channels>
        <Channel name=”
         channelname” provider=”
         providername”>
            <Properties>...</Properties>
        </Channel>
    </Channels>
</DisplayProfile>

The channel definition in the display profile need not have the <Container> tag unless the channel is defined within a container. Channel definitions in the display profile can be encapsulated inside a container. The advantage of this is that it provides name scoping so that channels with the same name do not collide.

Unless a channel is referenced directly from the DesktopServlet URL, in which case it need not be encapsulated inside a container, you must reference a channel from some container in order to see it.

The container within which the channel will operate must adhere to the following structure:


<DisplayProfile>
    <Channels>
        <Container>
            <Properties>...</Properties>
            <Available>...</Available>
            <Selected>...</Selected>
            <Channel>...</Channel>
        </Container>
    </Channels>
</DisplayProfile>

To upload display profile changes, use the psadmin add-display-profile or psadmin modify-display-profile subcommand. See Sun Java System Portal Server 7 Command-Line Reference for more information on the psadmin command and see the Portal Server administration console online help for more information on administering the display profile.

Installing the Provider

This section provides information on:

Installing Manually

ProcedureTo install the provider manually:

Steps
  1. Compile the provider class file and copy the file to the provider class base directory which, by default, is PortalServer-DataDir/portals/portal-ID/desktop/classes. Or copy the file to the location specified in the PortalServer-DataDir/portals/portal-ID/config/desktopconfig.properties file.

  2. Copy the resource bundle files, if any, to PortalServer-DataDir/portals/portal-ID/desktop/classes directory.

  3. Develop the JSPs and templates for the provider and copy the files to the template root directory for the provider which, by default, is PortalServer-DataDir/portals/portal-ID/desktop/desktoptype/providerName.

  4. Develop and upload the display profile XML fragments for the provider, the provider’s channels, and the container within which the channels will operate, if any.

Transporting Using the psadmin Utility

Utilize the psadmin export/import -t provider utility for deploying channels and providers. The psadmin export/import -t provider command enables you to transfer or move providers or channels from one the Portal Server software host to another. The psadmin export/import -t provider utility creates a specialized packaging mechanism called a .par file for transport of channels and providers into and out of the server.

A .par file is an extended form of the .jar file format, with added:

The use of .par files is optional. You can just as well copy all files into their correct locations. The par utility makes deployment easier if you have to install the files on multiple servers.

To create a .par file from scratch, use the export subcommand of the psadmin utility.

To export an existing provider, use the export subcommand of the psadmin utility.

For example, if you have the provider associated files in the development environment ready for deployment into the production environment, use the following command to build the channel and provider into a PAR file which can then be deployed on the system.

psadmin export -u dn_amadmin -f passwordfile -t provider -p portal-ID -d|-g -x exportfile provider.par

To deploy the .par file into the system, use the following command:

psadmin import -u dn_amadmin -f passwordfile -p portal-ID dn -O '"provider=providername|channel=channelname","provider=providername|channel=channelname"'


Note –

All providers that ship with the Portal Server software are in the service-level Desktop display profile. There is no command to extract them all.


See Sun Java System Portal Server 7 Command-Line Reference for more information on the psadmin utility.