Understanding Portals and Portlets: Part Two
A real-world implementation
Dec. 15, 2004 12:00 AM
Related Links: Understanding Portals and Portlets: Part One
In the November issue of JDJ (Vol. 9, issue 11) I explained the theory behind the JSR 168 (Portlet Specification) from an academic perspective. The specification provides the infrastructure, classes, interfaces, and JSP tags for building applications that can be pieced together from a handful of off-the-shelf or custom portlets. This time around, I provide you with a real-world implementation that utilizes the knowledge you picked up from Part 1 of this series.
Along the way, you'll learn how to properly install Pluto (the Portlet Reference Implementation you can use to test your portlets) and learn about some pretty cool tools as well.
A Quick Refresher
Last month, we learned that portlets are similar to servlets, except they aren't allowed to use several HTML control tags such as the <body> tag. This is because the portal page provides these controlling tags, whereas the portlets provide the tags necessary to complete their own work.
Portlets also share the application context with servlets and JSPs and can even include the output of another servlet or JSP as part of their content. To offer the user the ability to customize portlets, there are special Window States (such as normal, minimized, and maximized) and Portlet Modes (such as Edit, View, Help) that can be controlled by the end user. Furthermore, the portlet can use these states and modes to determine what content it needs to show the user at any given point. User's actions are received within a portlet in the form of both action and render methods. Action methods respond to the user's interaction with the portlet, and render methods are called to paint the output of the portlet.
Later in this article, we'll see how we can put all of these features and settings to use in our example portlet. However, before we can dive into the code, we need to ensure that our environment is ready to test a portal page and its contained portlets.
Given the fact that Pluto is very Mavenized these days, you'll need to download Maven (a tool that allows you to build and deploy your project based on a Project file). In addition, you'll need a servlet engine to run Pluto (since Pluto runs as a servlet). I suggest Tomcat (preferably version 5) as the servlet engine.
If you're developing on a Windows machine, the Tomcat setup is pretty easy. I downloaded Tomcat from the Apache Web site using http://jakarta.apache.org/tomcat/.
Make sure you extract the Tomcat binaries into its own directory and be sure you have the JAVA_HOME environment variable pointing to your Java installation directory path. Once Tomcat is installed, try your hand at Maven. Download and install Maven from the Apache Web site as well.
Define an environment variable named MAVEN_HOME and point it to the Maven root directory. You may also want to add Maven's bin directory to your path, so you can easily execute Maven from any command prompt window in any directory. If all goes well, you should be able to run Maven with the -v option to view its version information.
Finally, it's time to locate and download Pluto. At the time of this writing, the latest version of Pluto is 1.0.1, and is in a Subversion Source Code Management (SCM) system. If you visit http://cvs.apache.org/viewcvs.cgi/portals/pluto/trunk/?root=Apache-SVN, you'll find the trunk.
You can either use the Web interface to surf each package and download them directly (which is very cumbersome), or you can download and use Tortoise for Subversion, which adds context options to Windows Explorer in order to assist you in downloading content from various Subversion repositories across the Internet. The Tortoise installation and documentation is located at http://tortoisesvn.tigris.org.
Tortoise provided Windows Explorer with new context menu items as shown in Figure 1.
Next, you'll need to create a new directory and download Pluto. Right-click in the newly created directory while in Windows Explorer to bring up the context menu and select the option marked "Checkout...". You'll need to specify the complete path to the Subversion repository, which is mentioned on the Apache.org Web site as follows http://svn.apache.org/repos/asf/.
A Subversion repository is similar to CVS, but provides added features and is becoming extremely popular. Many sites are changing their repositories from CVS to Subversion (and the Apache group is no exception).
I simply added the remainder of the URL to locate the Pluto project as shown in Figure 2.
Once you download Pluto's source files you'll have a complete directory tree with the necessary files needed to build Pluto. You can always update Pluto with newer changes by opening the context menu offered by Tortoise. You'll notice that the menu will change to reflect new choices available now that you have downloaded Pluto.
To run Maven against the Pluto file, you'll need to perform the following tasks:
- Copy the build.properties.sample file to build.properties.
- Modify the build.properties and specify the location and version of Tomcat:
- Run the maven fullDeployment command.
The fullDeployment operand tells Maven to run this task within the project file. The task has been provided with everything needed to download any necessary or missing projects, compile Pluto, and deploy Pluto.
Now, you're ready to access Pluto for the first time (it comes with a test portal). First, you'll need to run Tomcat. Once Tomcat has finished loading, you can access the portal by surfing over to http://localhost:8080/pluto/portal. You should be presented with the page shown in Figure 3.
If you click on the Test portal, you'll be able to test out much of what a JSR 168 portlet has to offer. You'll see two instances of the same portlet host on a portal page with two columns (one for each portlet). The source code can be located at [pluto-installation-dir]/testsuite.
The ImageViewer Portlet
When I thought about writing the example for this article, I wanted to come up with an idea that was simple enough to understand, yet realistic enough to give you a starting point for building your own real-world portlets. (The source code for this article can be downloaded from www.sys-con.com/java/sourcec.cfm.) The result is a portlet that utilizes many JSR 168 features to provide an end user with a portlet that has two portlet modes: view and edit.
The view mode allows the end user to specify an image stored in a subdirectory named images on the server side (relative to the portlet's context root), and displays the image within the portlet on the way back to the browser. After entering a name and clicking the "Show Image" button, the user is presented with the result as illustrated in Figure 4.
You'll notice that there is some text in the portlet that specifies, "color = white". White is the default color chosen for the portlet's background. However, this can be changed by entering the Edit mode of the portlet, which is achieved by clicking on the "edit" link on the portlet's title bar. When you do so, you're presented with the output shown in Figure 5.
If you change the selection to "Blue" and press the "Change Color" button, then go back to View mode and select an image, you'll notice that the background now reflects the new background color.
The ImageViewer Source Code Explained
Now that you've seen the ImageViewer portlet from the end-user's perspective, let's take an in-depth look at the source code.
The first thing I did was to set up my directory structure, which resembles the image shown in Figure 6.
I knew that I would be building the files listed in Table 1.
The Portlet.XML Deployment Descriptor File
Let's look at the portlet.xml file, which contains the various descriptors used to deploy the portlet properly (see Listing 1).
The first part of the file includes the standard customary XML tag used to identify the file and the schema used to validate the file's content. Next, we see the root portlet tag. Within this tag are several other tags including description, portlet-name, display-name, portlet-class, init-param (of which there are three), supports (for mime types), locale, and portlet-info. The most important of these tags are the portlet-name and the portlet-class tags.
The portlet-name provides a name that can be used internally or programmatically to reference the portlet, while the portlet class provides the classpath used by the portlet container to load the appropriate class and create instances from it.
The description tag can be used by development tools to provide a description of what the portlet does, whereas the display name can be used to provide the developer with a unique name that (hopefully) differs from other portlets in the portlet catalog. As portals become more popular, you'll start to see drag-and-drop support within the various development environments, allowing developers to drag portlets onto a portal page and drop them into the page. The display name will become very important, showing the developer which space is occupied by which portlet.
I included three different init-param values that provide the portlet with the names of the JSPs used for its View and Edit modes and the default background color of white.
The supports tag provides the mime-type tag, which tells the portlet container that the portlet will provide HTML for the various views and that two different modes are supported: View and Edit. The supported locale tag specifies that our chosen language is English.
Finally, the deployment descriptors provide the title tag, used by default for providing a title for the portlet in the portal page; the short title, which can be used to provide a shorter version of the title (for use in WAPs or other devices that have a smaller screen display area); and keywords, which are used to search for portlets within development tools. The search can, for example, narrow down the catalog of portlets to a few portlets that support stock screening or image manipulation, or whatever other functionality you're interesting in providing your end users with from your portal pages.
The ImageViewerPortlet Java Source File
The source code for the ImageViewerPortlet.java file starts off by defining the package name and importing the necessary packages and/or classes. Next, it names the class and provides the methods. There are no data members in this class (see Listing 2).
The first method we'll look at is init(). This method doesn't have much to do in this case, but I wanted to assure you that it is in fact called. Therefore, I simply added an output message to the console.
Now it's time to meet the processAction() method. Based on the retrieved portlet mode, the portlet determines whether it's in View mode or Edit mode. If it is in View mode, this method simply has to copy the present parameters (passed from the user's browser, which includes the image name the user wishes to see) into the response's render parameters so they can be picked up by the doView() method. If the portlet is in Edit mode, it retrieves the current background color from the request (this is always passed in the JSP as you'll soon see), and places it in the PortletSession (where it can be picked up by the JSP page). I could have used portlet preferences for the background color (along with a validator class), but I chose to keep the example simple.
Next, we come to the doView() method. This method retrieves the PortletSession object, which can be used to then retrieve the bgColor. This is just one of many ways to pass data around. I simply wanted to use as many techniques as possible without overwhelming you.
If the background color has not been set into the session, it's set at this point by retrieving the default color from the portlet's configuration object using the getInitParameter() method.
Next, I set the mime type for the view mode and dispatch to the JSP page (including its output in the final HTML sent to the browser).
Finally, the doEdit() method appears in the listing. This one is pretty simple and resembles the bottom half of the doView() method. The only difference is that it dispatches to the Edit JSP instead of the View JSP.
The View JSP
The view.jsp file provides the source code in Listing 3. The top portion of this file includes the portlet tag library. One of the most important steps you must take (before you can use any of the portlet internal objects) is to call portlet:defineObjects tag, which is provided by the tag library. Next, it creates a few variables to hold the action URL, the image filename the user specified, and the background color (retrieved from the session object).
After creating the variables, the HTML provides a string containing the current color, a form to include the controls used by the user to interact with the portlet, and the submit button.
If a filename is provided, the name is used with some special methods to conjure up a complete path to the actual image file. You must use the renderRequest.getContextPath() method to create a legitimate path. Don't assume that you could simply use the relative path and it will work.
Finally, the newly created path is used in the image tag to display the image within the portlet.
The Edit JSP
The code for the Edit JSP isn't much different from that of the View JSP. It only differs in its content, which should be very self-evident (if you know HTML at least at a basic level). See Listing 4 to view the source code for the edit.jsp file.
Deploying to Pluto
To build the source code, I created an Ant file. Once you have compiled the code, you can deploy it to the Pluto portal using the following commands:
maven deploy -Ddeploy=/ImageViewer/target/ImageViewer.war
There are still a few more steps you have to follow in order to view the portlet within Pluto. You need to modify the Portlet Entity Registry and the Page Registry files. These can be located at:
The portlet entity registry file requires that you specify an application and a portlet ID for your new portlet. The application ID must be unique. The portlet entity registry file also needs to know the name of the portlet so that it can go out and find it in the webapps path. Furthermore, this information is used to map the portlet name to the appropriate classpath for loading the class. The following are my additions to the portlet entity registry file:
The page registry provides Pluto with the layout information for your portlet. The names used in the fragments must be unique as in my example:
<fragment name="ImageViewerPortlet" type="page">
<fragment name="row3" type="row">
<fragment name="col3" type="column">
<fragment name="p4" type="portlet">
<property name="portlet" value="6.1"/>
In the above example, I simply told Pluto that I will need one row by one column. Within that row/column, I want it to display the portlet identified by "6.1". The number "6" is the application ID and "1" is the portlet ID.
After you edit and save the two XML files, restart Tomcat and you should now see the Portal page link named "Image Viewer".
Although I've tried to provide you with as much information and features as I could, the only true way to learn how to build the JSR 168 portlets is to jump right in and do it. You should be able to use this code as the foundation for other portlets. Remember, if you do decide to start creating portlets, try to make them self-contained units of work. That way, they can be shared across projects, teams, and possibly even companies.
JM commented on 10 Jan 2005
I understant that must to make a WAR and later put this file into portlet web-apps (tomcat) but... can you told us how must to be tha ant file ?
or if we can compile the portlet using another way.
John Windberg commented on 30 Dec 2004
Am I missing something?
I needed not install maven to get pluto running initially, it was all bundled up. However, there is this step in the article, "To build the source code, I created an Ant file. Once you have compiled the code, you can deploy it to the Pluto portal using the following commands:"
Ummmm. What Ant file? What maven deploy? What are you talking about? Where do these files go?
I've got pluto running, the pluto tests look ok, I have your source code all typed in, where do I put them?
Matt commented on 28 Dec 2004
Your "Listing 1: portlet.xml file" source code example is missing the opening "portlet-app" tag:
Mike Glascock commented on 23 Dec 2004
The link to Part One is incorrect. It returns Part 2 again.
Ann Klein commented on 20 Dec 2004
Maven? Pluto? Tortoise? I am sure the are wonderful but what are they (animal, vegatable, Servlets, IDEs)? Are there other pieces of software in the same class? Maybe I am already using one or my company has standardized on an alternative.
Bill Watson commented on 17 Dec 2004
This seems to be coming up more and more frequently - ColdFusion developers being asked to defend ColdFusion against a planned move to Java and J2EE. And so, in case you end up in this situation, this is what you need to know.
For starters, any suggestion of "we need to stop using ColdFusion because we are going to use Java" demonstrates a complete lack of understanding of what exactly ColdFusion is. So, let's start with a brief explanation of the ColdFusion-Java relationship.
Applications written in ColdFusion (as of ColdFusion MX) are pure Java. Or, expressed slightly differently, ColdFusion runs on a J2EE server (either embedded, or one of your choosing) running a Sun-verified Java application (the ColdFusion engine), executing Java bytecode (compiled from your CFML source code). In other words, CFML (the code you write) is a developer-time consideration, not a run-time consideration. There is no CFML at runtime; at runtime you are executing pure Java, no more or less so than had you written the application in straight Java. Your ColdFusion application is a Java application; if you deploy a ColdFusion application what you have deployed is Java. It's as simple as that.
This means that the assertion that ColdFusion and Java are somehow mutually exclusive is just flat out incorrect. But what about the CFML code you write? Isn't that ColdFusion specific and not pure Java? And isn't that an issue? I don't think so. There is an entire industry of Java add-ons out there - tools, tags, language extensions, and more - and Java shops use these (as they should; after all, why reinvent the wheel?). If your Java code leverages third-party add-ons for reporting, or back-end integration, or charting, or ... does that make your code any less Java? Nope, not at all.
Experienced developers know that starting from step one is expensive and seldom makes sense, regardless of the language and platform. Experienced developers have toolboxes at their disposal, stuff they can leverage and reuse to be as productive as possible. Experienced developers write modular applications, separating logic and processing and presentation into tiers, allowing these to evolve independently of each other, even allowing them to be inserted or removed independently.
For Java developers, one of these tools should be ColdFusion. After all, why write dozens of lines of Java code to connect to a database when a single tag can accomplish the exact same thing (likely using the same code internally)? And why write lots of code to send an SMTP message using JavaMail APIs when a single tag can do it for you (again, using those same APIs)? You can think of ColdFusion as a bunch of prewritten Java code, stuff you can use so as to hit the ground running. And that makes your app no less Java than if you had done all the work manually.
However, some may counter that CFML is proprietary, and that the fact that you need to pay for an engine to execute your code somehow makes it non-Java. I have actually heard this from customers. So is this a valid issue? Again, I don't think so. For starters, paid does not equal proprietary. After all, these same customers do not balk at spending big bucks on their J2EE servers (and management tools and professional services and more). Furthermore, there are indeed third-party CFML engines out there. I am not going to comment on how good they are and how viable an alternative they are - that's irrelevant. What is relevant is that they exist, and that means that CFML is not a single-vendor or proprietary.
Great, so ColdFusion simplifies Java development, and ColdFusion applications are no less Java than applications written in low-level Java directly. But simplicity and abstractions require sacrificing power, right? Wrong! ColdFusion applications can (and should) leverage Java; Java APIs, Java classes, JavaBeans, JSP tags, you name it, ColdFusion can leverage it because ColdFusion itself is Java. It's that simple.
So, ColdFusion or Java? The answer should be yes, ColdFusion is Java, and Java development can benefit from ColdFusion. This is not an either/or proposition, it's a "you can have it all so why the heck would you want to do it any other way?" proposition.
Microsoft ASP has been an important player in Web application scripting since, well, since a year or so after the introduction of ColdFusion. From an application development process viewpoint, ColdFusion and ASP are not that different. Both are script based, both are very page centric, both embed server-side processing and client-side presentation code in source files, and both are implemented as HTTP server add-ons (ASP via ISAPI, ColdFusion via ISAPI and more). ASP and ColdFusion can coexist, and indeed, as most ColdFusion deployments are on Windows, the likelihood of ASP and ColdFusion coexisting (even if ASP is not used) is very high.
The ASP versus ColdFusion discussion used to come up regularly. But not anymore. Now that Microsoft has essentially abandoned any future development on classic ASP, replacing it with ASP.NET, few organizations are embarking on brand new ASP deployments. But having said that, if you do need to defend ColdFusion against ASP, here's what you need to know.
For starters, ASP capabilities are a subset of those of ColdFusion. Or put differently, ColdFusion can do anything that ASP can do, and a whole lot more too. The reverse is not true. Sure, ASP can be extended (using COM objects) to do just about anything that ColdFusion can do, but that's just it, you need to extend ASP - it's your responsibility to do so. Simple things that ColdFusion developers take for granted, like being able to generate an e-mail message, or process an uploaded file, or generate a business chart, none of those are native ASP functionality.
And this is not mere boasting, this is important, because it's the way to head off the "but ASP is free" argument. Sure, ASP is free for starters, but buy all the add-on bits you need to make it functionally equivalent to ColdFusion (even ColdFusion Standard, and even ColdFusion 3 or 4!) and you'll end up paying far more than ColdFusion costs. Sure, ASP is cheaper initially, but you get what you pay for. Or rather, you don't get what you don't pay for. And when you do pay for it, you'll end up paying a whole lot more.
And that's just looking at initial costs. ASP development is also far more time consuming than ColdFusion development. Even if you're comfortable in the languages used, you'll still have to write lots more code to get the job done. Even the execution of simple SQL statements is far more complex in ASP - one tag versus lots of lines of ugly code. More code = longer development time = costs more. Plus, more code = more complex ongoing maintenance = costs even more.
At the risk of sounding like an MBA, when you look at the total cost of ownership, ASP is not the cheaper option at all. Oh, and on top of all that, ASP is proprietary, a single vendor solution, and you're married to Windows boxes (no Linux, no Unix, no portability).
Maybe this is why, as already stated, most ColdFusion servers run on Windows, Windows boxes that likely already have ASP installed. Why? Because hundreds of thousands of developers have figured out that free can be far too expensive.
Comparing ASP.NET to ColdFusion is difficult. Actually, it's not just difficult, it's simply incorrect, and not an apples-to-apples comparison. In order to defend ColdFusion against a "we are moving to ASP.NET" claim, you (and whoever is involved in the decision making) need to take a big step back. Why? Simple, because ASP.NET is part of Microsoft's .NET solution, and ASP.NET apps take advantage of the .NET Framework and infrastructure, just like ColdFusion apps take advantage of J2EE. In other words, deciding between ColdFusion and ASP.NET (and indeed, defending ColdFusion against ASP.NET) first requires a .NET versus J2EE discussion.
J2EE and .NET are remarkably alike, both in terms of objectives and the range of their various components and systems. Of course, applications and application development with the two platforms are not alike at all; everything from tools to languages to methodologies are different. At their respective cores, both .NET and J2EE provide the building blocks and technologies needed to build applications. Security abstractions, database support, back-end integration, system level services, transactions and messaging, run-time services, and more are all provided by the platforms themselves. Both J2EE and .NET provide "safe" environments in which applications run (the JVM and CLR respectively); both J2EE and .NET support the use of different languages within these environments (although this potential has been realized to a greater degree in .NET); both have a scripting solution designed for Web applications (JSP or ColdFusion for J2EE, ASP.NET for .NET); and both are incredibly powerful and capable.
Many organizations are going through a J2EE or .NET discussion, usually independent of any discussion about ColdFusion. And there are pros and cons to both options. J2EE wins when vendor independence, openness, and portability are a priority. .NET wins when it comes to tools, a better client experience, or simply a commitment to the Microsoft way (there is more to it than that, but that's an entire column unto itself).
However, as many are discovering, J2EE versus .NET is not always an either/or proposition. In fact, lots of organizations are discovering that they need both, and that the future is decidedly heterogeneous. This is especially true for larger organizations where there's room for both, and interoperability (primarily via SOAP) makes this a workable option.
If an organization has made the strategic decision to bet its future solely on Microsoft and .NET, then they probably should use ASP.NET. Sure, ColdFusion can coexist and interoperate with the .NET world, but ASP.NET will likely be the preferred option. For organizations going the J2EE route, well, I've covered that one already. But for most organizations, ColdFusion remains compelling, leveraging the worlds of J2EE natively and .NET via SOAP. In fact, some organizations have discovered that ColdFusion is the simplest way to create client applications that talk to both J2EE and .NET back ends, if that is needed.
So, ColdFusion or ASP.NET? That depends on what your IT future looks like. And unless the future is Microsoft and Windows only, ColdFusion remains an important cog in the IT engine.
PHP is not one that comes up often; there is not a significant overlap between PHP developers and ColdFusion developers. But, in the interests of presenting the complete story, here is what you need to know.
PHP is also script based. Pages contain code that is processed by the PHP engine. The PHP engine itself is open source, and the PHP language uses a syntax borrowed from C, Java, and Perl (the latter is important, as PHP is particularly popular with former Perl developers). PHP runs on all sorts of systems, and uses functions and APIs for all sorts of processing.
PHP's stated goal (as per the official PHP FAQ) is to "allow Web developers to write dynamically generated pages quickly." Ironically, developers with both CFML and PHP experience will tell you that while PHP development may be quicker than using C or Java, it does not come close to that of ColdFusion and CFML.
There is no refuting PHP's power; PHP developers have an impressive and rich set of functions and language extensions available, and that is definitely part of PHP's appeal. But this power comes at a cost.It takes a lot more PHP code to do what simple CFML tags do, and as explained before, more code = greater cost. If you truly need that power, then PHP may indeed be an option worth considering (although CFML+Java would likely give you the same power and more). But if what you really need is to "write dynamically generated pages quickly," then PHP leaves much to be desired.
One of the most compelling arguments for PHP is its cost there is none. But, as explained earlier, the cost of software is only one part of the total cost of application development, arguably the least significant cost in the long run. It is for this reason that despite being incredibly popular with developers and consulting shops, corporate users have been slow to adopt PHP as a development platform (which in turn is why the PHP versus ColdFusion discussion comes up so infrequently).
The bottom line is if you really need the power and flexibility of PHP and can justify the longer development cycles and more code to manage and maintain it, then PHP should seriously be considered. But if time to completion and total cost of ownership are an issue, then ColdFusion wins hands down.
And there you have it, the elevator-pitch arguments needed to defend ColdFusion, if the need so arises. Of course, the ultimate defense is results, and delivering results is something ColdFusion developers have proven themselves to be incredibly good at.
John Smith commented on 16 Dec 2004
John commented on 10 Dec 2004
Great article to help get started with JSR168. Please keep similiar portlet articles coming. Thanks!