Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

The making of MetroSphere, Part 29: Understand the web.xml and portlet.xml files

Nicholas Chase, President, Chase and Chase, Inc.
Nicholas Chase
Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of an interactive development firm in Clearwater, Florida, and is the author of four books on Web development, including XML Primer Plus (Sams).

Summary:  With all of the magic that goes on in the WebSphere® Portal Web interface, it's easy to forget that at its heart, a portlet application is just a collection of servlets and their supporting classes, strung together using the web.xml and portlet.xml files. As we moved to customize the MetroSphere.com experience, we realized that understanding just how these two files fit together was crucial to controlling items such as the initial title of a portlet window. This article explains the major pieces of these two files and how they control what you see in your portlet application.

Date:  09 Apr 2004
Level:  Introductory

Activity:  1489 views
Comments:  

Editor's update

The Web site MetroSphere.com -- the online technical community discussed in this article -- is no longer live. However, the information and screen captures regarding the installation of IBM WebSphere Portal are still accurate and relevant.

In this article, we'll back away from the main MetroSphere application in favor of a no-nonsense look at exactly what all of those items in the web.xml and portlet.xml files really mean. To follow along, you'll need a text editor for looking at and editing these files, as well as a Java compiler for compiling the sample class and as a way to create a WAR file. WebSphere Studio Application Developer (Application Developer) is perfect for these tasks. You should also have a basic understanding of what portlets are and how they work.

The basic portlet

As you might know, a portlet is a subclass of a servlet, so I'll start by creating the simplest of portlets:


Listing 1. A simple portlet that outputs text
package files;

import org.apache.jetspeed.portlet.*;

public class TestPortlet extends PortletAdapter {

  public void init(PortletConfig portletConfig) 
    throws UnavailableException
  {
    super.init( portletConfig );
  }
  
  public void doView (PortletRequest request, PortletResponse response)
     throws PortletException, java.io.IOException
  {

     response.getWriter().println("Hi!");

  }

}

In the portlet application, this portlet simply outputs the text.


The web.xml file

If you create this servlet in Application Developer by choosing New > Servlet, Application Developer populates the web.xml file with basic information about the class and how it fits into the overall Web application. If you simply created the class, however, this doesn't happen. In either case, it's good to understand what all of the information in the file means. Take a look at the default data generated by Application Developer:


Listing 2. Default data generated by Application Developer
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
     "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
 "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app id="WebApp">
    <display-name>PortletTest>/display-name>
    <servlet id="Servlet_1">
        <servlet-name>TestPortlet>/servlet-name>
        <display-name>TestPortlet>/display-name>
        <servlet-class>files.TestPortlet>/servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TestPortlet>/servlet-name>
        <url-pattern>TestPortlet>/url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html>/welcome-file>
        <welcome-file>index.htm>/welcome-file>
        <welcome-file>index.jsp>/welcome-file>
        <welcome-file>default.html>/welcome-file>
        <welcome-file>default.htm>/welcome-file>
        <welcome-file>default.jsp>/welcome-file>
    </welcome-file-list>
</web-app>


By default, Application Developer calls the Web application by the name of the project and uses the name of the class for the servlet name, display name, and URL pattern. You don't, however, have to follow this pattern. You could, for example, construct your file like this:


Listing 3. Sample file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
     "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
 "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app id="WebApp">
    <display-name>PortletTest</display-name>
    <servlet id="Servlet_1">
        <servlet-name>Servlet-name</servlet-name>
        <display-name>Display-name</display-name>
        <servlet-class>files.TestPortlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet-name</servlet-name>
        <url-pattern>TestPortlet</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

For a portlet application, the name of the Web application is irrelevant; it's not used anywhere. The servlet-name elements for servlet and servlet-mapping must match, because that's how they're related together. (Yes, current practice might lean more toward an id attribute, but that's just the way it is.) The url-pattern technically doesn't have to match the servlet-class, but in practice, it works more reliably for a portlet application.

So, take look at what's been done here. First, a servlet has been defined, providing information on how to identify it internally (through the servlet-name) and for the user (through the display-name), should this Web application be accessed directly in a Web application server such as WebSphere Application Server. A class that serves as the basis for the servlet has also been defined, complete with any package information.

Next, mapping information has been provided that tells the application server what servlet to run based on the URL being accessed. Once the URL is matched to the url-pattern, the servlet-name maps back to the original servlet definition. In this way, the URL is mapped back to the actual class to execute.

Tag libraries and web.xml

Before moving on to the portlet.xml file, I'll cover one more useful function in web.xml -- adding JavaServer Pages (JSP) tag libraries:


Listing 4. Adding JSP tag libraries
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
     "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
 "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app id="WebApp">
    <display-name>PortletTest</display-name>
    <servlet id="Servlet_1">
        <servlet-name>Servlet-name</servlet-name>
        <display-name>Display-name</display-name>
        <servlet-class>files.TestPortlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet-name</servlet-name>
        <url-pattern>TestPortlet</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
    <taglib>
        <taglib-uri>/tld/blogtaglib.tld</taglib-uri>
        <taglib-location>/WEB-INF/tld/blogtaglib.tld
        </taglib-location>
    </taglib>
</web-app>

The taglib-uri defines the URL that is listed in the actual taglib tag in a JSP page. It doesn't have to match the actual URL in any way, though here it's similar. The taglib-location is the actual location of the definition file, relative to the current application. This distinction is important. This web.xml file applies only to the PortletTest application. When we made the tag library available to the general portal, we added this information to the overall portal application's web.xml file, where it was relative to that application.

When the servlet has been created and the Web application server has been told about it, the portal application must be told to treat it as a portlet. I'll talk about how to do this in the section discussing the portlet.xml file.


The portlet.xml file

The first step in creating the portlet.xml file is to define the actual portlet application. To do that, you actually need to create the portlet application itself, which is a kind of template, and the concrete portlet application, which gets instantiated:


Listing 5. Creating the portlet application
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN"
 "portlet_1.1.dtd">
<portlet-app-def>
    <portlet-app uid="Portlet-app_uid">
        <portlet-app-name>Portlet-app-name</portlet-app-name>
    </portlet-app>
    <concrete-portlet-app uid="concrete-portlet-app_uid">
        <portlet-app-name>Concrete portlet-app-name</portlet-app-name>
    </concrete-portlet-app>
</portlet-app-def>

Now, before going any further, acknowledge two facts. First, these are obviously not names that you would put on an actual application. It's not that they don't work -- they do -- but they're certainly not descriptive. Because the whole point of this article is to show you what all of these pieces actually mean, I've intentionally chosen names that are easy to trace back.

Second, notice the two uid values. Notice that they are completely different. The uid for the concrete portlet application does not point back to the actual portlet application, though in practice the concrete portlet application typically mirrors the uid for the original application, with some digit or character appended to it to make it unique.

Application settings

Before you add any actual portlets, you can add information about the concrete application itself. In the MetroSphere application, we used this capability to provide database connection information, for example. The information is part of the concrete-portlet-app:


Listing 6. Adding concrete application information
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN"
 "portlet_1.1.dtd">
<portlet-app-def>
    <portlet-app uid="Portlet-app_uid">
        <portlet-app-name>Portlet-app-name</portlet-app-name>
    </portlet-app>
    <concrete-portlet-app uid="concrete-portlet-app_uid">
        <portlet-app-name>Concrete portlet-app-name</portlet-app-name>
        <context-param>
            <param-name>Context-param param-name</param-name>
            <param-value>Context-param param-value</param-value>
        </context-param>
   </concrete-portlet-app>
</portlet-app-def>

Later, you'll see how this information interacts with WebSphere Portal's browser-based administration and with the portlet API.

Adding the portlet

Now that you've created the portlet application, look at how the portlet itself fits in. First, you need to add it to the portlet application:


Listing 7. Adding the portlet to the portlet application
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN"
 "portlet_1.1.dtd">
<portlet-app-def>
    <portlet-app uid="Portlet-app_uid">
        <portlet-app-name>Portlet-app-name</portlet-app-name>
        <portlet id="Portlet_1" href="WEB-INF/web.xml#Servlet_1">
            <portlet-name>Portlet-name</portlet-name>
            <cache>
                <expires>0</expires>
                <shared>NO</shared>
            </cache> 
            <allows>
                <maximized/>
                <minimized/>
            </allows>
            <supports>
               <markup name="html">
                   <view/>
                   <edit/>
               </markup>
            </supports>
        </portlet>
    </portlet-app>
    <concrete-portlet-app uid="concrete-portlet-app_uid">
        <portlet-app-name>Concrete portlet-app-name</portlet-app-name>
        <context-param>
            <param-name>Context-param param-name</param-name>
            <param-value>Context-param param-value</param-value>
        </context-param>
    </concrete-portlet-app>
</portlet-app-def>

This section is defining both the portlet itself and the capabilities it will have when it's instantiated. In some ways, this is like the class definition; it's a template for the object you'll eventually create.

Now, start with the portlet element itself. The id attribute is how you'll identify the portlet; you'll refer to it in the next section when you create the concrete portlet. The href is how you determine the servlet that represents the portlet. The URL:

WEB-INF/web.xml#Servlet_1

tells the portal to look inside this application's web.xml file for a servlet with an id attribute of Servlet_1. If you look back at Listing 2, you'll see that that's the TestPortlet servlet. (For those of you who keep track of these things, this is actually an XPointer reference.)

Now that I've identified the servlet I'm talking about, I can make some statements about it. The first is the portlet name. Next, I'm determining whether the portlet is to be cached, and for how long, in seconds. To expire a portlet immediately, use 0. To cause the server to cache the portlet indefinitely, use -1. I'm also determining whether that cache is to be shared between user sessions.

The allows and supports elements determine the buttons that appear in the upper-right corner of the portlet window. The allows element lets you determine whether the portlet window can be minimized or maximized.

The supports element lets you determine whether the edit, configure, and help buttons will appear, assuming the user has the proper permissions. In other words, if the portlet doesn't support the edit mode, the user won't see the edit icon, even if he or she has the appropriate privileges. The supports element lets you make these decisions based on the markup in use at the time, so you can even determine the markups for which the portlet would appear. For example, if you were viewing the portal in WML on a cell phone, this portlet would not appear because it doesn't support the view mode for the WML markup. (Or any other mode, for that matter.) A portlet must support at least one markup, and the view mode is required for each markup the portlet supports.

Now, the actual concrete portlet needs to be defined.

Adding the concrete portlet

You've got the base portlet, so now you need to define the concrete portlet that serves as the basis for the actual instantiated portlet:


Listing 8. Defining the concrete portlet
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN"
 "portlet_1.1.dtd">
<portlet-app-def>
    <portlet-app uid="Portlet-app_uid">
        <portlet-app-name>Portlet-app-name</portlet-app-name>
        <portlet id="Portlet_1" href="WEB-INF/web.xml#Servlet_1">
             <portlet-name>Portlet-name</portlet-name>
             <cache>
                 <expires>0</expires>
                 <shared>NO</shared>
             </cache> 
             <allows>
                 <maximized/>
                 <minimized/>
                 <resizing />
                 <closed />
             </allows>
             <supports>
                 <markup name="html">
                     <view/>
                 </markup>
             </supports>
        </portlet>
    </portlet-app>
    <concrete-portlet-app uid="concrete-portlet-app_uid">
        <portlet-app-name>Concrete portlet-app-name</portlet-app-name>
        <context-param>
            <param-name>Context-param param-name</param-name>
            <param-value>Context-param param-value</param-value>
        </context-param>
        <concrete-portlet href="#Portlet_1">
            <portlet-name>Concrete Portlet-name</portlet-name>
            <default-locale>en</default-locale>
            <language locale="en">
                <title>Concrete-portlet title</title>
                <title-short>Title-short</title-short>
                <description>Description</description>
                <keywords>keywords</keywords>
            </language>
        </concrete-portlet>
    </concrete-portlet-app>
</portlet-app-def>

Now, notice that the href attribute on the concrete-portlet points back to the id value from the portlet element. That linkage is how the concrete portlet is related back to the actual portlet. From here, determine the name of the portlet, as it will appear when the portlet application is installed or updated, as shown in Figure 1.


Figure 1. The concrete portlet app and concrete portlet show on install
The concrete portlet app and concrete portlet

The rest of the new information here relates to localization. First, I'm setting a default locale for the portlet, and then I'm setting information such as the title (which appears on the portlet window itself), the short-title, and the description, which appears when the user is adding the portlet to the page, as shown in Figure 2.


Figure 2. The concrete portlet title and description appear when searching for portlets
The concrete portlet title and description

You can also set multiple languages, so if the user is looking for a language other than, in this case, English, you can provide information in the appropriate language.


The portlet application versus the concrete portlet application

It's important to understand that while the portlet application defines the basic template for each portlet, it is actually the concrete application and concrete portlets that get instantiated. Notice how Figure 2 shows that it's the concrete portlet application that is displayed when the application is installed, and not the portlet application itself.

Note also that you can have any number of concrete portlets based on a single portlet, and they can have their own title, descriptions, and so on. You can also add concrete portlet-specific information or context parameters:


Listing 9. Adding concrete portlet-specific information
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE portlet-app-def PUBLIC "-//IBM//DTD Portlet Application 1.1//EN"
 "portlet_1.1.dtd">
<portlet-app-def>
    <portlet-app uid="Portlet-app_uid">
        <portlet-app-name>Portlet-app-name</portlet-app-name>
        <portlet id="Portlet_1" href="WEB-INF/web.xml#Servlet_1">
            <portlet-name>Portlet-name</portlet-name>
            <cache>
                <expires>0</expires>
                <shared>NO</shared>
            </cache> 
            <allows>
                <maximized/>
                <minimized/>
                <resizing />
                <closed />
            </allows>
            <supports>
                <markup name="html">
                    <view/>
                </markup>
            </supports>
        </portlet>
    </portlet-app>
    <concrete-portlet-app uid="concrete-portlet-app_uid">
        <portlet-app-name>Concrete portlet-app-name</portlet-app-name>
        <context-param>
            <param-name>Context-param param-name</param-name>
            <param-value>Context-param param-value</param-value>
        </context-param>
        <concrete-portlet href="#Portlet_1">
            <portlet-name>Portlet-name</portlet-name>
            <default-locale>en</default-locale>
            <language locale="en">
                <title>Concrete-portlet title</title>
                <title-short>Title-short</title-short>
                <description>Description</description>
                <keywords>keywords</keywords>
            </language>
            <config-param>
              <param-name>
              Concrete-portlet config-param param-name
              </param-name>
              <param-value>
              Concrete-portlet config-param param-value
              </param-value>
          </config-param>
        </concrete-portlet>
    </concrete-portlet-app>
</portlet-app-def>

Accessing parameters

At this point, I've set two different types of parameters: application settings and portlet settings. I'll discuss the application settings first.

I created application parameters by adding them to the definition of the concrete portlet application. This action makes them available for editing through the administration pages. In the Portal Administration section, click Portlet Applications and highlight the PortletTest.war application. Clicking Modify Parameters gives you an opportunity to change these values, as shown in Figure 3.


Figure 3. The web interface enables you to modify concrete app parameters
The web interface to modify concrete app parameters

You can access both the application setting parameters and the portlet setting parameters from within the portlet itself (some lines in this example have been split for display here):


Listing 10. Accessing the application and portlet setting parameters
package files;

import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlets.*; 

public class TestPortlet extends PortletAdapter {

  public void init(PortletConfig portletConfig) 
    throws UnavailableException
  {
    super.init( portletConfig );
  }
  
  public void doView (PortletRequest request, PortletResponse response)
     throws PortletException, java.io.IOException
  {

     String value = 
     (String)request.getPortletSettings()
        .getApplicationSettings().getAttribute(
             "Context-param param-name"
             );
      response.getWriter().println("Context-param param-name = 
           "+value+"<br />");

      String portletvalue = 
      request.getPortletSettings()
        .getAttribute(
             "Concrete-portlet config-param param-name
             ");
      response.getWriter().println(
           "Concrete-portlet config-param param-name = " 
           + portletvalue
           );

  }

}


Putting it all together

When you put it all together and install the portlet application, adding the portlet to a page shows the concrete portlet title, as well as the parameters you told it to output, as shown in Figure 4:


Figure 4. The final installed portlet instance
The final installed portlet instance

Summary

Although it seems like a lot of extraneous information, the web.xml and portlet.xml files actually give you a great deal of control over what users can do with your portlets and how they appear to users. The web.xml file defines the actual servlet that forms the basis for the portlet. The portlet.xml file creates the portlet application (with its portlet definitions) along with the concrete portlet application and the concrete portlet definitions that link back to it to define what the user sees.


Resources

About the author

Nicholas Chase

Nicholas Chase, a Studio B author, has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, and an Oracle instructor. More recently, he was the Chief Technology Officer of an interactive development firm in Clearwater, Florida, and is the author of four books on Web development, including XML Primer Plus (Sams).

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Sample IT projects
ArticleID=10323
ArticleTitle=The making of MetroSphere, Part 29: Understand the web.xml and portlet.xml files
publish-date=04092004
author1-email=
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).