uPortal logo

Writing a channel for uPortal 2.0.1

Owen Gunden

University of Virginia

(updated 8-06-02)


Index

Overview

About this document

This document pertains to the uPortal, an open, sharable internet portal under development by institutions of higher-education.

The purpose of this document is to describe the steps required to write a custom uPortal channel. It details each of the main steps, simultaneously building a simple example channel. When referring to the example channel, the background is this color.

I wrote it all by hand, using vim.

Help is always appreciated! If you find something wrong with this document, or would like to add something here or there, or anything of the sort, send me an email. Feel free to edit the html source and send me a modification, if you like. Just please make sure that it's still valid xhtml.

Types of Channels

uPortal 2.0.1 supports six types of channels. These are:

Channel Type Description What you must provide
Image This is a simple channel type that is used to display an image with optional caption and subcaption. The image may be a hyperlink to another page. Image url, hyperlink, optional caption and subcaption
Inline Frame This type of channel is used to render an entire HTML page within a frame. It doesn't work with Internet Explorer versions less than 5 or Netscape versions less than 6, and it doesn't work very well with Netscape 6. url of the html page
RSS (Rich Site Summary) This is the most common type of channel. All of the content is defined in an XML document, which must adhere to the RSS specification. url of the rss file
Simple XML Transformation The channel's content is defined by an XML document, and the styling must be done with one or more XSL documents (written in XSLT). url of the XML file and the XSL file
Web Proxy This is one way to incorporate an already-written web application. If you are creating a new channel (that you need to be dynamic), however, it is recommended that you write a custom channel. There is more information about using the web proxy channel type here. url of the web application
Custom This type of channel is used to publish channels that need to incorporate dynamic content. It is the most general and powerful type of channel. All of the other types of channels are subtypes of custom channels. Java class, XSL stylesheet(s)

Much uPortal content can (and should!) be developed using one of the first five types of channels. On the other hand, certain types of content, particularly dynamic content, requires more power than these methods have to offer. For this type of power, a custom channel is in order.

This document discusses the steps required to create a custom channel using the Java IChannel interface.

What you need to know

What you might want to know

The steps

Here are the steps you need to follow when writing your channel for uPortal 2.0.1.

  1. Prepare to create your channel by deciding what your channel needs to do, and what you will call it.
  2. Write the Java code to respond to user input and produce the content (in XML form) for your channel.
  3. Write a stylesheet list (SSL) which describes each of the stylesheets your channel uses.
  4. Write the stylesheet(s) that will transform your XML into xhtml, which is sent to the user's browser.
  5. Publish the channel via the channel publishing mechanism that is built into uPortal 2.0.1.

Getting started

Decide what your channel will do

First thing to do is decide exactly what your channel will do. Since you have decided your channel should be a custom Java channel, your channel probably has dynamic content (meaning it changes based on user input).

Try to envision just the content (not the presentation) of the output of your channel expressed as an XML string. If you think there might be other situations where people would need to express similar content, you might try looking for a DTD or schema that suits your needs (one good place to look is xml.org's XML registry). Using a more general DTD or schema can be useful as your channel will be producing XML that you might be able to use outside of the uPortal as well as inside.

Our example channel will take in a name, and then display "Hello" to that name. The content of the output of the channel is merely a name, so the XML will look something like:
 <name>Owen</name> 
Where "Owen" is the name we're trying to pass to the stylesheet.

The channel will also have an "About this channel" page, which simply displays some text describing the channel. In this case, the content is that text that we need to display:
 <about>A bunch of text describing the channel</about> 
     

Naming and placing your files

Your Java source should be in a file with the same name as your channel, except that it has a 'C' prepended to it. It goes in:

<uportal-home>/source/<package>/ 

Note that with the quick-start distribution, <uportal-home> refers to the uPortal_2-0-1-quick-start/uPortal_rel-2-0-1 directory, and with the uPortal-only distribution it refers to the uPortal_rel-2-0-1 directory.

Your stylesheet list is usually named the same as your Java source, except instead of having a .java extension it has a .ssl extension. It goes in:

<uportal-home>/webpages/stylesheets/<package>/ 

The stylesheets are .xsl files, and can be named whatever you choose. They go in the same directory as the stylesheet list file.

The example channel is called HelloWorld, so its Java source goes in CHelloWorld.java. Since the package on the channel is:
edu.virginia.uportal.channels.helloworld
The file locations for all the files that are used are as follows:
<uportal-home>/source/edu/virginia/uportal/channels/helloworld/CHelloWorld.java
<uportal-home>/webpages/stylesheets/edu/virginia/uportal/channels/helloworld/CHelloWorld.ssl
<uportal-home>/webpages/stylesheets/edu/virginia/uportal/channels/helloworld/normal_explorer.xsl
<uportal-home>/webpages/stylesheets/edu/virginia/uportal/channels/helloworld/normal_netscape.xsl
<uportal-home>/webpages/stylesheets/edu/virginia/uportal/channels/helloworld/about.xsl

Writing the Java class

Import statements

There are some classes that are used by every channel for the uPortal. You'll need import statements for at least these classes.

// A channel needs these eight classes no matter what:
import org.jasig.portal.IChannel;
import org.jasig.portal.ChannelStaticData;
import org.jasig.portal.ChannelRuntimeData;
import org.jasig.portal.ChannelRuntimeProperties;
import org.jasig.portal.PortalEvent;
import org.jasig.portal.PortalException;
import org.jasig.portal.utils.XSLT;
import org.xml.sax.ContentHandler;

// This is only useful if you will be using the LogService (which you should!!):
import org.jasig.portal.services.LogService;

The class declaration

Your class must implement the IChannel interface, so this must be in the class declaration.

public class CHelloWorld implements IChannel 

Necessary fields

At the very least, you'll need to keep track of the static data and the runtime data that the portal sends you.

private ChannelStaticData staticData;
private ChannelRuntimeData runtimeData;

Often your channel consists of a few different "views" or "pages." One good way to deal with this is to enumerate the different pages and have some state for remember the current page.

private static final int NORMAL_MODE =    42; // two of my
private static final int ABOUT_MODE  = 31337; // favorite numbers
private int mode; // whether we're in NORMAL_MODE or ABOUT_MODE

You'll also need fields to keep track of any other state that you need for your channel.

private String name; // the name to say hello to
private String name_prev; // the name that was previously submitted, to go
                          // in the text box by default.

The constructor

You can do any initialization you need in the constructor. It will get called once as the uPortal is setting up your channel.

  /**
   *  Construct0r.
   */
  public CHelloWorld() {
    this.name = "World"; // default to "Hello World!"
    this.name_prev = ""; // start with the text box empty
    this.mode = NORMAL_MODE; // start in normal mode
  }

IChannel interface methods

The IChannel interface requires that you implement five methods. These are described below.

Writing the stylesheet list

The stylesheet list is just that: a list of stylesheets. You name a bunch of stylesheets and then describe the cases in which they should be used. The attributes of stylesheets which differentiate them from one another are the stylesheet title and the stylesheet media. The title is arbitrary, the media refers to the user's browser type.

The stylesheet list is an XML document containing a processing instruction (the thing inside the <? ?> tags) for each stylesheet. Since it is an XML document, you must have beginning and ending document tags, even though they mean nothing in this context.

<?xml version="1.0"?>
<!-- CHelloWorld.ssl, part of the HelloWorld example channel -->

<?xml-stylesheet
    href="normal_netscape.xsl"
    title="normal"
    type="text/xsl"
    media="netscape"?>

<?xml-stylesheet
    href="normal_explorer.xsl"
    title="normal"
    type="text/xsl"
    media="explorer"?>

<?xml-stylesheet
    href="about.xsl"
    title="about"
    type="text/xsl"
    default="true"?>

<document>
</document>

Writing the stylesheet(s)

Your stylesheets are written in XSLT, which is a language for transforming XML documents.

See the section What you need to know for information on where to learn more about XML/XSLT.

about.xsl
<?xml version="1.0" encoding="utf-8"?>
<!-- about.xsl, part of the HelloWorld example channel -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html" indent="no" />
  <xsl:param name="baseActionURL">baseActionURL_false</xsl:param>
  <xsl:param name="name_prev">world</xsl:param>

  <xsl:template match="/">
    <a name="helloworld" />
    <xsl:apply-templates />
    <p><a href="{$baseActionURL}?back=true">Back</a></p>
  </xsl:template>

  <xsl:template match="about">
    <p><xsl:value-of select="." /></p>
  </xsl:template>
</xsl:stylesheet>
normal_explorer.xsl
<?xml version="1.0" encoding="utf-8"?>
<!-- normal_explorer.xsl, part of the HelloWorld example channel -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html" indent="no" />
  <xsl:param name="baseActionURL">baseActionURL_false</xsl:param>
  <xsl:param name="name_prev">world</xsl:param>

  <xsl:template match="/">
    <p />
    <a name="helloworld" />
    <xsl:apply-templates />
    <form action="{$baseActionURL}#helloworld" method="post">
      Enter your name:
      <input type="text" name="name" size="15"
            class="uportal-input-text"
            value="{$name_prev}" />
      <input type="submit" name="submit" value="submit"
            class="uportal-button" />
      <input type="submit" name="clear" value="clear"
            class="uportal-button" />
    </form>
    <p>This is the <b>explorer</b> stylesheet.</p>
  </xsl:template>

  <xsl:template match="name">
    <p>Hello <xsl:value-of select="." />!</p>
  </xsl:template>
</xsl:stylesheet>
normal_netscape.xsl
<?xml version="1.0" encoding="utf-8"?>
<!-- normal_netscape.xsl, part of the HelloWorld example channel -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html" indent="no" />
  <xsl:param name="baseActionURL">baseActionURL_false</xsl:param>
  <xsl:param name="name_prev">world</xsl:param>

  <xsl:template match="/">
    <a name="helloworld" />

    <xsl:apply-templates />
    <form action="{$baseActionURL}#helloworld" method="post">
      Enter your name:
      <input type="text" name="name" size="15"
            class="uportal-input-text"
            value="{$name_prev}" />
      <input type="submit" name="submit" value="submit"
            class="uportal-button" />
      <input type="submit" name="clear" value="clear"
            class="uportal-button" />
    <p>This is the <b>netscape</b> stylesheet.</p>
    </form>
  </xsl:template>

  <xsl:template match="name">
    <p>Hello <xsl:value-of select="." />!</p>
  </xsl:template>
</xsl:stylesheet>

Publishing the channel

Before you can try out your new channel, you need to publish it to the uPortal. This means putting information about the channel into the uPortal database.

Fortunately, there is a mechanism built in to the uPortal to help you publish a channel. In order to use this mechanism, however, you need to be a privelaged uPortal user (to be precise, you need to belong to the "channel developers" group). If you aren't a privelaged user, get someone who is in the Portal Administrators group (or log in as such a user) and add your username using the groups manager. If this method doesn't work, or you don't know of any privelaged users, add an entry to the up_group_membership table in the database. The SQL to add this entry would look something like this:

INSERT INTO up_group_membership VALUES (14, 501, 'F')

where 14 is the id of the group you want to join (groups and their ids are listed in up_group) and 501 is your uPortal user id (users and their ids are listed in up_user).

Having logged in as someone with the proper permissions, you should see a link in the top-right corner of the page that reads "Channel Admin." Click it, and follow the instructions to publish your channel.

Here are the steps used to publish HelloWorld:
  1. Click "Channel Admin"
  2. Click "Publish A New Channel"
  3. Choose a Custom channel type.
  4. Fill out all the General Settings. Under Channel Class answer "edu.virginia.uportal.channels.helloworld.CHelloWorld"
  5. When asked to Add Parameters, simply click "Next >"
  6. Under Channel Controls, check the box next to Has About
  7. Add the channel to at least one category
  8. Add the channel to the "Everyone" group
  9. Review and click "Finish"
To test the hello world channel, go to "Customize", and add the channel to your layout.

Valid XHTML 1.0! Valid CSS!