Chapter 5. Portlet Primer
Prev |  | Next

## Chapter 5. Portlet Primer

### Roy Russo

`<roy@jboss.org>`

## 5.1. JSR 168 Overview

The JSR 168 specification aims at defining porlets that can be used by any JSR168 portlet container also called portals. There are different portals out there with commercial and non-commercial licences. In this chapter we will briefly describe such portlets but for more details you should read the specifications available on the web.

### Note

This section is a brief overview of the JSR 168 Portlet Specification , and it does not cover the topics in great detail. We strongly encourage portlet developers to read the Specification that can be found here .

As of today, JBoss portal is fully JSR168 1.0 compliant, that means that any JSR168 portlet will behave as it should inside the portal.

### 5.1.1. Portal Pages

A portal can be seen as pages with different areas and inside areas, different windows and each window having one portlet.

### 5.1.2. Rendering Modes

A porlet can have different view modes, three modes are defined by the specification but a portal can extend those modes. The 3 modes are:

- VIEW - Generates markup reflecting the current state of the portlet.
- EDIT - Should allow a user to customize the behaviour of the portlet.
- HELP - Should provide some information to the user as to how to use the portlet.

### 5.1.3. Window States

Window states are an indicator of how much page real-estate a portlet should consume on any given page. There are 3 states defined by the specification:

- NORMAL - A portlet shares this page with other portlets.
- MINIMIZED - A portlet may show very little information or none at all.
- MAXIMIZED - A portlet may be the only portlet displayed on this page.

### 5.1.4. Section Status

This overview of the portlet specification, is a work in progress. Check back for more in-depth analsis of the specification, but please read on for real-world cases of how to leverage the specification.

## 5.2. Tutorials

The tutorials contained in this chapter are targetted toward portlet developers. Although they are a good starting and reference point, we do heavily recommend that portlet developers read and understand the Portlet Specification (JSR-168) . We also recommend, using our JBoss Portal User Forums for user-to-user help, when needed.

### 5.2.1. Deploying your first portlet

#### 5.2.1.1. Introduction

This section will introduce the reader to deploying his first portlet in JBoss Portal. It requires you download the HelloWorldPortlet from PortletSwap.com, using this link .

#### 5.2.1.2. Package Structure

Portlets are packaged in war files, just like other JEE applications. A typical portlet war file can also include servlets, resource bundles, images, html, jsps, and other static or dynamic files you would commonly include.

#### 5.2.1.3. The Portlet Class

Included in the download bundle you should have one java source file: HelloWorldPortlet\src\main\org\jboss\portlet\hello\HelloWorldPortlet.java , and it should contain the following:

                      package org.jboss.portlet.hello;

    import javax.portlet.GenericPortlet;
    import javax.portlet.PortletException;
    import javax.portlet.RenderRequest;
    import javax.portlet.RenderResponse;
    import javax.portlet.UnavailableException;
    import java.io.IOException;
    import java.io.PrintWriter;

    public class HelloWorldPortlet extends GenericPortlet
    {
       protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException
       {
          rResponse.setContentType("text/html");
          PrintWriter writer = rResponse.getWriter();
          writer.write("Hello World!");
          writer.close();
       }
    }

Now lets dissect our simplest of portlets:

-     public class HelloWorldPortlet extends GenericPortlet

  All Portlets MUST implement the javax.portlet.GenericPortlet Interface.

-     protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws
                                 PortletException, IOException, UnavailableException

  In this case, our doView will be called when the portlet is asked to render output in VIEW Mode.

-     rResponse.setContentType("text/html");

  Just like in the servlet-world, you must declare what content-type the portlet will be responding in.

-     PrintWriter writer = rResponse.getWriter();
      writer.write("Hello World!");
      writer.close();

  Here we output the text Hello World! in our portlet window.

  ### Note

  Portlets are responsible for generating markup fragments, as they are included on a page and surrounded by other portlets.

#### 5.2.1.4. The Application Descriptors

JBoss Portal requires certain descriptors be included in your portlet war, for different reasons. Some of these descriptors are defined by the Portlet Specification, and some are specific to JBoss Portal.

Now lets explain what each of these does:

- portlet.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
                   version="1.0">
         <portlet>
            <portlet-name>HelloWorldPortlet</portlet-name>
            <portlet-class>org.jboss.portlet.hello.HelloWorldPortlet</portlet-class>
            <supports>
               <mime-type>text/html</mime-type>
               <portlet-mode>VIEW</portlet-mode>
            </supports>
            <portlet-info>
               <title>HelloWorld Portlet</title>
            </portlet-info>
         </portlet>
      </portlet-app>

  This file must adhere to its definition in the Portlet Specification. You may define more than one portlet application in this file.

  -     <portlet-name>HelloWorldPortlet</portlet-name>

    Define your portlet name. It does not have to be the Class name.

  -     <portlet-class>org.jboss.portlet.hello.HelloWorldPortlet</portlet-class>

    The FQN of your portlet class must be declared here.

  -     <supports>
           <mime-type>text/html</mime-type>
           <portlet-mode>VIEW</portlet-mode>
        </supports>

    The supports attributes allow you to declare extra vital information about the portlet. In this case, we are letting the portal know that it will be outputting text/html and only support a VIEW mode.

    ### Note

    A content-type must be declared here for every portlet, and it must match with how the portlet is programmatically responding. Likewise, a portlet mode must be declared here and have a corresponding method in its class. In our case, the VIEW mode will map to the doView() in our class.

  -     <portlet-info>
           <title>HelloWorld Portlet</title>
        </portlet-info>

    The portlet's title will be displayed as the header in the portlet window, when rendered, unless it is overridden programatically.

- portlet-instances.xml

      <deployments>
         <deployment>
            <instance>
               <instance-id>HelloWorldPortletInstance</instance-id>
               <portlet-ref>HelloWorldPortlet</portlet-ref>
            </instance>
         </deployment>
      </deployments>

  This is a JBoss Portal specific descriptor that allows you create an instance of a portlet. The portlet-ref value must match the portlet-name value given in the packaged portlet.xml . The instance-id value can be named anything, but it must match the instance-ref value given in the *-object.xml file we will explore below.

- helloworld-object.xml

      <deployments>
         <deployment>
            <if-exists>overwrite</if-exists>
            <parent-ref>default.default</parent-ref>
            <window>
               <window-name>HelloWorldPortletWindow</window-name>
               <instance-ref>HelloWorldPortletInstance</instance-ref>
               <region>center</region>
               <height>1</height>
            </window>
         </deployment>
      </deployments>

  The *-object.xml is responsible for creating/configuring windows, pages, and even portal instances. In our example, we are creating a portlet window, assigning it to a page, and specifying where it should appear on that page. This is a specific descriptor to JBoss Portal.

  -     <if-exists>overwrite</if-exists>

    Instructs the portal to overwrite or keep this object if it already exists. Possible values are overwrite or keep . Overwrite will destroy the existing object and create a new one based on the content of the deployment. Keep will maintain the existing objct deployment or create a new one if it does not yet exist.

  -     <parent-ref>default.default</parent-ref>

    Tells the portal where this portlet should appear. In this case, default.default specifies that this portlet should appear in the portal instance named default and the page named default .

  -                                         <window-name>HelloWorldPortletWindow</window-name>

    Can be named anything.

  -                                         <instance-ref>HelloWorldPortletInstance</instance-ref>

    The value of instance-ref must match the value of instance-id found in the portlet-instances.xml .

  -     <region>center</region>
        <height>1</height>

    Specify the layout region and order this window will be found on the portal page.

To illustrate the relationship between the descriptors , we have provided this simple diagram

#### 5.2.1.5. Building your portlet

If you have downloaded the sample, you can execute the build.xml with ANT or inside your IDE. Executing the deploy target will compile all src files and produce a helloworldportlet.war under HelloWorldPortlet\helloworldportlet.war.

If you want to create an expanded war directory, after executing the above deploy target, you should execute the explode target.

The above target will produce the following:

This will deflate the helloworldportlet.war, and allow you to deploy it as an expanded directory. It will work just the same, with some additional benefits noted below:

The advantage to expanded war deployments is that you can modify xml descriptors, resource files jsp/jsf pages easily during development. Simply touch the web.xml to have JBoss Application Server hot-deploy the web appllication on a live-running server instance

#### 5.2.1.6. Deploying your portlet

Deploying a portlet is as simple as copying/moving the helloworldportlet.war in to the server deploy directory. Doing this on a running instance of the portal and application server, will trigger a hot-deploy :

    18:25:56,366 INFO  [Server] JBoss (MX MicroKernel) [4.0.3SP1 (build: CVSTag=JBoss_4_0_3_SP1 date=200510231054)] Started in 1m:3s:688ms
    18:26:21,147 INFO  [TomcatDeployer] deploy, ctxPath=/helloworldportlet, warUrl=.../tmp/deploy/tmp35219helloworldportlet-exp.war/

Pointing your browser to http://localhost:8080/portal/ , should yield a view of our HelloWorldPortlet:

### 5.2.2. A Simple JSP Portlet

#### 5.2.2.1. Introduction

This section will introduce the reader to deploying a simple JSP portlet in JBoss Portal. It requires you download the HelloWorldJSPPortlet from PortletSwap.com, using this link .

This portlet will introduce you to using JSPs for view rendering and the portlet taglib for generating links.

#### 5.2.2.2. Package Structure

Portlets are packaged in war files, just like other JEE applications. A typical portlet war file can also include servlets, resource bundles, images, html, jsps, and other static or dynamic files you would commonly include.

#### 5.2.2.3. The Portlet Class

Included in the download bundle you should have one java source file: HelloWorldPortlet\src\main\org\jboss\portlet\hello\HelloWorldJSPPortlet.java , and it should contain the following:

    package org.jboss.portlet.hello;

    import javax.portlet.ActionRequest;
    import javax.portlet.ActionResponse;
    import javax.portlet.GenericPortlet;
    import javax.portlet.PortletException;
    import javax.portlet.PortletRequestDispatcher;
    import javax.portlet.RenderRequest;
    import javax.portlet.RenderResponse;
    import javax.portlet.UnavailableException;
    import java.io.IOException;

    public class HelloWorldJSPPortlet extends GenericPortlet
    {
       protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException
       {
          rResponse.setContentType("text/html");

          String sYourName = (String) rRequest.getParameter("yourname");

          if(sYourName != null)
          {
             rRequest.setAttribute("yourname", sYourName);
             PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/view2.jsp");
             prd.include(rRequest, rResponse);
          }
          else
          {
             PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/view.jsp");
             prd.include(rRequest, rResponse);
          }
       }

       public void processAction(ActionRequest aRequest, ActionResponse aResponse) throws PortletException, IOException, UnavailableException
       {
          String sYourname = (String) aRequest.getParameter("yourname");

          // do something

          aResponse.setRenderParameter("yourname", sYourname);
       }

       protected void doHelp(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException
       {
          rResponse.setContentType("text/html");
          PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/help.jsp");
          prd.include(rRequest, rResponse);
       }

       protected void doEdit(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException
       {
          rResponse.setContentType("text/html");
          PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/edit.jsp");
          prd.include(rRequest, rResponse);
       }
    }

Now lets look at some of our methods:

-                                protected void doHelp

                                 AND

                                 protected void doEdit

  Support for these Modes must be declared in the portlet.xml. They will be triggered when a user clicks on the respective icons in the portlet window titlebar, or through generated links within the portlet.

-     public void processAction(ActionRequest aRequest, ActionResponse aResponse) throws PortletException, IOException, UnavailableException
      {
         String sYourname = (String) aRequest.getParameter("yourname");

         // do something

         aResponse.setRenderParameter("yourname", sYourname);
      }

  This method will be triggered upon clicking on an ActionURL from our view.jsp. It will retrieve yourname from the HTML form, and pass it along as a renderParameter to the doView().

-     rResponse.setContentType("text/html");

  Just like in the servlet-world, you must declare what content-type the portlet will be responding in.

-     protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws PortletException, IOException, UnavailableException

  In this case, our doView, is responsible for dispatching to the appropriate jsp view.jsp or view2.jsp , depending on the existence of the yourname parameter passed in from the processAction .

#### 5.2.2.4. The Application Descriptors

JBoss Portal requires certain descriptors be included in your portlet war, for different reasons. Some of these descriptors are defined by the Portlet Specification, and some are specific to JBoss Portal. For brevity, we only discuss the portlet.xml descriptor here. For discussion on the other descriptors, please view Section 5.2.1.4, “The Application Descriptors” or the chapter on descriptors: Section 6.1, “Portlet Descriptors” .

- portlet.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
                   version="1.0">
         <portlet>
            <portlet-name>HelloWorldJSPPortlet</portlet-name>
            <portlet-class>org.jboss.portlet.hello.HelloWorldJSPPortlet</portlet-class>
            <supports>
               <mime-type>text/html</mime-type>
               <portlet-mode>VIEW</portlet-mode>
               <portlet-mode>EDIT</portlet-mode>
               <portlet-mode>HELP</portlet-mode>
            </supports>
            <portlet-info>
               <title>HelloWorld JSP Portlet</title>
            </portlet-info>
         </portlet>
      </portlet-app>

  This file must adhere to its definition in the Portlet Specification. You may define more than one portlet application in this file.

  ### Note

  This sample portlet supports 3 view modes: VIEW, EDIT, and HELP. The supported modes must be declared in the portlet.xml using the portlet-mode tag. .

#### 5.2.2.5. JSP files and the portlet taglib

Of importance in this tutorial are the two view jsps. The first, allows the user to input his name, which is then posted to the processAction method in our portlet class, set as a renderParameter , then the render method is invoked (in our case its the doView , which then dispatches to our view2.jsp .

Now lets have a look at our view.jsp :

    <%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

    <portlet:defineObjects/>

    <div align="center">
       This is a simple HelloWorld JSP Portlet. Type in a name and it will dispatch to the view2.jsp to print out your name.
       <br/>

       <form action="<portlet:actionURL><portlet:param name="page" value="mainview"/></portlet:actionURL>"
             method="POST">
          Name:<br/>
          <input type="text" name="yourname"/>
       </form>
       <br/>
       You can also link to other pages, using a renderURL, like <a
          href="<portlet:renderURL><portlet:param name="yourname" value="Roy Russo"></portlet:param></portlet:renderURL>">this</a>.
    </div>

-                                <%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

  Define the portlet taglib. You do not need to bundle the portlet taglib, JBoss Portal will handle that for you.

-     <portlet:defineObjects/>

  Calling defineObjects creates implicit objects in this jsp, that you can access, like: renderRequest, actionRequest, portletConfig .

-                                <form action="<portlet:actionURL><portlet:param name="page" value="mainview"/></portlet:actionURL>" method="POST">

  We create an HTML form, but generate the URL it will post to, using the portlet tag library. In this case, notice how we are creating an actionURL , which will activate out processAction method, passing in any input parameters in the form.

-     <a href="<portlet:renderURL><portlet:param name="yourname" value="Roy Russo"></portlet:param></portlet:renderURL>">

  Likewise, we are able to create a link to our doView , by simply creating it with a renderURL , that passes in our yourname parameter.

#### 5.2.2.6. Building your portlet

If you have downloaded the sample, you can execute the build.xml with ANT or inside your IDE. Executing the deploy target will compile all src files and produce a helloworldportlet.war under HelloWorldPortlet\helloworldjspportlet.war.

If you want to create an expanded war directory, after executing the above deploy target, you should execute the explode target.

The above target will produce the following:

This will deflate the helloworldjspportlet.war, and allow you to deploy it as an expanded directory. It will work just the same, with some additional benefits noted below:

The advantage to expanded war deployments is that you can modify xml descriptors, resource files jsp/jsf pages easily during development. Simply touch the web.xml to have JBoss Application Server hot-deploy the web appllication on a live-running server instance

#### 5.2.2.7. Deploying your portlet

Deploying a portlet is as simple as copying/moving the helloworldjspportlet.war in to the server deploy directory. Doing this on a running instance of the portal and application server, will trigger a hot-deploy :

    15:54:34,234 INFO  [Server] JBoss (MX MicroKernel) [4.0.4.CR2 (build: CVSTag=JBoss_4_0_4_CR2 date=200603311500)] Started in 1m:9s:766ms
    15:55:04,062 INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjspportlet, warUrl=.../tmp/deploy/tmp57782helloworldjspportlet-exp.war/

Pointing your browser to http://localhost:8080/portal/ , should yield a view of our HelloWorldPortlet:

### 5.2.3. A Simple JSF Portlet

#### 5.2.3.1. Introduction

This section will introduce the reader to deploying a simple JSF portlet in JBoss Portal. It requires you download the HelloWorldJSFPortlet from PortletSwap.com, using this link .

This portlet will introduce you to leveraging the JSF framework in portlet development.

#### 5.2.3.2. Package Structure

Portlets are packaged in war files, just like other JEE applications. A typical portlet war file can also include servlets, resource bundles, images, html, jsps, and other static or dynamic files you would commonly include.

Like a typical JSF application, we also package our faces-config.xml that defines our managed-beans, converters, validators, navigation rules, etc...

### Note

When deploying on JBoss Application Seever, you do not need to package the myfaces libraries with your portlet application. JBoss AS already bundles these libraries by default under JBOSS_HOME/server/default/deploy/jbossweb-tomcat55.sar/jsf-libs/

#### 5.2.3.3. The Application Descriptors

JBoss Portal requires certain descriptors be included in your portlet war, for different reasons. Some of these descriptors are defined by the Portlet Specification, and some are specific to JBoss Portal. For brevity, we only discuss the portlet.xml and faces-config.xml descriptors here. For discussion on the other descriptors, please view Section 5.2.1.4, “The Application Descriptors” or the chapter on descriptors: Section 6.1, “Portlet Descriptors” .

- portlet.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
                   version="1.0">
         <portlet>
            <portlet-name>HelloWorldJSFPortlet</portlet-name>
            <portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class>
            <init-param>
               <name>default-view</name>
               <value>/WEB-INF/jsp/index.jsp</value>
            </init-param>
            <supports>
               <mime-type>text/html</mime-type>
               <portlet-mode>VIEW</portlet-mode>
            </supports>
            <portlet-info>
               <title>HelloWorld JSF Portlet</title>
            </portlet-info>
         </portlet>
      </portlet-app>

  This file must adhere to its definition in the Portlet Specification. You may define more than one portlet application in this file. Now lets look at the portions that deal with our use of JSF:

  - Here we define our portlet class, as we normally would. However, note the use of the MyFacesGenericPortlet. In this case, we will allow the MyFacesGenericPortlet to handle all requests/responses from our users:

        <portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class>

    ### Note

    If you wanted to add more functionality to your JSF portlet, not included in the MyFacesGenericPortlet, you could sublass it and create your own Class.

  - We need to initialize the portlet with a default view page for it to render, much like a welcome page:

        <init-param>
           <name>default-view</name>
           <value>/WEB-INF/jsp/index.jsp</value>
        </init-param>

- faces-config.xml

      <?xml version="1.0"?>
      <!DOCTYPE faces-config PUBLIC
         "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN"
         "http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
      <faces-config>
         <managed-bean>
            <description>Basic UserBean</description>
            <managed-bean-name>user</managed-bean-name>
            <managed-bean-class>org.jboss.portlet.hello.bean.User</managed-bean-class>
            <managed-bean-scope>session</managed-bean-scope>
         </managed-bean>
         <navigation-rule>
            <navigation-case>
               <from-outcome>done</from-outcome>
               <to-view-id>/WEB-INF/jsp/result.jsp</to-view-id>
            </navigation-case>
         </navigation-rule>
      </faces-config>

  There is nothing special about the faces-config.xml included here. This application would work just as well outside of a portlet as it would inside a portlet container. In the above lines, we define a basic User Bean and a navigation rule to handle the submittal of the original form on the index.jsp.

#### 5.2.3.4. The JSP files

#### 5.2.3.5. Building your portlet

If you have downloaded the sample, you can execute the build.xml with ANT or inside your IDE. Executing the deploy target will compile all src files and produce a helloworldjsfportlet.war under HelloWorldJSFPortlet\helloworldjsfportlet.war.

If you want to create an expanded war directory, after executing the above deploy target, you should execute the explode target.

The above target will produce the following:

This will deflate the helloworldjsfportlet.war, and allow you to deploy it as an expanded directory. It will work just the same, with some additional benefits noted below:

The advantage to expanded war deployments is that you can modify xml descriptors, resource files jsp/jsf pages easily during development. Simply touch the web.xml to have JBoss Application Server hot-deploy the web application on a live-running server instance

#### 5.2.3.6. Deploying your portlet

Deploying a portlet is as simple as copying/moving the helloworldjsfportlet.war in to the server deploy directory. Doing this on a running instance of the portal and application server, will trigger a hot-deploy :

    22:30:03,093 INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjsfportlet, warUrl=.../tmp/deploy/tmp5571helloworldjsfportlet-exp.war/
    22:30:03,312 INFO  [FacesConfigurator] Reading standard config org/apache/myfaces/resource/standard-faces-config.xml
    22:30:03,390 INFO  [FacesConfigurator] Reading config jar:file:/C:/jboss-4.0.4.CR2/server/default/tmp/deploy/tmp5504jboss-portal.sar-contents/lib/jsf-facelets.jar!/META-INF/faces-config.xml
    22:30:03,406 INFO  [FacesConfigurator] Reading config jar:file:/C:/jboss-4.0.4.CR2/server/default/tmp/deploy/tmp5504jboss-portal.sar-contents/lib/tomahawk.jar!/META-INF/faces-config.xml
    22:30:03,468 INFO  [FacesConfigurator] Reading config /WEB-INF/faces-config.xml
    22:30:03,484 ERROR [LocaleUtils] Locale name null or empty, ignoring
    22:30:03,640 INFO  [MyFacesGenericPortlet] PortletContext 'C:\jboss-4.0.4.CR2\server\default\.\tmp\deploy\tmp5571helloworldjsfportlet-exp.war\' initialized.

Pointing your browser to http://localhost:8080/portal/ , should yield a view of our HelloWorldJSFPortlet:

Prev | Up | Next
Chapter 4. Upgrading 2.2 - 2.4 | Home | Chapter 6. XML Descriptors