hross: January 2008 Archives

ALUI Performance Commentary

| | Comments (0) | TrackBacks (0)

Performance in the portal is a tricky subject, at best. There are plenty of external (and internal) factors that can contribute to poor performance, or the perception of poor performance and unfortunately for the conscientious system administrator, developer or project manager, it's not always easy to tell where the bottlenecks are.

Performance Comments

One simple thing you can do to analyze what is going on with your page performance is check the comments. What I mean is, by default there are performance comments built into every page in the portal (they can be enabled/disabled in your portalconfig.xml). Usually, they look something like this (these were taken from http://portal.plumtree.com/):

<!--Hostname: prodweb17--><!--Total Request Time: 1953
Control Time: 0
Page Construction Time: 1922
Page Display Time: 16
--><!--Portal Version: 6.1.0.253366, Changelist: 253366, Build Date: 04/02/2007 at 08:30 AM-->

All well and good, right? But what do these numbers mean? How about I start by quoting one of our internal knowledge base articles:

  • Total Request Time is the total time it took to process the HTTP request.
  • Control Time is the time it took for the MVC Control to process the request. The Control Time will be equal to -1 if no Control was called (i.e., the request went directly to the MVC View).
  • Page Construction Time is the time it took to construct the HTMLPage for display.
  • Page Display Time is the time it took to actually render the HTMLPage into HTML and write it to the HTTP Response.

Hmmm. Okay, how about a "revised standard English" version? As usual, I'm relying on various Gerald Kanapathy comments and my own testing and breakdown of the portal source code for this info:

  • Total Request Time - This is everything, basically a sum of all the below times.
  • Control Time - This is just the time it took to make decisions for the page. A lot of times this is going to be pretty low unless there are postbacks or things going on in the background. Usually custom PEI's and other logic will be executed here.
  • Page Construction Time - This is pretty much everything else, including how long it took to request HTML from all the portlets on the page and how long it took to render any transformer tags on the page. You will see a big reduction in this time the second time you hit most pages because of portlet caching.
  • Page Display Time - This is almost always very low (30 ms and lower, at least) and is pretty much a measure of network latency and performance of your application server. I don't think it really takes client-side latency into account, so I recommend you measure this using something like Yahoo's YSlow Firefox Plugin.

If you *really* want to be sure of these times and where custom code you wrote is executing, I recommend doing something simple like adding a 5 second Sleep statement in your PEI/Server API code/Portlet and seeing how it shows up in the page performance comments.

Another interesting note here is that these comments can help you diagnose image server problems. If your page request time is low but you still experience slow request times, you can start looking toward the image server for issues. Yahoo's YSlow Firefox Plugin is, again, a great resource for this (and for getting suggestions on performance improvement).

Is This Enough?

Although the comments can be very useful in diagnosing where a problem starts, they don't seem to be nearly enough, nor are they very specific. For instance, if there are 7 portlets on a page, which one is causing the construction time to whack out? Are my custom tags causing construction time problems or is there a lag in my remote portlet response?

As is normally the case here, I wouldn't ask the questions if I didn't already have the answers. In this case, my answer is that we can add our own performance comments to the page in the form of portal component replacement.

Since writing a portlet performance plugin turned out to be more challenging (and interesting) than I thought, and since I'm a sucker for cliffhangers, you'll have to wait 'til next time for the explanation....

Creating Custom Publisher JSP's

| | Comments (0) | TrackBacks (0)

First, let me apologize for my lack of posting for the last month and a half. I have no excuses. I have been lazy. That said, this should be a pretty interesting post...

Thus far, this blog has focused on fairly technical analysis and deconstruction of the ALUI product stack -- analysis which carries with it plenty of disclaimers, but should at least help the reader understand how the product works. This post is no exception -- in fact, this post will carry with it my biggest disclaimer yet:

Proceed at your own risk. What I am about to do is neither supported nor advocated by anyone at BEA. Not even me. This could break the product, make you a social outcast, even prevent you from playing on the company softball team. You have been warned.

Okay. Still with me anyway? Now that you're proceeding after ignoring my bolded advice above... how about being able to add your own custom JSP's to manipulate Publisher? And how about I start by explaining why you might think that's a good idea.

An Example: Edit Inline

Every good analysis needs an objective. In this instance, I'm going to pick a depreciated capability in Publisher 6.4, the ability to edit inline in a portlet. You generally see this capability in the Announcement Portlet Template, but it sure would be nice to be able to turn it on or off for all portlets/portlet templates, or even possibly fix portlets that don't have it turned on, for some reason. As you can see from the screenshot below, that's currently not possible in the Publisher UI:

object_categories 

Figure 1 - Edit Inline Capability in the Announcement Portlet Editor

How about we change that?

Tools You'll Need to Follow Along

As with any adventure, we won't get far without the right tools. In order to keep with this post, you're going to need the following:

WinRAR - I love this product. It'll extract any zip/rar/jar/war file and preserve folder structure, unlike WinZIP. Even better, it's cheap, easy to use, and has great Windows Explorer extensions. You'll never use WinZIP once you use WinRAR.

TextPad - You don't necessarily need a great text editor for this exercise, but having color coded text files is a life saver. I personally use this to open JSP files, so I'm not burdened by the overhead of a full-fledged IDE. This is my editor of choice.

Eclipse - You're going to need a Java IDE, whether you like it or not. There are other IDE's available, but Eclipse is free and one of the most popular. Plus, you'll need to use it in conjunction with the below...

Jad - Jad is a java decompiler. You may need this in some instances to figure out what is going on. It's a very simple command line executable that you can put in a folder somewhere and create an environment variable for.

Jadclipse - I cannot tell you how many times I have thanked my lucky stars that this product exists. It's an Eclipse extension that allows you to decompile java classes on the fly in the Eclipse IDE, which means you can right click any object in your source code, choose Open Declaration and view Java source.

I'm not going to teach you how to use these tools, nor point out their possible mis-uses, since there are a bajillion internet resources for that. I'm going to assume you have rudimentary knowledge enough to keep up. If you don't, then you probably shouldn't be doing this anyway =).

Deconstructing Publisher

The important thing to keep in mind is that Publisher itself is just a Java web application being hosted in a customized version of Tomcat. As such, we can do anything to it that we could do to any other custom web application, including: extracting files from the war file, analyzing the libraries, and adding our own JSP's to the war.

It turns out the adding JSP's part is the simplest portion of this exercise. All we have to do is open up the war file using WinRAR and drop them into the folder structure. But I'm getting ahead of myself. First, we have to figure out how we might go about writing a JSP that would change the Edit Inline capability. Let's start by taking a look at the main web application WAR file, found at:

$PT_HOME/ptcs/6.4/webapp/ptcs.war

As I mentioned, we can open this file in WinRAR, since it is compressed in the same manner ZIP files are. I prefer to just extract all of the files and folders to a directory, since we will need some of them later. The base directory should look something like this:

ptcs_war_contents

 

Next, I set up a quick workspace in Eclipse with a single Java project in it (make sure JadClipse is installed in this workspace). I then create a User Library: Window | Preferences -> Java | Build Path | User Libraries| New...

Usually, I call this library Publisher and I use the Add Jar's button to add all of the jar files in the WEB-INF/lib directory from the above ptcs.war file.

Once this has been done, I create one more User Library called Tomcat which contains all of the jar files in:

$PT_HOME/common/container/tomcat/5.0.28/common/lib

I then add both of these libraries to my Java Project's build path. At this point, we have referenced all of the libraries needed to build Publisher code in our Java project.

Astute readers will probably note that there are better ways (especially in Eclipse) to compile and test JSP's, but I am a simple man, and I find this works fine for my simple purposes.

Finding a Starting Point

Once we have built an environment, we need to figure out how to get Publisher to do what we want it to do. To me, this means finding a starting point for learning about how the product works. In my case, I happen to have worked with the product for quite a while, so this isn't particularly tough. In cases where you're not following my example, you will have to dig around the JSP's you find in the ptcs.war and try to make some sense of them.

In the case of Edit Inline, the place I started was [ptcs.war]/published_tools/content_item.jsp. Why start here? Well, I happen to know that this JSP is used by the News Portlet to do simple things like publish articles and create new ones. I also happen to know it's not that complicated in its mechanics, so it should be pretty easy to figure out.

Looking at the JSP, it turns out there's not much for us to see. The bulk of the heavy lifting done by the Publisher product is actually done in a bunch of java libraries contained in the WEB-INF/lib directory in the war (see the import statement near the top of the JSP for the packages which are used).

Building Our Own Library

I suppose there's not much mystery here, either. The easiest way to manipulate functionality in the product is to build our own library that does whatever we want, then insert it into the war file (this can be done simply by packaging our custom code in a .jar file and shoving the jar file into the WEB-INF/lib directory of the war file.

In my case, I want to build a page that will let me turn Edit Inline on and off for a particular portlet. To that end, I am going to create a static function that will automatically read (1) a portlet ID and (2) whether or not 'edit inline' is being turned on or off, from query string parameters on the URL. I will then write a simple JSP which calls that function when it is hit by a browser.

In order to make sure I was correctly instantiating a Publisher session and reading parameters, I used the code in com.plumtree.content.client.http.content_gadget.ContentGadgetTools as a model, then just extrapolated the Edit Inline part by spelunking the libraries and testing on my local Publisher instance. Since I wanted to keep it simple, this code sets Edit Inline only for the first content item in a portlet. It could be modified if other results were desired. Here is what I finally came up with:

package com.plumtree.content.client.http.content_gadget;

import com.plumtree.content.*;
import com.plumtree.content.app.PortletConfigEditor;
import com.plumtree.content.app.Session;
import com.plumtree.content.app.User;
import com.plumtree.content.client.http.*;
import com.plumtree.content.data.*;
import com.plumtree.content.util.portal.PortletId;
import com.plumtree.remote.portlet.*;

import javax.servlet.http.*;

public class RossContentGadgetTools {

    public static Session getSession(HttpServletRequest request,
            HttpServletResponse response) throws ContentException {
        
        // initialize a publisher session using the HttpClient object and portlet context
        ContentSystem.startup();
        HttpClient.initializePage(request, response);
        IPortletContext portletContext = PortletContextFactory
                .createPortletContext(request, response);
        
        // here's our session...
        String userName = portletContext.getUser().getUserName();
        Session session = null;
        String sessionId = null;
        sessionId = (String) request.getSession().getAttribute("sid");
        if (sessionId != null)
            try {
                session = Session.get(sessionId);
            } catch (DoesNotExistException e) {
                sessionId = null;
            }
        if (session == null) {
            int userId = portletContext.getUser().getUserID();
            session = User.login(userId, userName);
            request.getSession().setAttribute("sid", session.getId());
        }
        
        // return the session
        return session;
    }

    /***
     * Set edit inline for the first content item in a portlet
     * @param request
     * @param response
     * @return
     */
    public static String setInline(HttpServletRequest request,
            HttpServletResponse response) {
        try {
            // get the portlet ID
            int portletId = HttpClient
                    .getIntParameter(request, "portletId", -1);
            
            boolean editInline = HttpClient.getBooleanParameter(request, "inline", true);

            Session session = getSession(request, response);

            PortletToolbox toolbox = session.getSite().getPortletToolbox();
            PortletId pid = new PortletId(portletId);
            PortletConfig portletConfig = toolbox.getPortletConfig(pid);

            // instantiate the editor, set the first object to inline/not inline and
            // save
            PortletConfigEditor pcEditor = new PortletConfigEditor(session,
                    portletConfig);
            
            pcEditor.confirmEditing();
            // you could change the arguments here to something like 1,0, etc
            // depending on the portlet and item
            // (they could even be querystring arguments)
            pcEditor.setInlineEditing(0, 0, editInline);
            pcEditor.save();
            pcEditor.unlock();

            return "Success";

        } catch (Exception ex) {
            ex.printStackTrace();
            return "An error occurred. Check the log for details.";
        }
    }
}

As you can see, all I really did was build a single custom functionality and package it in the same namespace as similar tools used by Publisher.  In case you just want the completed library, here is a link to the jar file.

Leveraging Our Custom Library

Great. We have a function that appears to do what we want it to do. So now what? Now comes the easy part... we write a JSP that uses the function, then drop the JSP in our ptcs.war file. Here is what the JSP looks like. (view source to get a complete view) That's it. All I did was edit the war file using WinRAR and drag the update_inline.jsp into the top level directory.

Of course, there is one problem here: we have no direct link to the JSP in the portal. This means that our average user will never be able to get to the link (which is probably a good thing). But we know it exists, and we can use it. In order to change a portlet's Edit Inline setting, all you need to do is start up Publisher with the modifications mentioned, open the diagnostics page from Publisher Explorer, hit Control+N (this will give us a new window with a URL bar) and change the last part of the ptcs URL to point to the JSP with the query string arguments we require. For more detailed instructions, see the readme I wrote on how to install/use the customization.

You could also write an HTML page with a link to the JSP, all kinds of cool javascript options, etc, and create a portlet from the Publisher Web Service. Since I am lazy, I didn't do that.

Conclusion

First and foremost, read my disclaimer again. There is absolutely no support for doing what I describe in this post. Still... it's cool, it can lead to all kinds of neato functionality you could never hope to have without manipulating the product, and it will at least lead you to a much better understanding of what's going on under the covers.

Oh yeah, Happy New Year!

About this Archive

This page is a archive of recent entries written by hross in January 2008.

hross: November 2007 is the previous archive.

hross: February 2008 is the next archive.

Blogroll


Integryst

Function1

Fabien Sanglier

Bill Benac

Jordan Rose

Chris Bucchere

Robert Herrera

Nanek Blog Aggregator

Spartan Java




if you'd like to be listed here.




I don't blog about non-tech issues here, but you can check my Google Reader Shared Items if you want to know what I'm currently interested in.

Categories