Understanding Struts Custom Tags
If you write Java Server Pages, this article tries to bring together the pieces you need to know to write 'presentation logic'. This article is about custom tags, how to develop them and how to make maximum use of them. This article is also about tag libraries that come with Struts. What is covered is: what is a tag; what is a 'custom' tag; how you can build one; how they make life easier; and how Struts comes with tag libraries for developers to indulge.
Tag 101: What is a Tag anyway?
Anyone who has seen a HTML document has seen a tag. Simply put, a tag is some text enclosed between the characters "<" and ">". Tags have names, attributes and values. Tags may have a body or may be bodyless. An example of bodyless tag is:
<tagName1 attrtibute1="value1" attribute2="value2" />
Tags with a body have a start tag, a matching end tag and some content within them. An example of a tag with body is:
<tagName2 attribute1="value1" > <tagName3 attribute2="value2"/> </tagName2>
End tags always start with the character "/".
What is a 'Custom Tag' then?
HTML Tags are pre-defined. You cannot write HTML tags with names you like. A 'custom' tag is something you write so that the compiler/interpreter understands what it is supposed to do. For example, if you write <TABLE ...>, the browser understands that a table has to be displayed. However, if you want to arrange your documents according to chapters, you cannot write something like <CHAPTER...>. The browser will not understand the tag, because it is not a pre-defined HTML tag.
A custom tag, is thus, a tag, you write in your Java Server Page. When the jsp compiler encounters that tag, it knows what to do with it. It generates the proper HTML after doing whatever it is supposed to do.
Dissecting a Custom Tag
From a custom tag developer's perspective, a custom tag (or 'tag extension') has three parts:
- Write a Java class implementing one of the two interfaces, namely, javax.servlet.jsp.tagext.Tag or javax.servlet.jsp.tagext.BodyTag. Methods to implement include doStartTag(), doEndTag() for the Tag interface. Tag interface is implemented only for bodyless tags. For tags with body content, the BodyTag interface is implemented and the developer not only has to implement the doStartTag() and doEndTag() methods, but also doInitBody() and doAfterBody().
- Write a tag library descriptor, (TLD, for short), which is a XML document containing information about all the custom tags. This file has .tld extension. The TLD file conforms to a DTD. A sample entry in the TLD looks like this:
<tag> <name>TagName</name> <tagclass>package.name.TagClass</tagclass> <bodycontent>JSP</bodycontent> <attribute> <name>Attr1</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag>
Although not mandatory, the TLD file is usually placed under WEB-INF/tlds/.
- Declare the TLD in the web.xml file. web.xml is the standard descriptor file for any web application. The TLD is declared like:
<webapp> .... <taglib> <taglib-uri>/TLDNameAsDeclaredInTLD</taglib-uri> <taglib-location>/WEB-INF/tlds/my.tld</taglib-location> </taglib> </webapp>
Using a Custom Tag in your page
Now that the custom tag is built and deployed, it can be used in a JSP by:
- Declaring the TLD as a directive:
<@ taglib uri="TLDNameAsDeclaredInTLD" prefix="test" %>
- Using a tag "Tag1", which is a part of the TLD, in the JSP page:
<test:tag1 attr1="value1" attr2="value2" />
As soon as the runtime encounters the "test" tag, it knows a tag in that library is going to be used. In the above example, "tag1" in the library is used. When the runtime parses "<test:tag1", the doStartTag() method of "tag1" is triggered.
What is a software framework?
A software framework refers to a collection of classes and interfaces working in a cooperative fashion to facilitate application development. Just the way struts of a building holds the entire structure, a framework acts as a skeleton to an application.
Welcome to Struts
Struts framework is used for web applications where presentation data will change dynamically, and the choice of technology is Java. Struts is an open source project, and is a part of Apache Software Foundation. The latest version is 1.1.
Struts can be acquired from http://jakarta.apache.org/struts/acquiring.html.
You can download either a binary distribution or a source distribution. If you download binary distribution, the pre-requisite software applications are (a) Java Development Kit (Java version 1.2 or later), (b) a Servlet Container compatible with Servlet API specification 2.2 or later and JSP specification 1.1 or later and (c) an XML parser that is compatible with Java API for XML parsing specification 1.1 or later. If you have downloaded J2SE 1.4, then you do not have to worry about getting a parser, because J2SE 1.4 or later comes bundled with a parser.
If you choose to download the source distribution, then you have to download a plethora of software applications. http://jakarta.apache.org/struts/userGuide/installation.html gives you the entire list.
Bird's eye-view of Struts architecture
Struts uses the MVC design pattern, which stands for Model, View and Controller respectively. Controller is the component responsible for transferring data back and forth from the front-end (View) to the back-end (Model). Struts provides the controller (which is a servlet). View refers to the JSP's and Model refers to your business objects. They can be anything from Enterprise Java Beans, regular Java classes or Java Beans.
Overview of the common libraries
The Struts distribution contains four main tag libraries: html, bean, logic and nested for us to use in our JSP's. We will discuss only the three commonly used.
Brief description of the taglibs:
html: Contains tags to output standard HTML, including forms, textfields, checkboxes, radio buttons.
bean: Contains tags for accessing JavaBeans and their properties. Developers can also define new beans and set properties.
logic: Contains tags for generating conditional output, iteration capabilities and flow management.
Common features of Struts Tags
- Automatic Scoping: Struts tags check all contexts (namely page, request, session, application) and use the first instance found. Developers do not have to explicitly "retrieve" objects from a particular scope. They may, however, specify a context.
- Almost all Struts tags have attributes: id, scope, name, and property. id is the name of the variable to be used in the page, name is the name of the bean, property is the property of the bean to be set or accessed, scope is the context in which the bean is to be created or retrieved from.
- Nested references to properties can be made like:
property = "abc.def.ghi"which is equivalent to:
- Indexed references, like:
property="abc"which is equivalent to:
getAbc(3);or as a setter:
setAbc(3, value);This is a new feature, added in Struts 1.1
There are tags for rendering HTML image, link, and button. Interestingly, there is no tag for rendering a HTML table. A tag to look for is the ErrorsTag, which is required to display error messages on the page. After configuring the resource bundle, struts-config.xml, validation.xml and validator-rules.xml for error-handling, all one has to do is write "<html:errors/>" on the page where the error message needs to be displayed. Struts takes care of the rest.
All Struts HTML tags have some common properties, of which, name and styleClass stand out. name refers to the name of the ActionForm or JavaBean where the data is going to be gathered from. style and styleClass are used to specify the CSS files to be used to display these elements.
Tags in this library are responsible for rendering a bean, or bean property and creating a new JavaBean in any desired scope. Tags to look for, in this library, are cookie, define, header, message and struts. HeaderTag is used to retrieve any HTTP request header value. CookieTag is used to retrieve any value from a cookie or add any cookie in the response object. MessageTag is used for localization. Generally, <bean:message key="someKey">, renders value associated with "someKey" in the resource bundle. A common way of using this tag is to render page titles, labels. The titles, labels can be configured in the resource bundle like:
title.mainPage=Welcome to my HomePage title.catalogue=Catalogue Page label.submit=Submit label.subscribe=SubscribeAnd in the jsp page, you write:
This renders the text: "Subscribe".
The Struts tag exposes any Struts configuration object (ApplicationResourcesConfig, ActionConfig or any class in the org.apache.struts.config package).
Useful tags in this library, prevents writing Java code in JSP's. Tags used for conditional logic, are MessagesPresentTag, MessagesNotPresenttag, NoEqualTag, EqualTag. The IterateTag is useful for looping collections. RedirectTag and ForwardTag are used for rendering a HTTP redirect and forward respectively. The ForwardTag takes only one attribute, "name", which is the one specified in the global-forward element in struts-config.xml.
It is usually rare for a small project to write custom tags. What exists today, in the market is good enough for common tasks. Using custom tags mean cleaner JSP code, easier to maintain, reusable across applications. One point to note is that not all tags within the Struts libraries can be used outside Struts, but most can.
Struts is not the only destination if you are looking to add intelligence to your JSP's. Other places to look for tag libraries are:
Prepared by Saikat Goswami, Boston, Massachussets, firstname.lastname@example.org