Chapter 5. Portlet Primer
Prev |  | Next

## Chapter 5. Portlet Primer

### Roy Russo

`<roy@jboss.org>`

### Chris Laprun

`<chris.laprun@jboss.com>`

### Thomas Heute

`<thomas.heute@jboss.com>`

## 5.1. JSR-168 Overview

The JSR-168 Portlet Specification aims at defining portlets that can be used by any JSR-168 portlet container, also known as a portal. There are different portals with commercial and non-commercial licenses. This chapter gives a brief overview of the JSR-168 Portlet Specification. Portlet developers are strongly encouraged to read the JSR-168 Portlet Specification.

JBoss Portal is fully JSR-168 compliant, which means any JSR-168 portlet behaves 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 portlet can have different view modes. Three modes are defined by the JSR-168 specification, but a portal can extend those modes. The three modes are:

- `view` - generates markup reflecting the current state of the portlet.

- `edit` - allows a user to customize the behavior of the portlet.

- `help` - provides 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 consumes on any given page. The three states defined by the JSR-168 specification are:

- `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 JSR-168 Portlet Specification is a work in progress. Check back for more in-depth analsis of the specification. The sections following here after contain real-world cases for 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, it is highly recommend that portlet developers read and understand the JSR-168 Portlet Specification. Use the JBoss Portal User Forums for user-to-user help.

### 5.2.1. Deploying your first Portlet

#### 5.2.1.1. Introduction

This section describes how to deploy a portlet in JBoss Portal. Before proceeding, download the HelloWorldPortlet from JBoss PortletSwap.

#### 5.2.1.2. Package Structure

Like other Java Platform, Enterprise Edition (Java EE) applications, portlets are packaged in WAR files. A typical portlet WAR file can include servlets, resource bundles, images, HTML, JavaServer™ Pages (JSP™), and other static or dynamic files. The following is an example of the directory structure of the HelloWorldPortlet portlet:

#### 5.2.1.3. Portlet Classes

The following is the `HelloWorldPortlet/src/main/org/jboss/portlet/hello/HelloWorldPortlet.java` Java source file, which comes bundled with the HelloWorldPortlet:

    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();
    	}

    }

    public class HelloWorldPortlet extends GenericPortlet

  All portlets must implement the `javax.portlet.Portlet` interface. The portlet API provides a convenient implementation of this interface, in the form of the `javax.portlet.GenericPortlet` class, which among other things, implements the `Portlet render` method to dispatch to abstract mode-specific methods to make it easier to support the standard portlet modes. As well, it provides a default implementation for the `processAction`, `init` and `destroy` methods. It is recommended to extend `GenericPortlet` for most cases.

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

  As we extend from `GenericPortlet`, and are only interested in supporting the `view` mode, only the `doView` method needs to be implemented, and the `GenericPortlet` `render` implemention calls our implementation when the `view` mode is requested.

    rResponse.setContentType("text/html");

  As in the servlet world, you must declare what content-type the portlet will be responding in. Do this before starting to write content, or the portlet will throw an exception.

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

  This produces the `Hello World!` text in our portlet window.

### Markup Fragments

Portlets are responsible for generating markup fragments, as they are included on a page and are surrounded by other portlets. In particular, this means that a portlet outputting HTML must not output any markup that cannot be found in a `<body>` element.

#### 5.2.1.4. Application Descriptors

JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the JSR-168 Portlet Specification, and others are specific to JBoss Portal. The following is an example of the directory structure of the HelloWorldPortlet portlet:

To create the `WEB-INF/` and `META-INF/` directories, extract the `helloworldportlet.war` file.

The following is an example of the `HelloWorldPortlet/WEB-INF/portlet.xml` file. This file must adhere to its definition in the JSR-168 Portlet Specification. You may define more than one portlet application in this file:

    <?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>

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

  Define the portlet name. It does not have to be the class name.

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

  The Fully Qualified Name (FQN) of your portlet class must be declared here.

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

  The `<supports>` element declares all of the markup types that a portlet supports in the `render` method. This is accomplished via the `<mime-type>` element, which is required for every portlet. The declared MIME types must match the capability of the portlet. As well, it allows you to pair which modes and window states are supported for each markup type. All portlets must support the `view` portlet mode, so this does not have to be declared. Use the `<mime-type>` element to define which markup type your portlet supports, which in this example, is `text/html`. This section tells the portal that it only outputs text and HTML, and that it only supports the `view` mode.

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

  When rendered, the portlet's title is displayed as the header in the portlet window, unless it is overridden programmatically. In this example, the title would be `HelloWorld Portlet`.

The `HelloWorldPortlet/WEB-INF/portlet-instances.xml` file is a JBoss Portal specific descriptor, that allows you to create instances of portlets. The `<portlet-ref>` value must match the `<portlet-name>` value given in the `HelloWorldPortlet/WEB-INF/portlet.xml` file. The `<instance-id>` value can be named anything, but it must match the `<instance-ref>` value given in the `*-object.xml` file, which in this example, would be the `HelloWorldPortlet/WEB-INF/helloworld-object.xml` file.

The following is an example of the `HelloWorldPortlet/WEB-INF/portlet-instances.xml` file:

    <?xml version="1.0" standalone="yes"?>
    <!DOCTYPE deployments PUBLIC
       "-//JBoss Portal//DTD Portlet Instances 2.6//EN"
       "http://www.jboss.org/portal/dtd/portlet-instances_2_6.dtd">
    <deployments>
       <deployment>
          <instance>
             <instance-id>HelloWorldPortletInstance</instance-id>
             <portlet-ref>HelloWorldPortlet</portlet-ref>
          </instance>
       </deployment>
    </deployments>

The `*-object.xml` file is a JBoss Portal specific descriptor that allow users to define the structure of their portal instances, and create and configure their windows and pages. In the following example:

- a portlet window is created.

- specifies that the window displays the markup generated by the `HelloWorldPortletInstance` portlet instance.

- the window is assigned to the `default.default` page.

- the `<region>` element specifies where the window appears on the page.

The following is an example `HelloWorldPortlet/WEB-INF/helloworld-object.xml` file:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE deployments PUBLIC
       "-//JBoss Portal//DTD Portal Object 2.6//EN"
       "http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
    <deployments>
       <deployment>
          <parent-ref>default.default</parent-ref>
          <if-exists>overwrite</if-exists>
          <window>
             <window-name>HelloWorldPortletWindow</window-name>
             <instance-ref>HelloWorldPortletInstance</instance-ref>
             <region>center</region>
             <height>1</height>
          </window>
       </deployment>
    </deployments>

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

  Tells the portal where this portlet appears. In this case, `default.default` specifies that the portlet appears in the portal instance named `default`, and on the page named `default`.

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

  Instructs the portal to overwrite or keep this object if it already exists. Accepted values are `overwrite` and `keep`. The `overwrite` option destroys the existing object, and creates a new one based on the content of the deployment. The `keep` option maintains the existing object deployment, or creates a new one if it does not exist.

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

  A unique name given to the portlet window. This can be named anything.

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

  The value of `<instance-ref>` must match the value of one of the `<instance-id>` elements found in the `HelloWorldPortlet/WEB-INF/portlet-instances.xml` file.

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

  Specifies where the window appears within the page layout.

The following diagram illustrates the relationship between the `portlet.xml`, `portlet-instances.xml`, and `helloworld-object.xml` descriptors:

JBoss Portal 2.6 introduces the notion of content-type, which is a generic mechanism to specify what content displayed by a given portlet window. The `window` section of the previous example, `HelloWorldPortlet/WEB-INF/helloworld-object.xml`, can be re-written to take advantage of the new content framework. The following is an example deployment descriptor that uses the new content framework:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE deployments PUBLIC
       "-//JBoss Portal//DTD Portal Object 2.6//EN"
       "http://www.jboss.org/portal/dtd/portal-object_2_6.dtd">
    <deployments>
       <deployment>
          <parent-ref>default.default</parent-ref>
          <if-exists>overwrite</if-exists>
          <window>
             <window-name>HelloWorldPortletWindow</window-name>
             <content>
                <content-type>portlet</content-type>
                <content-uri>HelloWorldPortletInstance</content-uri>
             </content>
             <region>center</region>
             <height>1</height>
          </window>
       </deployment>
    </deployments>

This declaration is equivalent to the previous `HelloWorldPortlet/WEB-INF/helloworld-object.xml` example. Use `<content-type>` to specify the content to display. In this example, the content being displayed by the `HelloWorldPortletWindow` is a `portlet`. The `<content-uri>` element specifies which content to display, which in this example, is the `HelloWorldPortletInstance`:

    <content>
       <content-type>portlet</content-type>
       <content-uri>HelloWorldPortletInstance</content-uri>
    </content>

To display certain content or a file, use the `cms` content-type, with the `<content-uri>` element being the path to the file in the CMS. This behavior is pluggable: you can plug in almost any type of content.

#### 5.2.1.5. Building your Portlet

The `HelloWorldPortlet.zip` file contains a pre-compiled `helloworldportlet.war` file; however, to manually build the `helloworldportlet.war` file:

1. Change into the `HelloWorldPortlet/` directory, and remove the existing `helloworldportlet.war` file.

2. If required, edit the `HelloWorldPortlet/src/main/org/jboss/portlet/hello/HelloWorldPortlet.java` file, and the application descriptors in the `HelloWorldPortlet/src/resources/helloworldportlet-war/WEB-INF/` directory.

3. Change into `HelloWorldPortlet/` directory, and run the ant deploy command. On Windows, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the `helloworldportlet.war` file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP pages. To expand the `helloworldportlet.war` file:

1. If you do not have the `HelloWorldPortlet/helloworldportlet.war` file, change into the `HelloWorldPortlet/` directory, and run the ant deploy command. This creates the `helloworldportlet.war` file.

2. To expand the WAR file, change into the `HelloWorldPortlet/` directory, and run the ant explode command. On Windows, the output will be similar to the following:

Note: the directory names will be different for your system.

The ant explode command creates a directory structure such as the following:

The expanded WAR file and the application descriptors are located in the `HelloWorldPortlet/output/lib/exploded/helloworldportlet.war/WEB-INF/` directory.

#### 5.2.1.6. Deploying your Portlet

If you did not expand the `helloworldportlet.war` file, copy the `HelloWorldPortlet/helloworldportlet.war` file into the correct JBoss AS or JBoss EAP `deploy/` directory. If you expanded the `helloworldportlet.war` file, copy the `HelloWorldPortlet/output/lib/exploded/helloworldportlet.war/` directory into the correct JBoss AS or JBoss EAP `deploy/` directory. For example, if you are using the `default` JBoss AS profile, copy the WAR file or the expanded directory into the `$JBOSS_HOME/server/default/deploy/` directory.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet:

    INFO  [TomcatDeployer] deploy, ctxPath=/helloworldportlet,
    warUrl=.../tmp/deploy/tmp35219helloworldportlet-exp.war/

To see the HelloWorldPortlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldPortlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the `$JBOSS_HOME/server/`configuration`/deploy/helloworldportlet.war/WEB-INF/web.xml` file. This only works if you copied the `HelloWorldPortlet/output/lib/exploded/helloworldportlet.war/` directory into the JBoss AS or JBoss EAP `deploy/` directory. On Linux, run the touch $JBOSS_HOME/server/`configuration`/deploy/helloworldportlet.war/WEB-INF/web.xml command to re-deploy the HelloWorldPortlet.

Re-deploying the HelloWorldPortlet produces output to the JBoss AS or JBoss EAP console, similar to the following:

    INFO  [TomcatDeployer] undeploy, ctxPath=/helloworldportlet,
    warUrl=.../deploy/helloworldportlet.war/
    INFO  [TomcatDeployer] deploy, ctxPath=/helloworldportlet,
    warUrl=.../deploy/helloworldportlet.war/

### 5.2.2. An example JavaServer™ Pages (JSP™) portlet

#### 5.2.2.1. Introduction

This section describes how to deploy a JSP™ portlet in JBoss Portal. Before proceeding, download the HelloWorldJSPPortlet from JBoss PortletSwap. The HelloWorldJSPPortlet demonstrates how to use JSP pages for view rendering, and the portlet tag library (taglib) for generating links.

#### 5.2.2.2. Package Structure

The application descriptors for the HelloWorldJSPPortlet portlet are similar to those from the HelloWorldPortlet (Section 5.2.1.4, “Application Descriptors”). Refer to Section 6.2, “Portlet Descriptors” for further information about application descriptors.

The HelloWorldJSPPortlet portlet contains the traditional portlet and JBoss Portal specific application descriptors. The following is an example of the directory structure of the HelloWorldJSPPortlet portlet:

To create the `WEB-INF/` and `META-INF/` directories, extract the `helloworldjspportlet.war` file.

#### 5.2.2.3. Portlet Classes

The HelloWorldJSPPortlet contains the `HelloWorldJSPPortlet/src/main/org/jboss/portlet/hello/HelloWorldJSPPortlet.java` file:

    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);
       }
    }

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

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

  Support for these modes must be declared in the `HelloWorldJSPPortlet/WEB-INF/portlet.xml` file. They are 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 is triggered when a user clicks on an `actionURL`, which is defined in the `HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp` file. This retrieves `yourname` from the HTML form, and passes it as a `aResponse.setRenderParameter` to the `doView()` method.

    rResponse.setContentType("text/html");

  As in the servlet world, you must declare what content-type the portlet will be responding in. Do this before starting to write content, or the portlet throws an exception.

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

  The `doView` implementation is responsible for dispatching to the appropriate JSP, `HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp` or `HelloWorldJSPPortlet/WEB-INF/jsp/view2.jsp`, depending on the existence of the `yourname` parameter passed in from `processAction`.

#### 5.2.2.4. JSP™ files and the Portlet Tag Library

The `HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp` and `HelloWorldJSPPortlet/WEB-INF/jsp/view2.jsp` JSP™ files are included in the HelloWorldJSPPortlet portlet. The `view.jsp` file allows a user to input their name. This is then posted to the `processAction` method in the portlet class, which is set as a `aResponse.setRenderParameter`. The `doView` `render` method is invoked, which dispatches to the `view2.jsp` JSP:

The following is an example of the `HelloWorldJSPPortlet/WEB-INF/jsp/view.jsp` file:

    <%@ 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 handles this for you.

    <portlet:defineObjects/>

  Calling `defineObjects` makes available implicit objects in the JSP, such as `renderRequest`, `actionRequest`, and `portletConfig`.

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

  A HTML form is created. This form posts to the URL defined by the portlet taglib. In this example, an `actionURL` is created, that activates the `processAction` method, which passes the input parameters from the form.

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

  You can create a link to the `doView` method by creating a `renderURL`, which passes the `yourname` parameter.

#### 5.2.2.5. Building your JSP™ portlet

The `HelloWorldJSPPortlet.zip` file contains a pre-compiled `helloworldjspportlet.war` file; however, to manually build the `helloworldjspportlet.war` file:

1. Change into the `HelloWorldJSPPortlet/` directory, and remove the existing `helloworldjspportlet.war` file.

2. If required, edit the `HelloWorldJSPPortlet/src/main/org/jboss/portlet/hello/HelloWorldJSPPortlet.java` file, and the application descriptors in the `HelloWorldJSPPortlet/src/resources/helloworldjspportlet-war/WEB-INF/` directory.

3. Change into `HelloWorldJSPPortlet/` directory, and run the ant deploy command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the `helloworldjspportlet.war` file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP™ pages. To expand the `helloworldjspportlet.war` file:

1. If you do not have the `HelloWorldJSPPortlet/helloworldjspportlet.war` file, change into the `HelloWorldJSPPortlet/` directory, and run the ant deploy command. This creates the `helloworldjspportlet.war` file.

2. To expand the WAR file, change into the `HelloWorldJSPPortlet/` directory, and run the ant explode command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

The ant explode command creates a directory structure such as the following:

The expanded WAR file and the application descriptors are located in the `HelloWorldJSPPortlet/output/lib/exploded/helloworldjspportlet.war/WEB-INF/` directory.

#### 5.2.2.6. Deploying your JSP™ portlet

If you did not expand the `helloworldjspportlet.war` file, copy the `HelloWorldJSPPortlet/helloworldjspportlet.war` file into the correct JBoss AS or JBoss EAP `deploy/` directory. If you expanded the `helloworldjspportlet.war` file, copy the `HelloWorldJSPPortlet/output/lib/exploded/helloworldjspportlet.war/` directory into the correct JBoss AS or JBoss EAP `deploy/` directory. For example, if you are using the `default` JBoss AS profile, copy the WAR file or the expanded directory into the `$JBOSS_HOME/server/default/deploy/` directory.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet:

    INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjspportlet,
    warUrl=.../deploy/helloworldjspportlet.war/

To see the HelloWorldJSPPortlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldJSPPortlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the `$JBOSS_HOME/server/`configuration`/deploy/helloworldjspportlet.war/WEB-INF/web.xml` file. This only works if you copied the `HelloWorldJSPPortlet/output/lib/exploded/helloworldjspportlet.war/` directory into the JBoss AS or JBoss EAP `deploy/` directory. On Linux, run the touch $JBOSS_HOME/server/`configuration`/deploy/helloworldjspportlet.war/WEB-INF/web.xml command to re-deploy the HelloWorldJSPPortlet.

Re-deploying the HelloWorldJSPPortlet produces output to the JBoss AS or JBoss EAP console, similar to the following:

    INFO  [TomcatDeployer] undeploy, ctxPath=/helloworldjspportlet,
    warUrl=.../deploy/helloworldjspportlet.war/
    INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjspportlet,
    warUrl=.../deploy/helloworldjspportlet.war/

### 5.2.3. An example Sun™ JSF Reference Implementation (RI) portlet

#### 5.2.3.1. Introduction

This section describes how to deploy a JSF portlet in JBoss Portal, using the Apache MyFaces JSF implementation in JBoss AS and JBoss EAP. Before proceeding, download the HelloWorldJSFSunRIPortlet from JBoss PortletSwap.

#### 5.2.3.2. Package Structure

JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the JSR-168 Portlet Specification, and others are specific to JBoss Portal. Like a typical JSF application, the HelloWorldJSFSunRIPortlet package contains a `faces-config.xml` file that defines managed-beans, converters, validators, navigation rules, and so on. The following is an example of the directory structure of the HelloWorldJSFSunRIPortlet portlet:

To create the `WEB-INF/` and `META-INF/` directories, extract the `helloworldjsfsunriportlet.war` file.

### Bundled Sun JSF RI

JBoss AS version 4.2.`x` and JBoss EAP bundle the Sun™ JSF RI libraries in the `$JBOSS_HOME/server/default/deploy/jboss-web.deployer/jsf-libs/` directory. Therefore, you do not need to package the Sun JSF RI libraries with your portlet application.

#### 5.2.3.3. Application Descriptors

Only the `portlet.xml`, `faces-config.xml`, and `web.xml` descriptors are described here. For more information about application descriptors, refer to Section 5.2.1.4, “Application Descriptors” and Section 6.2, “Portlet Descriptors”.

The following is an example of the `HelloWorldJSFSunRIPortlet/WEB-INF/portlet.xml` file. This file must adhere to its definition in the JSR-168 Portlet Specification. You may define more than one portlet application in this file:

    <?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>com.sun.faces.portlet.FacesPortlet</portlet-class>
          <init-param>
             <name>com.sun.faces.portlet.INIT_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>

    <portlet-class>com.sun.faces.portlet.FacesPortlet</portlet-class>

  This specifies that the `com.sun.faces.portlet.FacesPortlet` handles all requests and responses from the users. This class is part of the `HelloWorldJSFSunRIPortlet/WEB-INF/lib/jsf-portlet.jar` file.

    <init-param>
       <name>com.sun.faces.portlet.INIT_VIEW</name>
       <value>/WEB-INF/jsp/index.jsp</value>
    </init-param>

  You must initialize the portlet with a default page to render, similar to a welcome page.

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

  The `<supports>` element allows you to declare all of the markup types that a portlet supports in the `render` method. This is accomplished via the `<mime-type>` element, which is required for every portlet. The declared MIME types must match the capability of the portlet. As well, it allows you to pair which modes and window states are supported for each markup type. All portlets must support the `view` portlet mode, so this does not have to be declared. Use the `<mime-type>` element to define which markup type your portlet supports, which in this example, is `text/html`. This section tells the portal that it only outputs text and HTML, and that it only supports the `view` mode.

The following is an example `HelloWorldJSFSunRIPortlet/WEB-INF/faces-config.xml` file:

    <?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>

Without the `faces-config.xml` file, the application would work the same outside of the portlet as it would inside a portlet container. In this example, a basic user bean, `<managed-bean-name>user</managed-bean-name>`, and a navigation rule are defined, which handle the submission of the original form in the `HelloWorldJSFSunRIPortlet/WEB-INF/jsp/index.jsp` file.

The following is an example of the `Faces Servlet` and `Faces Servlet Mapping` sections from the `HelloWorldJSFSunRIPortlet/WEB-INF/web.xml` file:

    <?xml version="1.0"?>
    <!DOCTYPE web-app PUBLIC
       "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
       "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>

        <!-- Faces Servlet -->
        <servlet>
            <servlet-name>Faces Servlet</servlet-name>
            <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>

        <!-- Faces Servlet Mapping -->
        <servlet-mapping>
            <servlet-name>Faces Servlet</servlet-name>
            <url-pattern>*.jsf</url-pattern>
        </servlet-mapping>

    </web-app>

For Sun JSF RI portlets, the `Faces Servlet` and `Faces Servlet Mapping` sections are required to associate files with the `.jsf` extension to the Apache MyFaces servlet.

### Classes for the JSF-Portlet bridge are not included

Unlike Apache MyFaces, the classes for the JSF-Portlet bridge are not included in the JSF implementation, JBoss AS, or JBoss EAP. This library must be available in your application package. Navigate to the JSF-Portlet bridge webpage to download the JSF-Portlet bridge library.

#### 5.2.3.4. Building your JSF portlet

The `HelloWorldJSFSunRIPortlet.zip` file contains a pre-compiled `helloworldjsfsunriportlet.war` file; however, to manually build the `helloworldjsfsunriportlet.war` file:

1. Change into the `HelloWorldJSFSunRIPortlet/` directory, and remove the existing `helloworldjsfsunriportlet.war` file.

2. If required, edit the `HelloWorldJSFSunRIPortlet/src/main/org/jboss/portlet/hello/bean/User.java` file, and the application descriptors in the `HelloWorldJSFSunRIPortlet/src/resources/helloworldjsfsunriportlet-war/WEB-INF/` directory.

3. Change into `HelloWorldJSFSunRIPortlet/` directory, and run the ant deploy command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the `helloworldjsfsunriportlet.war` file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP pages. To expand the `helloworldjsfsunriportlet.war` file:

1. If you do not have the `HelloWorldJSFSunRIPortlet/helloworldjsfsunriportlet.war` file, change into the `HelloWorldJSFSunRIPortlet/` directory, and run the ant deploy command. This creates the `helloworldjsfsunriportlet.war` file.

2. To expand the WAR file, change into the `HelloWorldJSFSunRIPortlet/` directory, and run the ant explode command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

The expanded WAR file and the application descriptors are located in the `HelloWorldJSFSunRIPortlet/output/lib/exploded/helloworldjsfsunriportlet.war/WEB-INF/` directory.

#### 5.2.3.5. Deploying your JSF portlet

If you did not expand the `helloworldjsfsunriportlet.war` file, copy the `HelloWorldJSFSunRIPortlet/helloworldjsfsunriportlet.war` file into the correct JBoss AS or JBoss EAP `deploy/` directory. If you expanded the `helloworldjsfsunriportlet.war` file, copy the `HelloWorldJSFSunRIPortlet/output/lib/exploded/helloworldjsfsunriportlet.war/` directory into the correct JBoss AS or JBoss EAP `deploy/` directory. For example, if you are using `default` JBoss AS profile, copy the WAR file or the expanded directory into the `$JBOSS_HOME/server/default/deploy/` directory.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet:

    INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjsfsunriportlet,
    warUrl=.../tmp/deploy/tmp9138helloworldjsfsunriportlet-exp.war/

To see the HelloWorldJSFSunRIPortlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldJSFSunRIPortlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the `$JBOSS_HOME/server/`configuration`/deploy/helloworldjsfsunriportlet.war/WEB-INF/web.xml` file. This only works if you copied the `HelloWorldJSFSunRIPortlet/output/lib/exploded/helloworldjsfsunriportlet.war/` directory into the JBoss AS or JBoss EAP `deploy/` directory. On Linux, run the touch $JBOSS_HOME/server/`configuration`/deploy/helloworldjsfsunriportlet.war/WEB-INF/web.xml command to re-deploy the HelloWorldJSFSunRIPortlet.

Re-deploying the HelloWorldJSFSunRIPortlet produces output to the JBoss AS or JBoss EAP console, similar to the following:

    INFO  [TomcatDeployer] undeploy, ctxPath=/helloworldjsfsunriportlet,
    warUrl=.../deploy/helloworldjsfsunriportlet.war/
    INFO  [TomcatDeployer] deploy, ctxPath=/helloworldjsfsunriportlet,
    warUrl=.../deploy/helloworldjsfsunriportlet.war/

### 5.2.4. An example Apache MyFaces JSF portlet

#### 5.2.4.1. Introduction

This section describes how to deploy a JSF portlet in JBoss Portal, using the Apache MyFaces JSF implementation in JBoss AS and JBoss EAP. Before proceeding, download the HelloWorldJSFMyFaces42Portlet from JBoss PortletSwap.

Apache MyFaces can be used globally for the entire server, replacing the Sun JSF RI libraries, but the HelloWorldJSFMyFaces42Portlet uses its own libraries, but does not affect the application server.

#### 5.2.4.2. Package Structure

JBoss Portal requires certain descriptors to be included in a portlet WAR file. Some of these descriptors are defined by the JSR-168 Portlet Specification, and others are specific to JBoss Portal. Like a typical JSF application, the HelloWorldJSFMyFaces42Portlet package contains a `faces-config.xml` file that defines managed-beans, converters, validators, navigation rules, and so on. The following is an example of the directory structure of the HelloWorldJSFMyFaces42Portlet portlet:

To create the `WEB-INF/` and `META-INF/` directories, extract the `helloworldjsfmyfacesportlet.war` file. The `WEB-INF/lib/` directory must contain the Apache MyFaces libraries, along with the dependent libraries.

#### 5.2.4.3. Application Descriptors

Only the `portlet.xml`, `faces-config.xml`, and `web.xml` descriptors are described here. For more information about application descriptors, refer to Section 5.2.1.4, “Application Descriptors” and Section 6.2, “Portlet Descriptors”.

The following is an example of the `HelloWorldJSFMyFaces42Portlet/WEB-INF/portlet.xml` file. This file must adhere to its definition in the JSR-168 Portlet Specification. You may define more than one portlet application in this file:

    <?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>

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

  This specifies that the `org.apache.myfaces.portlet.MyFacesGenericPortlet` handles all requests and responses from the users. Therefore, there is no need to develop a specific portlet class, as Apache MyFaces provides a generic implementation which bridges the JSF and portlet worlds.

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

  You must initialize the portlet with a default page to render, similar to a welcome page.

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

  The `<supports>` element allows you to declare all of the markup types that a portlet supports in the `render` method. This is accomplished via the `<mime-type>` element, which is required for every portlet. The declared MIME types must match the capability of the portlet. As well, it allows you to pair which modes and window states are supported for each markup type. All portlets must support the `view` portlet mode, so this does not have to be declared. Use the `<mime-type>` element to define which markup type your portlet supports, which in this example, is `text/html`. This section tells the portal that it only outputs text and HTML, and that it only supports the `view` mode.

### Adding Functionality to an Apache MyFaces JSF portlet

To add functionality to an Apache MyFaces JSF portlet, sub-class it and create your own class.

The following is an example `HelloWorldJSFMyFaces42Portlet/WEB-INF/faces-config.xml` file:

    <?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>

Without the `faces-config.xml` file, the application would work the same outside of the portlet as it would inside a portlet container. In this example, a basic user bean, `<managed-bean-name>user</managed-bean-name>`, and a navigation rule are defined, which handle the submission of the original form in the `HelloWorldJSFMyFaces42Portlet/WEB-INF/jsp/index.jsp` file.

The following is an example of the `<context-parm>` element from the `HelloWorldJSFMyFaces42Portlet/WEB-INF/web.xml` file:

    <context-param>
       <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
       <param-value>true</param-value>
    </context-param>

These extra parameters let the application server know that the portlet embeds its own libraries. This avoids collision with the Sun JSF RI libraries bundled with JBoss AS and JBoss EAP. For more information, refer to the JBossFaces page on the JBoss Wiki.

#### 5.2.4.4. Building your Apache MyFaces JSF portlet

The `HelloWorldJSFMyFaces42Portlet.zip` file contains a pre-compiled `helloworldjsfmyfacesportlet.war` file; however, to manually build the `helloworldjsfmyfacesportlet.war` file:

1. Change into the `HelloWorldJSFMyFaces42Portlet/` directory, and remove the existing `helloworldjsfmyfacesportlet.war` file.

2. If required, edit the `HelloWorldJSFMyFaces42Portlet/src/main/org/jboss/portlet/hello/bean/User.java` file, and the application descriptors in the `HelloWorldJSFMyFaces42Portlet/src/resources/helloworldjsfmyfacesportlet-war/WEB-INF/` directory.

3. Change into `HelloWorldJSFMyFaces42Portlet/` directory, and run the ant deploy command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

Expanding the `helloworldjsfmyfacesportlet.war` file allows you to deploy the portlet as an expanded directory, which makes development easier. As well, it gives you access to the application descriptors, resource files, JSF, and JSP pages. To expand the `helloworldjsfmyfacesportlet.war` file:

1. If you do not have the `HelloWorldJSFMyFaces42Portlet/helloworldjsfmyfacesportlet.war` file, change into the `HelloWorldJSFMyFaces42Portlet/` directory, and run the ant deploy command. This creates the `helloworldjsfmyfacesportlet.war` file.

2. To expand the WAR file, change into the `HelloWorldJSFMyFaces42Portlet/` directory, and run the ant explode command. On Linux, the output will be similar to the following:

Note: the directory names will be different for your system.

The expanded WAR file and the application descriptors are located in the `HelloWorldJSFMyFaces42Portlet/output/lib/exploded/helloworldjsfmyfacesportlet.war/WEB-INF/` directory.

#### 5.2.4.5. Deploying your Apache MyFaces JSF portlet

If you did not expand the `helloworldjsfmyfacesportlet.war` file, copy the `HelloWorldJSFMyFaces42Portlet/helloworldjsfmyfacesportlet.war` file into the correct JBoss AS or JBoss EAP `deploy/` directory. If you expanded the `helloworldjsfmyfacesportlet.war` file, copy the `HelloWorldJSFMyFaces42Portlet/output/lib/exploded/helloworldjsfmyfacesportlet.war/` directory into the correct JBoss AS or JBoss EAP `deploy/` directory. For example, if you are using the `default` JBoss AS profile, copy the WAR file or the expanded directory into the `$JBOSS_HOME/server/default/deploy/` directory.

Performing this step on a running instance of JBoss AS or JBoss EAP, and JBoss Portal, triggers a hot-deploy of the portlet.

To see the HelloWorldJSFMyFaces42Portlet, navigate to http://localhost:8080/portal/, or, if the default JBoss Portal page is already open, refresh the page. The HelloWorldJSFMyFaces42Portlet is added to the bottom of the default JBoss Portal page:

To re-deploy the portlet, for example, if you have made changes to any of the application descriptors, touch the `$JBOSS_HOME/server/`configuration`/deploy/helloworldjsfmyfacesportlet.war/WEB-INF/web.xml` file. This only works if you copied the `HelloWorldJSFMyFaces42Portlet/output/lib/exploded/helloworldjsfmyfacesportlet.war/` directory into the JBoss AS or JBoss EAP `deploy/` directory. On Linux, run the following command to re-deploy the HelloWorldJSFMyFaces42Portlet:

    touch $JBOSS_HOME/server/configuration/deploy/helloworldjsfmyfacesportlet.war/WEB-INF/web.xml

Prev | Up | Next
Chapter 4. Upgrading JBoss Portal 2.4 to 2.6 | Home | Chapter 6. XML Descriptors