The following article, written by Cameron McKenzie and Sal Pece, is the first in a series of Portlet development tutorials appearing on TheServerSide. These tutorials and tips are designed to help any software developer who is looking to develop JSR-286 programming skills to become quickly adept at both basic and advanced portlet programming topics, empowering the developer to quickly create portlet-based software that can be effectively deployed to any of the standards-based portal servers on the market today.
What exactly is a portlet?
So, you want to develop portlets, eh? Well, we should probably baseline this whole process with a little bit of a discussion about just exactly what a portlet is.
A portlet, in the most vulgar sense, is simply a content-delivery vehicle. That's what a portlet does -- it delivers content to a user. Sure, a user can be as simple as a Web page, or as voluptuous as a handheld multimedia device, but that's all that a portlet really does -- it simply delivers content to an end user.
Portlets are not Web services; Web services are Web services. Portlets are not Web services. Portlets are not EJBs; EJBs are EJBs. Portlets are not EJBs. Portlets are not JavaBeans; JavaBeans are JavaBeans. Portlets are not JavaBeans. Portlets are, quite simply, standardized, Java-based, content delivery vehicles that render themselves within the confines of a portal page.
The mighty portlet interface
From the standpoint of an application developer, a portlet is any Java class that implements the javax.portlet.Portlet interface.
In many regards, a portlet behaves very much like a servlet from the Servlet and JSP API. Like a servlet, a portlet is a shy and reserved little creature that lives peacefully in a WAR file (Web Application aRchive). However, if you get a few drinks into a portlet and get it loaded, that little portlet remains loaded in memory forever, and it is not unloaded until the portal server shuts down or the administrator explicitly takes the portlet out of service. Once loaded, the single portlet instance can respond, in a threaded fashion, to an unlimited number of client requests, with the only restraint being the hardware limitations of the portal server on which it runs.
Figure 1. The Portlet interface and the methods it defines.
Lifecycle methods of the Portlet interface
The javax.portlet.Portlet interface defines four lifecycle methods, with the init and destroy methods used to allow a developer to take action when a portlet is first loaded, or when a portlet is unloaded by the portal server. Similar to the Servlet and JSP API, the method corresponding to a portlet's initialization is very uncreatively named init (PortletConfig config), and the method that maps to the unloading of a portlet is violently named destroy ().
The very generic portlet interface also defines two more very important lifecycle methods, namely the processAction method, which logically is intended to be used during the action-processing phase, and the render method, which as you could probably guess, corresponds to the rendering phase in which a portlet generates the markup fragment that eventually gets displayed back to the client.
The abstract class GenericPortlet
As a JSR-286 portlet developer, you will never create a class that simply implements the portlet interface. Okay, maybe never is a little bit of an exaggeration, but when you code your portlets, you don't implement the portlet interface directly, but you extend the abstract class GenericPortlet instead, which itself implements the javax.portlet.Portlet interface.
Along with providing a do-nothing constructor, and an implementation of the four lifecycle methods the portlet interface defines, the GenericPortlet class defines the pivotally important do<something> methods, namely doView, doEdit, and doHelp. These methods correspond to the three standard rendering modes of a portlet.
The GenericPortlet class also defines and implements a doDispatch() method, which is always called before any of the other do<mode> methods. Clever, eh? A method named doDispatch is used to dispatch incoming requests to the appropriate do<mode> method.
Figure 2. The methods of the GenericPortlet class.
What do portlets do?
Okay, so far we've discussed what a portlet is. In so doing, we have covered the mind-numbing details of the portlet interface and the abstract GenericPortlet class. That describes what a portlet is. But as developers, we are more concerned with what a portlet does, and more to the point, how it does it.
At the most fundamental level, portlets are simply presentation-tier components that handle a request-response cycle. When a request comes in from a client, portlets are responsible for inspecting that request, and figuring out exactly what the client is requesting.
Once the portlet has figured out what the crazy client is requesting, the portlet must then figure out how to respond. Before responding to a client, a portlet might use a bunch of EJBs or JavaBeans, Web services or JDBC, but eventually, a response must be formulated and sent back to the portal for portal page aggregation, after which content is finally returned to the client.
The essence of portlet programming is handling the request-response cycle. Conquer the request-response cycle, and the rest of the Portlet API will easily fall under your control.
Figure 3. The ancestry and the implemented interfaces of a custom portlet.
The most basic portlet
In the most basic sense, a portlet simply handles a Web-based, request-response cycle. As a portlet developer, our fundamental responsibility is to simply inspect the incoming request, and subsequently supply an appropriate response back to the user.
The Portlet API makes it very easy to develop delicious portlets that can intelligently respond to this Web-based request-response cycle. To create a portlet that can be viewed on any portal page, we simply create a Java class that extends GenericPortlet, and code a special method called doView.
And what do we do in the doView method? We implement some logic and eventually send some output to the client. The junk we output appears within the confines of a portlet window, on a portal page.
Figure 4. Output generated in the doView method is rendered within the confines of a portlet, which appears, aggregated, on a portal page.
The HelloWorldPortlet is an example of a very simple portlet that extends GenericPortlet, and simply outputs data to a client in the doView method. In this example, when the portlet is displayed on a portal page, the doView method is invoked, and the PortletResponse object is used to first set the response type to text/html and then deliver the Hello World message to the client.
The PortletRequest and PortletResponse
Two supremely important objects are passed to a portlet's doView method:
- a PortletRequest object, as the RenderRequest
- a PortletResponse object, as the RenderResponse
Everything a developer wants to know about the incoming request is stuffed inside the PortletRequest object. Anything a developer wants to do to the client is done through the PortletResponse object.
Okay, to say anything can be done to the client through the PortletResponse might be a bit of an exaggeration. The developer can't exactly slap an annoying end user across the face with the PortletResponse object; but a developer can send the annoying end user an HTML fragment with some snide comment embedded within.
Anything a developer wants to know about the incoming request is bundled up inside of the PortletRequest. Anything a developer is allowed to do to the client is done through the PortletResponse object. Conquer the request and response objects, and you've conquered portlet programming. Portlet programming is just that simple.
Of course, you don't have to limit your portlets to simple request-response handling. Few developers do. Java programming is all about freedom, and you are free to make your portlets as complex and as crazy as you want.
Fundamentally, though, all portlet development can be broken down to inspecting the incoming PortletRequest, implementing some logic, and then using the PortletResponse to deliver an appropriate reply back to the user. How you leverage the various services provided to you through the underlying application server that makes this whole portal thing possible is up to you. When it comes to portlet development, consider yourself the curator of your own funeral. ☺
Everyone loves a good WAR
Portlets don't exist in a peaceful little vacuum; quite the contrary actually, as they exist wrapped up within the confines of a violent WAR file. As I have said before, in its most banal form, a portlet is simply just a presentation-layer component, and in the Java world, the presentation layer is the domain of the Servlet and JSP API. Portlets piggyback off the Servlet and JSP API in a variety of ways, and one of the ways they hitch a ride on the Servlet-train is in their packaging. Both Servlet and Portlet applications are packaged and deployed as Web Application aRchives, aka WAR files.
Like all WAR files, a portlet WAR file contains a deployment descriptor named web.xml. The web.xml file pays homage to the Servlet and JSP heritage of the Portlet API, and is an important mechanism for describing how the Web container , which wraps around the portlet container in which a portlet application runs, should manage a portlet application.
<!-- The web.xml file isn't very sexy for a typical portlet application. --> <?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name>PortletBook</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
The portlet deployment descriptor: Portlet.xml
Accompanied by the required web.xml file, a portlet application deployment descriptor named portlet.xml also resides inside the WEB-INF folder of a WAR file. The WEB-INF folder branches directly off the root folder of the WAR. For the HelloWorldPortlet coded below, the corresponding portlet.xml file would look like as follows.
<?xml version="1.0" encoding="UTF-8"?> <portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" id="com.mcnz.portlet.HelloWorldPortlet.7aed100ae3"> <portlet> <portlet-name>HelloWorldPortlet</portlet-name> <display-name xml:lang="en"> HelloWorldPortlet </display-name> <portlet-class> com.mcnz.portlet.HelloWorldPortlet </portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> <title>Hello World Portlet</title> </portlet-info> </portlet> <default-namespace> http://portletbook/ </default-namespace> </portlet-app>
While both a servlet and a portlet WAR file contain a web.xml file, what sets a portlet application apart from a regular Servlet and JSP WAR file is the presence of this special portlet.xml deployment descriptor. For a portlet to truly exist, you must not only code a class that implements the portlet interface, but your portlet must also be defined in the portlet.xml file.
Conception and the Portlet API
The Java class that extends GenericPortlet and subsequently implements the portlet interface is like the sperm, whereas the definition of the portlet in the portlet.xml file is like the egg. Individually, they are nothing, but when the two of them come together within the ovaries of the portal server, our portlet truly comes to life.
At the very least, the portlet.xml file will define the portlet application, by providing a unique ID. A portlet.xml file will then define at least one, and potentially many, portlets. A single portlet application maps directly to the single WAR file that contains the portlet.xml file.
Furthermore, the portlet deployment descriptor will maintain a definition for each portlet contained within the given WAR file, with the definition including, at a minimum, a reference to the underlying Java class, the markup language and modes the portlet supports, and a title to be displayed above the portlet when it is rendered by the portal server.
The remaining elements of a WAR file
So far, we have established that a portlet application is packaged within a WAR file, and a WAR file, at the bare minimum, contains compiled Java code, along with a web.xml file, and a portlet.xml file, with those two files being the deployment descriptors for the Web module and the portlet application, respectively.
A WAR file will also contain a special manifest file, creatively named Manifest.mf, in a directory named meta-inf, which like the WEB-INF directory, sprouts out directly off the root of the WAR file. The manifest file should be used for maintaining the version of your applications. The contents of the manifest file, in a typical portlet application, is usually just a version number: Manifest-Version: 1.0. If you do not provide a manifest file of your own, the java -jar utility, or most automated WAR creation tools, will create one for you.
The Manifest.mf file is rather innocuous, containing nothing more than the following text string: Manifest-Version: 1.0
What exactly is a WAR file?
Now I hate to break it to you, but a WAR file isn't anything special. A WAR file is simply a compressed file, containing all of your portlet-related artifacts, all contained inside of a single zip file, with the extension of the zip file changed to .war. That's all a WAR file is.
You can actually change the extension of any WAR file to .zip, and it will open up with any standard zip based utility. Of course, with Java being Java, we can't call a zip file a zip file -- everything in the Java world has to have a cute and cuddly name, and nothing exemplifies the ideas of cute and cuddly like a good, wholesome WAR.
Packaging portlet aplications
So, a WAR file is really just a number of resources, zipped up into a single file, with that zip file maintaining the special folder structure needed for a portlet application.
Along with the required deployment descriptors, a WAR file will contain compiled Java code, placed in a package aware structure in a subdirectory named WEB-INF\classes.
As it has been stated before, a portlet application will also contain two deployment descriptors, named web.xml and portlet.xml, both of which will be happily placed together in the WEB-INF folder directly off the root of the WAR.
Finally, all WAR files will contain a rather mundane Manifest.mf file in a directory named META-INF, which like the WEB-INF directory, will be found directly off the root of the WAR.
The following shows you how the HelloWorldPortlet application, packaged in a file named mywar.war, would look if you inspected the contents with a WinZip utility.
Figure 5. Note the folder locations of the compiled Java class, and the deployment descriptors.
Do you have any quick tips for mastering Portlet API development? Let us know.
You should follow Cameron McKenzie on Twitter: @cameronmcnz
Interested in more articles and opinion pieces from Cameron McKenzie? Check these out:
- Why the Amazon S3 outage was a Fukushima moment for cloud computing
- Software ethics and why ‘Uber developer’ stains a professional resume
- It was more than user input error that caused the Amazon S3 outage
- Don’t let fear-mongering drive your adoption of Docker and microservices?
- Stop adding web UI frameworks like JSR-371 to the Java EE spec