Taglibs: Designing Web APIs for the Non-Programmer Blog


    As the number of web pages and web applications that need to be written rises, more and more non-coders wi ll need to write them. There simply isn't the budget or time for professional programmers and graphic designers to write them all. But this can only happen if we have a development platform that is reliable, concise, and easy to use. JSPs and taglibs have the potential to be this platform, but only if the tags are written well. This article will discuss the usability of taglibs and demonstrate the lessons learned from three redesign case studies.

    Taglibs: Visual Basic for the Web

    Just as Visual Basic brought simple desktop programming to the masses, web programming will increasingly be done by non-professionals. As we approach the day where every group of any kind has a web page, there simply won't be enough time and budget for professionals to write all of them. More web software will be written by people who don't have the time to learn full structured programming. They will make brochures, mailing lists, calendars, and online polls. There will be a lot of commonly requested features that simply need to be customized. These customers will need a Visual Basic of the web.

    As components of the J2EE system, JSP scriptlets and taglibs have the potential to be such a development system. J2EE is robust and reliable, with the ability to isolate applications from each other and from general concerns like load balancing and logging. J2EE makes a multi-customer hosting business practical.

    For those of you not familiar with them, taglibs are Java classes that convert an HTML element (tag) into new output before the page is sent to the user. It could be as simple as having<util:date> become January 1st, 2004, or as complicated as generating inline charts and reports. The important thing is that you, as the programmer, can use Java to write an encapsulated extension to HTML. To the web page writer, it looks like the extension is simply a magic tag; it's as if the browser itself now supports a new HTML element that does neat things.

    Taglibs are particularly good for non-professional developers. They integrate well with visual editors and provide a comfortable interface for people only familiar with the declarative programming of HTML. When properly designed, taglibs are easy to use, powerful, and can scale without any work from the end user.


    Like all software, taglibs have their own unique usability problems. The user interface (UI) of a taglib isn't buttons and menus, but tags and attributes. With a graphical UI, there is a cognitive cost to adding features. The features still display, even if the user never uses them. Witness the many unused buttons in the typical Microsoft Office application. Each extra piece of functionality costs the user a tiny bit of their concentration and memory, of their cognitive load. With a tag-based UI, however, the user has to know about a feature in order to use it, so unused functionality is hidden. A user can use two tags of a tagset and never know about the other fifty. This is the sign of a scalable UI. The cognitive load scales directly with the complexity of the task. Easy tasks require little knowledge; hard tasks require more knowledge.

    We have to be careful, though. In some sense, the UI for a taglib is really the documentation. If the manual is long or hard to read, then the application will be hard to use. Some taglibs have complex features that need lots of documentation. In these cases, we must make sure that the simple basic features can be used with very little reading; say, a single paragraph. Then, extra documentation can be read to learn how to do more complicated tasks.

    Defining our Audience

    A common technique for designing usable software is to create a synthetic user: an imaginary person who embodies the type of user for which we are writing. This user will have a name, job, and background. By personifying the user, we can get a better mental grasp of the problems this user will have, and how they will react under different circumstance.

    For this article we will create Bob, a veterinarian. As a new vet, he is a very busy man. He wants to create a web site for his struggling practice with updated news, a calendar, and simple navigation from page to page. His practice is too small to afford a professional designer, so he'll have to do it himself. He could learn to program JSPs with scriptlets, but he would rather spend his time helping animals. He can use a visual editor and knows enough about HTML to fix broken links. Bob is our target user.

    Bob's constraints tell us that our programming solution needs to be easy to use, quick to learn, and very reliable. It must have low load on the sysadmin, because Bob can't pay for much support. In short, Bob needs very good but very targeted software. This is why we want clean taglibs for Bob. Now let's redesign three tags for him to use.

    An RSS Tag

    <rss:contentfeed href="http://coolnews.org/feed.xml" id="coolnews"> <rss:for-each id="coolnews" item="item"> <b><%=item.getTitle()%></b><br> <%=item.getContent()%><br> <hr> </rss:feed>

    This is an RSS tag. It reads from an RSS feed and prints each item. It uses ids to mark the feeds and requires afor loop with scriptlet syntax. Our goal is to rewrite this tag to make it do as little as possible and let Bob use as much standard HTML as possible. The more attributes and tags that are required, the more Bob will have to learn before getting things to work. We want our users up and running with the simplest possible usage of a tag, and then we'll build upon that.

    So what does an RSS tag do? It reads from an RSS feed and prints each item. At a minimum, we need the URL of the RSS feed. While our users may not understand what an RSS feed is (an XML document returned over HTTP) they will probably understand that if you stick in a special URL from your news service, say The New York Times, then the headlines should come out. Now what should we call the attribute? RSS, LINK, FEED? While all of these may make sense in our domain, we need to consider our audience. What would Bob think? Well, Bob is familiar with web pages and he understands that the image tag puts an image in his web page. It would be a logical next step that an RSS tag puts an RSS feed in his web page. So we will follow the HTML lead and use src for the URL.

    Next we need to print out the title and content of each item. We can do this with title and body tags. The names are simple and unambiguous. Presto -- with a four-line example, Bob can now embed an RSS feed in his web page. The most common case is now the simplest to access.

    <rss:feed href="http://myblog.org/feed.xml"> <b><rss:title/></b><br> <rss:content/><br> <hr> </rss:feed>

    This will produce output that looks like Figure 1:

    Figure 1
    Figure 1. Output of the RSS tag

    Documenting the RSS Tag

    How can we document this? I once heard of a TV that required 15 minutes of setup screens and reading the manuals to install. Until the setup was finished, the TV could not be used for watching TV shows. When it takes fifteen minutes to make a device perform its primary purpose, then something is wrong. Any piece of software should perform its most primary function immediately. iTunes, for example, plays music and it does it very, very well. It does lots of other things, too, but you can make it play music after looking at it for about five seconds. Everything else is secondary. If you can't explain how to use the software in a single printed page (or on a single web page, "above the fold") then it's too complicated. Either the program or its documentation needs to change.

    The best way to document the RSS tag is with an example. Show that the software turns "this" (the three tags) into "that" (sample output). This is a very direct way of explaining what the software does and how it does it. The primary purpose is clear, and Bob can immediately use the software without reading one word further. All other features can come after further reading, but the basic feature is right there. Score one for usability! Our documentation is shown in Figure 2.

    Figure 2
    Figure 2. Documentation of the RSS tag

    A Tree Menu

    Our next case study is slightly more complex: a tree menu. I adapted this from some open source code I found on the Internet. It did its task well, generating cross-browser tree menus, but it wasn't simple to use. It did, however, have the advantage of not needing external JavaScript files, which made it a good base from which to start. Now let's look at how it works and then discuss how we can make it better.

    <treetag:tree level="1" label="Menu 1" browser="<%=getHeader(&apos;user-agent&apos;)" image="folder" type="mac"/> <treetag:tree level="2" label="Sub Menu 1" image="document" type="mac" href="foo.html"/> <treetag:tree level="1" label="Menu 2" image="folder" type="mac"/> <treetag:tree level="2" label="Sub Menu 2" image="document" type="mac" href="bar.html" />

    This will create a tree menu that looks like a file browser mixed with Windows help. It has a folder, book, or document image next to each item. It works well and isn't too complicated, but it could be a lot better. The tree it produces looks like Figure 3:

    Figure 3
    Figure 3. Sample tree output

    First, why do we have to specify the depth level of each node? If the tags were nested, then the level could be figured out at runtime. There is no reason to have the user specify the depth level. This is something well written software should do for the user, so let's get rid of that attribute. We also see that the user has to specify the browser type with a Java scriptlet. This could also be easily done inside of the tag code without user intervention, so let's pull that out, as well.

    Finally there is a pair of attributes to specify the icon. One is the platform type and the other is a keyword specified that maps to a set of images using a config file. To add any new images, the user would have to modify the config file and put the images in a special directory, probably controlled by the sysadmin. This system is also pretty specific to file browsers and doesn't lend itself to other uses of a tree menu, such as for navigation. It would be better if the user could just specify the images directly. This would keep them from bugging the sysadmin and allow for non-local images via external URLs. Again we will use a derivation ofsrc, since most people are familiar with that naming convention.

    Here is our redesigned tree menu:

    <tree:tree> <tree:node label="Menu 1" opensrc="folder.open.gif" closesrc="folder.close.gif"> <tree:node label="Sub Menu 1" src="doc.gif" href="foo.html"/> </tree:node> <tree:node label="Menu 2" opensrc="folder.open.gif" closesrc="folder.close.gif"> <tree:node label="Sub Menu 2" src="doc.gif" href="bar.html"/> </tree:node> </tree:tree>

    We've also expanded this from one tag to two by having a separate tree tag that wraps the nested node tags. This delineates the tree as a whole from its parts, as well as from the rest of the page, which will be important as we add new features, such as styling.

    Styling the Tree

    The code above will create a tree, but it won't look like anything more than a list of links with some indentation. We have to specify styling. Styling is tricky because there are a million different ways to style a menu. One solution is to create a set of attributes on each tag for the font, dimensions, color, and border, but that would result in many, many attributes and might still not cover every possible usage. Another solution is to require the use of CSS, but of course the user would have to understand CSS, yet another thing to learn. What does Bob want? He probably understands colors and fonts and would only learn CSS by small examples. The best solution is to do both: have a limited set of attributes for the most common settings (colors and borders) and to require the use of CSS for anything more complicated. Now the tag code will look like this:

    <tree:tree border="1" bgcolor="#ff0000" color="#ffffff"> <tree:node label="Menu 1"> <tree:node label="Sub Menu 1" bgcolor="#0000ff"/> </tree:node> <tree:node label="Menu 2"> <tree:node label="Sub Menu 2" bgcolor="#0000ff"/> </tree:node> </tree:tree>

    We've added the border, bgcolor, andcolor attributes to the tree tag at the top. This sets those values for the whole tree. Bob can override the colors for each node as desired. This scheme handles quite a lot of cases while still being simple and easy to describe.

    For CSS styling, Bob will need to know what HTML is actually generated by the tags. We could document this or tell him to do a view source from the browser, but if we have nested tables, it could still be complicated. Instead, we provide named classes to access the different parts of the tree. Here is the final version:

    <style> .tree { width: 200; background-color: #ffff00; border: 1px solid black; } .top-node { font: 14pt bold sans-serif; } .node { background-color:#0000ff; font: 10pt sans-serif; } </style>

    With this design, Bob only learns enough to do the task at hand, but he is prepared for learning more complicated features. The styling and the API both scale with the complexity of the task.

    As a final addition we can add auto-opening. Since HTML trees are usually used for navigation, it would be nice if the branch that contains the current page was always open. This could be implemented by putting an open tag on each page to force the proper menu to be open. However, our code knows thehref of each node and the URL of the current page, so we can figure it out auto-magically most of the time. 99% of the time, this is exactly what the user wants, so let's make this the default and let the user turn it off in cases where it's not appropriate. I call this a passive feature, since it requires no intervention or even knowledge by the user to function. As our lives become more complex, I think we are going to see more and more of these kinds of features.

    An HTML Calendar

    Our final example is an HTML calendar. I've come across this one several times with small organizations that want a web-based calendar just to show when their next meeting or class is. They want it to look pretty but simple. It's not collaborative or dynamic. It's a small piece of software that should be simple to use, but as I found how out, dealing with dates can be very tricky.

    Let's start with the basics:


    This produces the calendar seen in Figure 4.

    Figure 4
    Figure 4. Basic calendar tag output

    Now that's a simple API. It prints a calendar for the current month with arrows to go forward and backward through time. As with the tree, styling is handled mostly through CSS. It's pretty simple to just display the calendar. Events, however, are another matter.

    Specifying events through structured notation is difficult, as the designers of virtually any calendaring software can attest. The basic idea is to have the user specify as much detail as needed and all other variables will be looped. It's not going to be perfect, but it should be enough to cover most tasks. Here's an example:

    <calendar:event day="31" month="12" year="1999" description="New Years Eve"/> <calendar:event day="31" month="10" description="Halloween"/> <calendar:event day="5" description="Rent due!"/> <calendar:event day="Tuesday" description="Dance class"/> <calendar:event day="Monday" week="1" description="Neighborhood Meeting"/>

    This produces the calendar seen in Figure 5:

    Figure 5
    Figure 5. Calendar with event tags

    The first event is New Year's Eve, 1999; a one-time event. The second is on the 31st day of every 10th month, or every Halloween. The third is on the fifth of every month, and the fourth is every Tuesday. Finally, the fifth is every Monday in the first week of a month, or the first Monday of each month. These five examples cover almost every possible event someone could want, in a clear syntax. There are only four attributes to learn and they directly relate to the Bob's likely mental model.

    To make this truly easy to use we would want to handle alternate forms of each value, most of which we can do with help fromjava.util.Calendar. We can ignore capitalization, support localized spellings of the weekdays, and allow the use of month names instead of numbers. Any strange form of data entry should be supported, if at all possible. The more mental work we can remove from Bob's web coding, the better he can perform his real job.

    Leaving Out Features

    I should note that some features were specifically left out. There is no way to specify a time of day or use advanced selectors, such as "do this every business day." These features are common in personal planners, but aren't actually relevant to our users. Setting the time of the event doesn't matter because this calendar isn't used as an alarm. It's a calendar on a web page, not a PDA or Outlook. The time can be included in the description, but our software doesn't need to do anything special with it. The second feature, specifying more than one day a week, is a timesaver but doesn't add anything new. Bob could just make five of the same event. This is a good tradeoff, because setting up a calendar is an uncommon task. Bob will probably do a single setup and update it maybe once a month. The savings in learning time more than makes up for the time spent copying and pasting the event. As a compromise, though, we could accept comma-separated weekdays; a transparent addition to most users.

    Packaging and Documentation

    Now we have designed three JSP taglibs to handle relatively complicated tasks with a simple API. Before I finish, I'd like to talk a little bit about packaging. We want to make the software as easy to install as possible, since a failed install = failed software, and that doesn't help anyone.

    First we should package up all code as a .war file. Any support files, config files, etc. should be packaged up in the .war as well. Even the .tld can go in there. To help with the job of packaging, I recommend Ant tasks. In addition to the usual .jar and .war tasks, there are a few that auto-generate the documentation from the .tld file. This output should be used as a base but not a replacement for prose with examples. After all, you wouldn't want to learn MS Word by reading the function reference. (Actually, that might be kinda cool :) )

    There should be two separate sets of documentation, one for the installer and one for the user. This is because the user documentation will likely be forwarded by your customer, the admin, to his users, the people actually using your software. It's also a good idea to write all documentation as HTML with CSS stylesheets so that the admin can rebrand it if necessary.

    The installer's set should discuss what the software does, what resources it requires, and how to configure it. The taglib should, if at all possible, run with zero configuration: just a single entry in the web.xml file. Sensible defaults and auto-detection really help out here. The second set of documentation is for the user. It only covers what the software does and how to use it. It should start with simple examples using the primary function of the taglib, then build upon that. That way, the users can start at the beginning and only read enough to do what they want.

    Source Code

    The three tags I've described here are released as open source and are available as taglibtools.zip. I developed them specifically for non-technical users. The RSS feed was for my sister, who is an actress with a weblog. The calendar was for the president of my neighborhood association. The tree was for the redesigned neighborhood web site that my girlfriend, a print designer, has created. All three are smart but non-technical people with better things to do than learn my APIs. The tags had to be reliable, so that I didn't have to fix them, and simple, so that I didn't have to answer lots of questions.


    In this article, I have covered the basics of usability for software and then shown how that is applied to the UI of taglibs. We've learned the golden rules of UI design:

    1. Know your audience. Just like art, code needs an audience to be relevant, and different audiences need different programs.

    2. Reuse your user's brain. Use well previously known metaphors and notations wherever possible.

    3. Minimize configuration. Use auto-detection and reasonable defaults.

    4. Make your UI scale. Complexity of the UI should grow linearly with the complexity of the task.

    5. Make your documentation scale. The user should have to read enough to get the job done and no more.

    6. Handle malformed and unusual input wherever as possible.

      And most importantly ...

    7. Don't waste your user's brain. This means his or her time and cognitive abilities. Your user is using your software to save time. Successful (and popular) software won't waste it.

    I hope I have also demonstrated how important taglibs will be to the future of the Web. If they are to be heavily used, and I hope they will, then ease of use will be the primary factor in their design.