By Andrew Wills
October 12, 2007

Recently I was asked by University of Colorado System to develop a portlet-based user interface for their User Impersonation capabilities. These tools allow special users -- developers and help desk staff -- to assume the identity of another user within the portal. Developers use Impersonation to test what they're working on; help desk personnel use it to provide better support for callers with issues... to see what they see.

Under the hood, Impersonation uses a table in the portal database. This table maps real identities to identities that will be assumed: if there's a row with your username in the 'real identity' column and the 'assumed identity' column is not null, then you will take on the person attributes (and consequently the layout, group affiliations, and permissions) of that user.

Before I get carried away: this portlet is actually the subject of the next article I hope to write. University of Colorado has generously agreed to make it available to the community as open source. I hope to release this article (Part One), the next article (Part Two), and the portlet itself before the JA-SIG Winter 2007 Unconference. Sounds like 'famous last words' material to me.

But this all begs the question: if the Impersonation Portlet is the subject of the next article, what is this article about?

Real Portlets, Real Easy

When I wrote the Impersonation Portlet, perhaps the first notion that came to me was, "This looks like a great opportunity to leverage the work I've been doing with Cernunnos." Colleagues at Unicon who know me well probably think I'd react that way to any assignment; perhaps they're right. But in this case I was sure I had a good match. I knew the things the portlet had to do -- read from and write to the database, log whenever someone assumes another identity, dispatch rendering to a JSP, etc. -- were available as Cernunnos tasks already.

I wrote a simple portlet class (240 lines) to streamline and generalize the practice of invoking Cernunnos scripts within portlets. Here's how it works:

  • CernunnosPortlet will satisfy each action cycle or rendering cycle by running a script located within the webapp
  • Actions are located in /WEB-INF/actions/ by default (but you can change it)
  • You choose which script will be invoked in the action cycle by passing a special parameter: action is the default (but you can change it) Remember: you must use an Action URL to trigger an action cycle!
  • Views are located in /WEB-INF/views/ by default (but you can change it)
  • You choose which script will be invoked in the rendering cycle by passing a different parameter: view is the default (but you can change it)
  • View choices are sticky; once you choose a view, the user will remain on that view until moved
  • You can display a JSP page using the <request-dispatcher> Task, or render by XSL using the <xslt> Task
  • In a single request, you may specify action and/or view in any combination: both, neither, just action, or just view
  • Every script will have a reference to the PortletRequest and PortletResponse objects
  • You may provide references to other objects (such as a DataSource) using Spring Dependency Injection

And there you have it: that's the 10,000' view, but there's really not much more to tell. I hoped simply to bridge the gap between two technologies -- Java Portlets and Cernunnos -- and get out of the way! The result is an approach that is thin, lightweight, and open.

Take It for a Test Drive

I believe this approach makes Java Portlets easier, and I've put together a short exercise to illustrate what I mean. Follow these steps to create your first Cernunnos-based portlet:

  1. Install Cernunnos on your workstation
  2. Create a new, empty directory called 'PortalTools' and navigate into it on the command prompt
  3. Enter the following commands:

Congratulations! You have just authored and built a JSR-168 portlet application named 'PortalTools' that contains a 'WelcomeMessage' portlet. If you deploy it in uPortal, publish the 'WelcomeMessage' portlet, and add it to your layout, you should see something like this:

If you're keeping score, I figure this article has come half way to living up to its title: Real Portlets, Real Easy. This example is easy enough -- but honestly, it's not much use. In Part Two we'll take a close look at the Impersonation Portlet I prepared for University of Colorado. This portlet does real work: database interaction, multiple screens, role-based security, etc. I'm going to wait for the next article to tackle something of this scale.

Nevertheless there are some simple things we can do to the WelcomeMessage Portlet to make it more interesting. For example, we can enhance the WelcomeMessage Portlet to support the following additional requirements:

  • The portlet shall welcome the user by his or her full name; and
  • The portlet shall display todays date in a user-friendly format

To include the user's name, we will need to access that information from the portal. According to the Java Portlet Specification, portlet applications must declare the user attributes they expect in their portlet.xml file.

Still within the 'PortalTools' directory, issue the following command:

At this point your portlet.xml file -- located within the 'PortalTools' project at web/WEB-INF/portlet.xml -- should look like this:

<portlet-app ... > 
  <portlet> 
    <portlet-name>WelcomeMessage</portlet-name>  
    <portlet-class>org.danann.cernunnos.runtime.web.CernunnosPortlet</portlet-class>  
    <supports> 
      <mime-type>text/html</mime-type>  
      <portlet-mode>view</portlet-mode> 
    </supports>  
    <portlet-info> 
      <title>WelcomeMessage</title> 
    </portlet-info> 
  </portlet>  
  <user-attribute> 
    <name>displayName</name> 
  </user-attribute>
</portlet-app>

You may freely make additional modifications to this file. For example, you can change the portlet title, provide additional metadata, use the add-portlet.crn script to create another portlet, or user the add-user-attribute.crn script to request more user attributes from the portal. You can make these changes in any combination, in any order.

Getting back to our task: we've told the portal we need the user's name, but we still need to access that information and display it on the screen. We also need to add the current date.

Edit the web/WEB-INF/views/WelcomeMessage/index.crn file as follows:

<with-attribute key="displayName" value="${jexl(
    WebAttributes.REQUEST.getAttribute('${const(javax.portlet.PortletRequest.USER_INFO)}').get('displayName')
  )}">
    <with-attribute key="displayDate" value="${newInstance(java.util.Date)}">
        <request-dispatcher resource="/WEB-INF/jsp/WelcomeMessage/index.jsp"/>
    </with-attribute>
</with-attribute>

Next edit the web/WEB-INF/jsp/WelcomeMessage/index.jsp file:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet"%>

<portlet:defineObjects/>

<p><strong>Welcome <c:out value="${displayName}"/><strong></p>

<p><strong>Today is  <fmt:formatDate value="${displayDate}" dateStyle="LONG"/><strong></p>

That's it! Re-build and re-deploy your portlet application. The welcome message should now look like this:

I hope this example is helpful. Sometimes I like to discuss ideas about software in abstract terms a little more than I should, and illustrate those ideas with concrete examples a little less than I should. If you're interested, I've written elsewhere about the aims and philosophy of Cernunnos.

As already indicated, the next article will be about the Impersonation Portlet developed for University of Colorado. This portlet features two views (including two JSP files), four actions, and plenty of database interaction.

Your Author:

drew's picture

Andrew Wills