Portlet Features

This page is to serve as a feature aggregator for desired portlet functionality. The switch from channels to portlets in uPortal 3 is going to leave some gaps in features that channels had available and the base portlet specification does not.

General

Portlet URLs

This refers more to the internals of uPortal and portlet URL generation than APIs the end portlet will actually use.

  • All URL parameters used by the framework should have their own prefix, 'uP_' would be a good candidate.
  • Portlet URL parameters should also be prefixed with some information specific to that portlet, 'plt.{window_id}_' is a possibility for the format.
  • Portlet URL parameters are defined by uPortal's portlet parameter syntax provider and URL constructor.

By planning on prefixing all URL parameters appropriatly we get more future flexibiltiy to support idioms such as portlet URL parameters that get passed to all the portlets rendering on the page.

Portlet Modes

Servant

This mode will allow a fully functional portlet to be used by another portlet or part of the framework to render a full UI including interaction with the servant portlet and access to a returned object. The idea behind doing this as a PortletMode is to allow a portlet to become a uPortal servant with minimal changes to the portlet's code.

  • A portlet that declares it supports the Server PortletMode will be available via the servant locator APIs described in the API section.
  • When a portlet is called in Servant mode it is under the same rendering constraints as PortletMode.VIEW.
  • The portlet will set a request attribute named "org.jasig.uportal.portlet.SERVANT_COMPLETE". The Object value of that attribute will be passed back to the code calling the servant portlet.
  • The calling portlet will use a servlet locater API to get a uPortal specific ServantPortlet interface via a unique name for the portlet (similar to fname's in uPortal 2).
  • With the ServantPortlet interface the caller can determine if the servant portlet is complete and call render and processAction methods to execute the servant portlet.

Publish

This mode is similar to the the Servant mode. It involves one portlet calling another portlet. In this case PUBLISH mode should only ever be called by the portlet publishing portion of the portlet administration portlet Portlet Administration.

  • All PortletPreferences stored when in this mode should be stored at the portlet definition level.

Subscribe

Similar to PUBLISH except displayed when subscribing to a portlet.

  • All PortletPreferences stored when in this mode should be stored at the portlet entity level.

Preview

The portlet administration portlet would provide a preview option for portlets implementing this mode when publishing is complete. It could also be used in the portlet subscription UI.

Window States

Detached

Tells the portlet it is being rendered in a pop-up style window.

Exclusive

Tells the portlet that it has full control over the OutputStream/PrintWriter for the request. Allows a portlet to render arbitrary content.

APIs

IPortletServantLocatorFactory.java
/**
 * Provides methods for creating portlet servant factories.
 */
public interface IPortletServantLocatorFactory {

    /**
     * Creates a new IPortletServantLocator instance that will be used to locate portlet servants.
     **/
    public IPortletServantLocator createPortletServantLocator();

}
IPortletServantLocator.java
/**
 * Provides methods for locating portlet servants provided by uPortal.
 */
public interface IPortletServantLocator {

    /**
     * Gets a new IPortletServant instance for running the specified portlet as a servant.
     * @param publishedPortletName is a portlet functional name given during portlet publising
     **/
    public IPortletServant locate(String functionalPortletName);

}
IPortletServant.java
/**
 * The PortletServant interface is a uPortal wrapper around a JSR-168 portlet that implements
 * the Servant PortletMode. It provides methods for delegating rendering and action processing
 * to the servant portlet, to watch for it's completion and to get the results of the servant's
 * operation.
 */
public interface IPortletServant {

    /**
     * Returns the unique portlet servant ID given by the servant locator when creating a new servant instance.
     */
    public String getId(); 

    public void render(RenderRequest request, RenderResponse response) throws PortletException, IOException;

    public void processAction(ActionRequest request, ActionResponse response) throws PortletException, IOException;

    public boolean isComplete();

    public Object[] getResults();
}
CustomPortletModes.java
/**
 * PortletModes that uPortal supports beyond the base portlet spec.
 */
public abstract class CustomPortletModes {
    public static final PortletMode SERVANT        = new PortletMode("servant");
    public static final PortletMode PUBLISH        = new PortletMode("publish");
    public static final PortletMode SUBSCRIBE      = new PortletMode("subscribe");
    public static final PortletMode PREVIEW        = new PortletMode("preview");
}
CustomWindowStates.java
/**
 * WindowStates that uPortal supports beyond the base portlet spec.
 */
public abstract class CustomWindowStates {
    public static final WindowState EXCLUSIVE = new WindowState("exclusive");
    public static final WindowState DETACHED  = new WindowState("detached");
}
IPortletIdentifier.java
/**
 * Provides key information for the different scoping levels related to a portlet's deployment. The
 * values of the keys should be immaterial to the portlet, they are simply keys used by the portal.
 * This information can be usefull for a portlet that needs to persist or share some information based
 * on scope.
 *
 * The scopes are listed from broadest to narrowest.
 */
public interface IPortletIdentifier {
    /**
     * This is the key a portlet uses to get the IPortletIdentifier object out of the PortletRequest's
     * attributes.
     */
    public static final String PORTLET_IDENTIFIER = "org.jasig.uportal.portlet.PORTLET_IDENTIFIER";

    public String getSystemId();

    public String getApplicationDeploymentId();

    public String getApplicationDefinitionId();

    public String getApplicationEntityId();

    public String getDeploymentId();

    public String getDefinitionId();

    public String getEntityId();

    public String getWindowId();
}

Implementation Ideas

PortletUtils

The PortletUtils class will only provide static methods to ensure compatability with the following implementation scheme:

PortletUtils will be packaged as part of a uPortal portlet utils library. The goal of this library is to be a small set of classes that a portlet developer can use to access services provided by uPortal.

To access the uPortal services this library will be deployed to a shared library location on the container. Allowing uPortal and all portlets to access the same instance of the classes. (Similar to pluto's deployment).

The library will contain a Locator class, this class with be a simple bean with a getter and setter for a service interface. The implementation of this service interface will exist in the uPortal context. When uPortal starts it will set a reference to this service interface implementation into the Locator class.

The classes, such as PortletUtils, in the library will use the service interface the Locator class has a static reference to for making their calls into uPortal.

The best way to implement a system like this is to first implement the PortletUtils class as part of the uPortal web application. As long as the PorltetUtils class and any objects accessible directly or indirectly though it are not uPortal specific the external library and locator class system can be implemented at a later time.

PortletIdentifier

The populated PortletIdentifier implementation provided by the portal will be passed to the portlets as a request attribute.