Sun Java System Portal Server 6 2004Q2 Developer's Guide |
Chapter 2
Overview of the Provider API (PAPI)This chapter provides an overview of the Sun Java System Portal Server software Provider Application Programming Interface (PAPI) and includes instructions for developing a custom provider.
This chapter contains the following sections:
IntroductionFigure 2-1 shows the relationship between the various interfaces, classes, and exceptions discussed in this chapter. For detailed information on these interfaces, classes, and exceptions, see the Javadocs at http://hostname:port/portal/javadocs.
Figure 2-1 The Provider Application Programming Interface (PAPI)
The Provider APIThis section provides an overview of the interfaces (see Provider, ProviderWidths, and ProviderEditTypes), base classes (see ProviderAdapter, ProfileProviderAdapter), context (see ProviderContext), exceptions (see Exceptions), and the lifecycle of the provider.
Provider
The Provider interface clearly defines the communication channel between a container and a provider. The container may be the DesktopServlet, or another provider object. The methods defined in the Provider interface supply the basic handshaking required for a container to display the content from a provider object.
A provider can implement this interface. Clients of the Provider interface call the methods in this interface to query information or to perform an action in the provider. Such clients include, but are not limited to, the DesktopServlet and other channels (container channels).
There are essentially two types of methods in this interface:
This includes getContent(), getEdit(), and processEdit() methods.
Methods that describe how the provider should be treated by the containing entity
This includes all methods that begin with is and get (minus the get* methods used for handling actions).
See the Javadocs for more information on the methods in this interface.
ProviderAdapter
The ProviderAdapter class implements aspects of the Provider using the ProviderContext. The ProviderAdapter class implements the ProviderWidths interface, which defines the provider widths, and ProviderEditTypes interface, which defines the edit types, making the constants defined in these interfaces available to classes that extend ProviderAdapter.
Developers who wish to implement a provider can extend this class or the ProfileProviderAdapter class for forward compatibility and convenient access to the ProviderContext interface.
See the Javadocs for more information on the methods in this class.
ProfileProviderAdapter
The ProfileProviderAdapter is a subclass of the ProviderAdapter that includes convenience wrappers around some commonly used methods in the ProviderContext interface, like get/set*Property(), exists*Property(), get/setStringAttribute(), and getTemplate().
The advantages of using the wrapper methods in the ProfileProviderAdapter class as opposed to using the methods in the ProviderContext interface are the following:
- For example, the ProviderContext.getStringProperty() accepts the channel name as an argument. Since the ProfileProviderAdapter knows the channel name, it can use ProfileProviderAdapter.getStringProperty() method without providing the channel name.
- All of the methods in ProviderContext throw a ProviderContextException. The analogous methods in ProfileProviderAdapter throw a ProviderException. For example, when implementing the getContent() method, since this method is already defined to throw a ProviderException, when a client calls ProfileProviderAdapter.getStringProperty() inside the getContent() method, you need not implement a try-catch block. However, if you use ProviderContext.getStringProperty(), you must catch the ProviderContextException.
See the Javadocs for more information on the methods in this class.
ProviderContext
The ProviderContext object provides information pertaining to the environment that a provider object is executing within. Such information may be specific to the user, to the web container, or be global (shared between multiple users). This interface does not define what information falls into each of these categories; this is left up to the implementation. Provider developers can obtain a handle to a ProviderContext object by extending ProviderAdapter, and then calling ProviderAdapter.getProviderContext().
The ProviderContext forms the layer between the services used by the provider and the provider implementation thus isolating the provider code from specific service interfaces and implementations. It defines the service interface for the Desktop, and allows different implementation to access the actual data.
The following are some of the methods in the ProviderContext:
- Service (data/functions pertaining to the Desktop service): getDesktopURL(), getLocaleString(), getLocale(), getDesktopType(), getLogoutURL(), getStringAttribute(), setStringAttribute(), getDefaultChannelName(), getLoginURL(), getRoles()
- Servlet (data/functions pertaining to the servlet): getRequestServer(), getServletConfig()
- Client type (data/functions pertaining to the client device type): getClientTypeProperty(), getDefaultClientType(), getClientType(), getCharset(), getClientPath(), getContentType(), getClientTypeProperties()
- Session:
- Data/functions pertaining to the user’s session: get/setSessionProperty(), getSessionID(), getUserID(), encodeURL(), isAuthless()
- Data/functions pertaining to per-client properties: get/setClientProperty()
- Data/functions pertaining to the debug service: isDebugEnabled(), isDebugErrorEnabled(), isDebugWarningEnabled(), isDebugMessageEnabled(), debugMessage(), debugWarning(), debugError()
- Data/functions pertaining to template access: getTemplate(), getTemplatePath(), getTemplateMostSpecificPath()
- Data/functions pertaining to channel properties: getProviderName(), getClassName(), getNames(), get/set*Property(), exists*Property(), getProviderVersion()
- Data/functions pertaining to config properties: getStaticContentPath(), getConfigProperty()
- Data/Functions pertaining to ClientTypeFilters: getClientPropertiesFilters(), getLocalePropertiesFilters(), getClientAndLocalePropertiesFilters()
- Data/Functions pertaining to URLEncoding: encodeURLParameter()
See the Javadocs for more information on the methods in this interface.
ProviderWidths
The ProviderWidths interface defines the widths that can be returned from the Provider.getWidth() method. The width is a suggestion to a client of a provider object as to how much screen real estate should be given to display the provider’s default view.
See the Javadocs for more information on the methods in this interface.
ProviderEditTypes
The ProviderEditTypes interface defines the edit types that can be returned from the Provider.getEditType() method. The edit type informs a client of a provider object what it can expect to be returned from the provider’s getEdit() method. The edit type can be EDIT_COMPLETE or EDIT_SUBSET.
- EDIT_SUBSET - Indicates that the edit page is not a complete document. This value is potentially returned from getEditType() to signify that the buffer returned is only a subset of a document. The edit type, if subset, means that the JSP edit container is used to wrap the content from the container. This is useful for providing a common look and feel for a set of common portal pages. That is, it allows the channel’s edit page to look and feel according to the container that it exists within although the same channel might appear in two different containers that have very different look and feel. In this case the form that wraps the edit content generated by the provider is drawn by the edit container.
- EDIT_COMPLETE - Indicates that the edit page is a complete document. This value is potentially returned from Provider.getEditType() to signify that the buffer returned is a complete document. The container of the provider uses this information to determine if it needs to wrap it’s edit page output to form a complete document. This is done with something called an edit container.
Containers use edit containers to provide a container-specific look and feel to otherwise heterogeneous providers. It allows the channel’s edit page to look and feel according to the container that it exists within although the same channel might appear in two different containers that have very different look and feel.
See the Javadocs for more information on the methods in this interface.
PropertiesFilter
The PropertiesFilter abstract class, when extended, can describe a specific filter criteria. To implement a specific filter, one must minimally implement the getCondition() and match() methods in the PropertiesFilter abstract class.
- The getCondition() method must return the condition on which the PropertiesFilter should operate.
- The getValue() method must return the value that corresponds to the given condition.
- The isRequired() method can be implemented to specify whether you want this to be a required filter or not. A conditional property lookup involves one or more property filters. If a filter in the filter list is required, then it must match for the overall conditional lookup to succeed. If a filter is not required, then it can fail to match without causing the overall lookup to fail.
A chain of non-required filters can be used to implement a progressively less-specific filter lookup, similar to the semantics of Java resource bundle lookup. For instance, an optional filter would be useful in a case where a locale lookup is followed by a date lookup. Given the filter {locale=en, locale=US, date=03/03/2003}, you can get it to successfully match a property with the qualifier {locale=en; date=03/03/2003} even though it does not exactly match the filter specification. This can be accomplished by setting the locale filter to be optional. The locale property type is deprecated.
Out of the box, the Portal Server software includes filters based on locale and client. The locale and client filter extend the PropertiesFilter abstract class and includes an implementation of the getCondition() and match() methods in the PropertiesFilter class. See the Javadoc for more details.
Exceptions
The Desktop expects a provider to only throw ProviderException or a subclass of the ProviderException. For correct operation, a provider must only throw expected exception type. That is:
Exceptions from providers are logged in /var/opt/SUNWam/debug/desktop.debug file. Note that this file is created only if there is an error.
ProviderException
The ProviderException is a generic superclass for all provider related exceptions.
AsciiFormInputExpectedException
The AsciiFormInputExpectedException will be thrown from Provider.processEdit() method when something other than ASCII only encoded form input is sent to it.
InvalidEditFormDataException
The InvalidEditFormDataException is thrown from the Provider.processEdit() method when there is an error in the data input by the user. If thrown, the Desktop will send back the same Edit page, and will attach the exception’s message as a parameter to the URL. For example, if the exception is:
throw new InvalidEditFormDataException("Error Error");
the Desktop will redirect back to the same Edit page, adding the error message to the URL error parameter:
error=Error Error
The edit page wrapper then looks for the error parameter in the URL and if present, displays the message (or the value of the error parameter) at the top of the page in red.
UnknownEditTypeException
The UnknownEditTypeException may be thrown from Provider.getEditType() method if an unknown or undefined edit type is encountered.
The Provider Life CycleThis section describes the lifecycle of the provider per user session. Figure 2-2, Figure 2-3, and Figure 2-4 shows how the Desktop handles each user session.
A session is created at the time the user logs in to the portal Desktop and ends when they logout. The session also ends when the user session is idle, or when the session times out. For authless logins, a single session is shared amongst all clients accessing the Desktop in authless mode, and the authless session never dies.
For each request, the DesktopServlet will validate the user session; if it is a valid session, the DesktopServlet will start to process the request. If a session does not exist, the DesktopServlet will create a session.
The creation of the provider context is equivalent to the creation of a session. The container provider context object is generated and maintained, one per session. So each time a request comes in, the cached container provider context object is used. For example, in Figure 2-2, when the first initial request comes in, the container provider context is created and initialized, and when the subsequent requests come in, as in the reload and logout requests shown in Figure 2-3 and Figure 2-4 respectively, the cached container provider context is returned.
The container provider context maintains a list of its contained provider objects and their cached content locally. Contained providers are created and initialized once per session, and their content is cached in the provider context object. Subsequent requests access the cached provider objects that live inside the provider context object.
The contentChanged() and allContentChanged() methods signify that either the content for one channel or all channels has changed, respectively. This is used to remove all the cached content for the channels, as well as to clear the cached provider objects. When the requested action is logout, as shown in Figure 2-4, the DesktopServlet will redirect the request to the logout URL, and the session will be destroyed. At this point, the provider context object is removed from the cached list, and ready for garbage collection. Also, if the session expires or times out, the provider context object is removed from the cached list.
Figure 2-2 and Figure 2-4 shows a sample of how the content and logout actions are processed. For detailed information on how the DesktopServlet and the back end providers handle each action (including content and logout), see .
Figure 2-2 The Provider Life Cycle - Initial Request for Authenticated User
Figure 2-3 The Provider Lifecycle - Desktop Reload Request for Authenticated User
Figure 2-4 The Provider Lifecycle - Logout Request