O'Reilly    
 Published on O'Reilly (http://oreilly.com/)
 See this if you're having trouble printing code examples


What Is a Portlet

by Sunil Patil
09/14/2005
Portlets
"Portlets are web components--like servlets--specifically designed to be aggregated in the context of a composite page. Usually, many portlets are invoked to in the single request of a portal page. Each portlet produces a fragment of markup that is combined with the markup of other portlets, all within the portal page markup." (from the Portlet Specification, JSR 168)

This article discusses the following:

  1. Elements of a Portal Page
  2. What Is a Portal?
  3. What Are Portlets?
  4. Developing a "Hello World" Portlet
  5. Deploying a HelloWorld Portlet on Pluto
  6. How a Portal Page Is Created
  7. Conclusion
  8. Resources

The Portlet specification defines a portlet as a "Java-technology-based web component, managed by a portlet container that processes requests and generates dynamic content." That's not the easiest thing to understand, is it? This article will explain what portlets are and what they do.

Figure 1 shows what your browser will look like when you access a portal server.

Thumbnail, click for full-size image.
Figure 1. Typical portal server content (click for full-size image)

If you take a closer look at the browser content, you will see that this page is made up of different "windows." There is one window for the weather update, another window for news, a third for a stock price update, and so on. Each of these windows represents a portlet. If you take closer look, you will find that each of these windows has a title bar and a few buttons, including minimize and maximize buttons.

Under the covers, these windows are different applications, developed independently of each other. The developer of the news portlet will create an application and pack it into a .war file. Then the administrator of the portal server will install this .war file on the server and create a page. In the next stage, every user will choose which applications he wants on his page. For example, if the user is not interested in stock updates but is interested in the sports update, he can replace his "Stocks Update" window with a "Sports Update" window.

Portlet technology requires learning a lot of new concepts, and it won't be possible for us to cover everything in one article, so we have split this article into two parts. In this part, we will define portals and portlets and develop a simple "Hello World" portlet. We will talk about a few more advanced topics in the next part.

We will use Apache's Pluto server--the reference implementation of the Portlet API 1.0 specification--for testing our sample portlets. We will also spend some time talking about how to install and use the Pluto server.

Elements of a Portal Page

Figure 2 shows the various elements of portal page.

Elements of a Portal page
Figure 2. Elements of a portal page

Every portlet page is made up of one or more than one portlet windows. Every portlet window is made up of two parts: one is the decoration, which will decide how the title bar, controls, and borders of portlet windows will appear. The second part is the portlet fragment, which is the part contributed by the portlet application.

Your portal server decides the overall look and feel of the portal page, such as the logo, the colors of the title bars, the images for the controls, etc. By changing a few standard JSPs and .css files, you can change the complete look and feel of your portal. We will talk more about this in the "How a Portal Page is Created" section.

Java Servlet & JSP Cookbook

Related Reading

Java Servlet & JSP Cookbook
By Bruce W. Perry

What Is a Portal?

In order to understand what a portlet is, it is very necessary to understand what a portal is. According to the Portlet Specification, "a portal is a web application that commonly provides personalization, single sign on, content aggregation from different sources, and hosts the presentation layer of information systems. Aggregation is the act of integrating content from different sources within a web page."

Portal functionality can be divided into three main parts:

  1. Portlet container: A portlet container is very similar to a servlet container, in that every portlet is deployed inside a portlet container that controls the life cycle of the portlet and provides it with necessary resources and information about its environment. A portlet container is responsible for initializing and destroying portlets and also for passing user requests to it and collecting responses.
  2. Content aggregator: As defined in the Portlet Specification, one of the main jobs of a portal is to aggregate content generated by various portlet applications. We will talk more about this in the "How a Portal Page is Created" section.
  3. Common services: One of the main strengths of a portal server is the set of common services that it provides. Services are not part of the portlet specification, but commercial portal implementations provide a rich set of common services to distinguish themselves from their competitors. A few common services that you can hope to find in most implementations are:

    There are a few more common services such as machine translation, in which case the portal server will take content generated by portlet in one language and machine translate it into a language requested by user. Most of the commercial portal servers provide access via handheld devices and are capable of generating different content for different browsers.

What Are Portlets?

Similar to servlets, portlets are web components that are deployed inside of a container and generate dynamic content. On the technical side, a portlet is a class that implements the javax.portlet.Portlet interface and is packaged and deployed as a .war file inside of a portlet container.

Portlets are similar to servlets, in that:

  1. Portlets are managed by a specialized container.
  2. Portlets generate dynamic content.
  3. A portlet's life cycle is managed by the container.
  4. Portlets interact with web client via a request/response paradigm.

Portlets are different from servlets, in that:

  1. Portlets only generate markup fragments, not complete documents.
  2. Portlets are not directly URL addressable. You cant send somebody URL of a portlet. You can send him the URL of the page containing a portlet.
  3. Portlets cannot generate arbitrary content, since the content generated by a portlet is going to be part of portal page. If a portal server is asking for html/text, then all portlets should generate text/html content. On the other hand, if the portal server is asking for WML, then each portlet should generate WML content.

Portlets do provide some additional functionality.

  1. Persistent storage for preferences: Portlets provide a PortletPreferences object for storing user preferences. These preferences are stored in a persistent data store, so they will be available across server restarts. As a developer, you don't have to worry about the actual implementation of how it is stored.

  2. Request processing: Portlets provide much more refined request handling. A portlet may get a request when user takes some action on it (a state called action phase), or because the user took action on some other portlet and the page needs to be refreshed. A portal server provides different callback methods for handling both situations.

  3. Portlet modes: Portlets use a concept of mode to indicate what user is doing. When using a mail application, you may be using it for reading, composing, or checking mail messages--this is the expected functionality of a mail application. Portlets normally provide this in VIEW mode. But there are other activities, like specifying a refresh time or (re-)setting the username and password. These activities allow the user to configure the behavior of the application, so they come under EDIT mode. Help functionality of the mail application comes under HELP mode.

    If you think about it, you will find none of these represents new functionality. Instead, most of these are common business requirements. The only thing the portlet specification is doing is providing you one layer of abstraction, so that it will be useful for all stake holders end users, developers and administrators.

    As a developer, I put all my business logic related to VIEW mode in a method called doView(), and I put business logic related to the configuration of my application in a doEdit() method, with help-related logic in a doHelp() method.

    This makes it simple for an administrator to control access in the portlet application, because all he has to do is change access rights of the portlet to dictate what things a user is allowed to do. For example, a user of a mail application is supposed to specify his username and password in EDIT mode, so it makes sense for him to have access to EDIT mode.

    But consider the case where I am the administrator of an intranet site and my company bought a third-party portlet application that displays news updates. This application allows a user to specify the URL from where it can retrieve updates. I want to use this application for displaying internal company news to users. Another requirement is that I don't want users to use this application for tracking any other news source. So as the administrator, I can specify the URL of an internal news update site for all users, and take out their edit privileges by changing the deployment descriptor of this portlet application.

    Using portlets makes my website much more appealing to the end user because she will get a similar UI for all her portlet applications. If she wants to read help information about any of the applications, she can click the help button. She will also know that clicking on an edit button will take her to a configure screen for that application. Standardizing the user interface will make your portlet application more appealing.

  4. Window state: The window state determines how much space should be given to content generated by a portlet on a portal page. If you click on the maximize button, the portlet will take up the entire screen and it will become the only portlet that will be available to the user. In minimized state, the portlet will be displayed as only a title bar. As a developer, you should customize your content based on the space available to you.

  5. User information: Commonly, portlets provide content personalized to the user making the request. To do this effectively, they may require access to user attributes such as name, email, phone, etc. The Portlet API provides the concept of user attributes for this. A developer can access these attributes in a standard way, and it is the responsibility of the administrator to map these attributes to an actual user information repository (usually an LDAP server).

We will talk more about some of these features--request processing, user information, and portlet modes--in the second part of this series.

Developing a "Hello World" Portlet

Now it is time to develop a sample HelloWorld portlet.

  1. Create a HelloWorld web project. Similar to a normal servlet project, it should have a /WEB-INF/web.xmlfile that will be the deployment descriptor of the project.
  2. Add portlet-api-1.0.jar file to your build path. This .jar is part of the Pluto distribution.
  3. Inside of your Source folder, create a HelloWorld.java file, like this:
    public class HelloWorld extends GenericPortlet{
      protected void doView(RenderRequest request,
      RenderResponse response) throws
      PortletException, IOException {
            response.setContentType("text/html");
            response.getWriter().println("Hello Portlet");
            }
    }

    Every portlet should implement the Portlet interface. This interface defines the life cycle methods for a portlet. Since you don't want to override all of those methods, we will extend the GenericPortlet class, which is an adapter class implementing the Portlet interface. It provides default implementations of all life cycle methods, so we only have to implement necessary methods.

    The only thing that we want to do in our HelloWorld portlet is to display "Hello Portlet." So we will override the doView() method of the GenericPortlet class. This method takes a PortletRequest and a PortletResponse as arguments. Call response.setContentType() first thing in the doView() method to inform the portlet container about what content type the portlet is going to generate--failure to do so will result in an IllegalStateException. Once the content type is set, you can get a PrintWriter from the response object and start writing into it.

  4. Every portlet application should have a portlet.xml file in the /WEB-INF folder, which is the deployment descriptor for a portlet application. Create a portlet.xml file, like this:
    <portlet>
      <description>HelloWorldDescription
            </description>
    
        <portlet-name>HelloWorld
            </portlet-name>
        <display-name>Hello World
            </display-name>
    
        <portlet-class>com.test.HelloWorld
            </portlet-class>
        <expiration-cache>-1
            </expiration-cache>
    
            <supports>
              <mime-type>text/html</mime-type>
          <portlet-mode>VIEW
              </portlet-mode>
            </supports>
        <supported-locale>en
            </supported-locale>
    
            <portlet-info>
              <title>Hello World</title>
              <short-title>Hello World
              </short-title>
              <keywords>Hello,pluto</keywords>
    
          </portlet-info>
    </portlet>

    The <portlet-name> element declares the name of the portlet. The <portlet-class> element specifies the fully qualified class name of portlet. The <expiration-cache> element specifies the time in seconds after which content is considered to be stale. This is a little bit more complicated than that: if you perform some action on the portlet, then new content will be generated, irrespective of cache time.

    The <supports> element specifies which modes are supported for a given <mime-type>. In our example, we are saying that HelloWorld can only generate content of the text/html content type, and for the text/html content type, only the view mode is supported. If you decide to add support for other content types, then you should add new <support> elements and specify what modes are supported for that MIME type. It is very common for a portlet to have VIEW, EDIT, and HELP modes for text/html, and only VIEW mode for the WML MIME type.

    You can also specify what locales the portlet supports by using the <supported-locale> element. The <title> element is used to specify a title for the portlet. If you want an internationalized title, then you can specify the name of the resources (i.e., a .properties) file using the <resource-bundle> element. In that case, the container will choose a title from the appropriate .properties file, based on the user's locale.

  5. Every portlet application is a web application, so it requires a web.xml file in addition to portlet.xml.
    <web-app>
      <display-name>Hello World Portlet
      </display-name>
      <welcome-file-list
        <welcome-file>index.jsp
            </welcome-file>
    
      </welcome-file-list>
    </web-app>
  6. The next step is compiling this content and packaging it into a .war file. You can do that yourself or download the sample code (see the "Resources" section) that has a build.xml that your can use for creating the .war file.

Deploying HelloWorld Portlet on Pluto

Pluto is in the early stages of development, so it does not have a set of easy-to-use administrative tools. In order to use the Pluto server, you will have to download both the binary and source versions. Please note that these instructions are for Windows; Unix users can get similar results by changing slashes and using .sh shell scripts rather than .bat batch files.

  1. Create a folder, such as C:\PlutoInstallation.
  2. Download pluto-1.0.1-rc1.zip and pluto-src-1.0.1-rc1.zip from the Pluto website.
  3. Extract pluto-1.0.1-rc1.zip into C:\PlutoInstallation. It should get extracted in C:\PlutoInstallation\pluto-1.0.1-rc1.
  4. Start Pluto by calling C:\PlutoInstallation\pluto-1.0.1-rc1\bin\startup.bat.

    You are ready to access your Pluto server at http://localhost:8080/pluto/portal.

  5. Extract pluto-src-1.0.1-rc1.zip to C:\PlutoInstallation\PlutoSrc.
  6. Go to C:\PlutoInstallation\PlutoSrc and run maven distribute:all.. This should build and download necessary dependencies required for running common admin tasks.

    Now it is time to install our HelloWorldPortlet.war as a portlet.

  7. First, copy HelloWorldPortlet.war to the C:\PlutoInstallation\portlets directory, creating the directory if necessary.
  8. Rename C:\PlutoInstallation\plutosrc\build.properties.sample to build.properties.
  9. Open build.properties and change it so that maven.tomcat.home points to the Pluto binary installation. In our example, this will be maven.tomcat.home=C:/PlutoInstallation/pluto-1.0.1-rc1.
  10. To install your portlet, go to C:\plutoInstallation\plutosrc\deploy and run maven deploy -Ddeploy=c:\PlutoInstallation\portlets\HelloWorldPortlet.war. You should get a "build successful" message.
  11. In C:\PlutoInstallation\pluto-1.0.1-rc1\webapps, you should see a folder for HelloWorldPortlet.
  12. Now, open the web.xml file of your installed portlet by going to the C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\HelloWorld\WEB-INF\ folder. You will see that a few lines are automatically added to this file, like this:
    <servlet>
    
      <servlet-name>HelloWorld</servlet-name>
         <display-name>HelloWorld Wrapper</display-name>
          <description>Automated generated
          Portlet Wrapper</description>
          <servlet-class>org.apache.pluto.core.PortletServlet
          </servlet-class>
    
          <init-param>
             <param-name>portlet-class</param-name>
             <param-value>com.test.HelloWorld
             </param-value>
          </init-param>
          <init-param>
    
             <param-name>portlet-guid</param-name>
             <param-value>HelloPluto.HelloWorld
             </param-value>
          </init-param>
    </servlet>
  13. Now it's time for us to add this portlet to the page. Go to C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\data. You will find two XML files there: pageregistry.xml and portletentityregistry.xml.
  14. portletentityregistry.xml contains the definition of the portlet. Add these lines to it:
     <application id="5">
       <definition-id>HelloWorld</definition-id>
         <portlet id="1">
           <definition-id>HelloWorld.HelloWorld</definition-id>
    
         </portlet>
        </application>

    The <definition-id> of the application should be the name of the web application folder. The portlet's <definition-id> should be equal to the generated portlet-guid in web.xml.

  15. pageregistry.xml defines which portlets to include on the page. Change it like this:
      <fragment name="p2" type="portlet">
        <property name="portlet" value="5.1"/>
      </fragment>
  16. Restart the Pluto server by first calling shutdown and then startup. Now go back to http://localhost:8080/pluto/portal and click on "Test Link"--it should show our HelloWorld portlet.
  17. The right side of Figure 3 shows what your HelloWorld portlet will look like.

    Thumbnail, click for full-size image.
    Figure 3. Screen shot of portlet screen (click for full-size image)

How a Portal Page Is Created

Figure 4 shows how the separate portlets are assembled by the portal container to create the page.

Portal page creation
Figure 4. Portal page creation

Most portal servers are basically web applications deployed in an application server, using a servlet for handling requests to the portal server. If you take a look inside of your Pluto installation, you will find out that Pluto is a normal web application, deployed in your Tomcat server. Take a look at C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\web.xml and you will find that org.apache.pluto.portalImpl.Servlet is mapped to get all requests pointed at the Pluto server.

Earlier, in "Elements of a Portal Page," we said that a portal page is made up of two types of content. One is content generated by various portlets on the page, and other is content generated by portal server.

In Pluto, whenever the user makes a request, control will go to the servlet. Depending on what page is requested by user, it will determine a list of portlets that need to be displayed. Once it has this list, it will pass control to these portlets in different threads and will collect content generated by them.

As for content contributed by the portal server (things like look and feel of the portal site and the decoration and controls for each portlet), the portal server depends on JSPs in the C:\PlutoInstallation\pluto-1.0.1-rc1\webapps\pluto\WEB-INF\aggregation folder. RootFragment.jsp is the main JSP, which decides the overall look and feel, and alignment. It includes Heads to decide what should be included in the <HEAD> tag of the generated page. Then it uses Banner.jsp to choose what should be displayed in the banner--by default, it will include pluto.png for displaying the banner. TabNavigation.jsp is used to decide the navigation scheme of the portal site. What this means is that you just need to change a few JSPs in this folder to change the whole look and feel of your portal site.

Depending on settings in pageregistry.xml, Pluto will decide how many rows a page should have, and use RowFragment.jsp to render it. It will use ColumnFragment.jsp to render each column. Then PortletFragmentHeader.jsp is used to render the header of every portlet; i.e., the title bar and the controls for minimize and maximize. footer.jsp is used to render the footer of the JSP. If you look at the HTML generated by portal page, you will find out that every portlet window is nothing but content inside a <TD> tag.

Conclusion

For any new technology to be successful, it should have few qualities: first, it should leverage existing technology; second, it should solve common problems of existing technology; and third, it should provide you one more layer of abstraction. (As they say, every layer of abstraction solves half of the problems.)

The Portlet API has a very good chance of succeeding servlet technology, because it is capable of using the existing application server infrastructure. You can call an EJB from your portlet, or you can start and participate in a global transaction controlled by the application server. In other words, your portlet can do pretty much every thing that a servlet can do, in a much more business-logic-centric way.

Portlets provide you with a layer of abstraction because now you no longer have to worry about what HTTP method is used by the client, or create your own infrastructure to capture client events like button clicks. Last but not least, portlets solve most of the common problems of servlets by providing services for things like single-sign-on, personalization, etc.

Resources

Sunil Patil has worked on J2EE technologies for more than five years. His areas of interest include object relational mapping tools, UI frameworks, and portals.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.