|
Primer : Tag Libraries |
|
|
Under the JSP specification, a capability exists to allow developers to define
their own JSP tags. You would define how the tag, its attributes, and its body are
interpreted, then group your your tags into collections called tag libraries that
can be reused in any number of JSP pages.
The ability to define tag libraries in this way permits developers to boil down complex server-side behaviors into simple and easy-to-use elements that content developers can easily incorporate into their JSP pages. These tag libaries make for a more friendly team-development environment because instead of having complex code inside HTML pages, one would have HTML-looking tags that accomplish the same thing. |
|
This primer will define what tag libaries are and demonstrate how to use them.
|
|
1.
If VisualWorks is not already running, please start running it now, load the Web Toolkit
parcel and start a Wave HTTP server.
2. There is a file in the db directory of the sandbox site that contains a product file called products.csv. Let's create an SSP page that displays a list of products in this file. The result would be the following:
<html> <head><title>Products</title></head> <body> <center> <h2>List of Products</h2> <table border=1> <tr> <th align=center><b>Product Category</b></th> <th align=center><b>Product Number</b></th> <th align=center><b>Product Name</b></th> <th align=center><b>Product Description</b></th> </tr> <% prodFile := 'c:\vw72nc\web\sandbox\db\products.csv' asFilename. separator := $;. "semi-colon" stream := prodFile readStream lineEndCRLF. [stream atEnd] whileFalse: [ stream upTo: separator. prodNumber := (stream upTo: separator). category := (stream upTo: separator). stream upTo: separator. prodName := (stream upTo: separator). prodDesc := (stream upTo: separator). stream upTo: (Character cr). response write: '<tr>'. response write: ('<td>',category,'</td>'). response write: ('<td>',prodNumber,'</td>'). response write: ('<td>',prodName,'</td>'). response write: ('<td>',prodDesc,'</td>'). response write: '</tr>'. ]. stream close. %> </table </center> </body> </html>
Figure 1. A total "SSP" solution for the display of products 3. In a team environment, an HTML author would complain that there's too much code in this file for them to edit in their favorite HTML editor. What the HTML authors want is some sort of mechanism that would allow them to insert some type of "placeholder" that would create the list of products without the placeholder containing any code. This placeholder would be a tag library and the concept would look something (but not exactly) like the diagram below.
Figure 2. The concept of a tag library The idea is to create something that has an HTML syntax. In reality, tag libaries use an XML syntax, which in a way is a custom HTML tag. Also, tag libraries should be flexible and extensible, so that if the HTML author needed to display, say the price of the product, all they would have to do is add an element that refers to the products price, for example something like <price/>. 4. In order to use custom JSP tag (or tag library), you need to define 3 separate components:
Figure 3. The tag library components 5. Writing (or developing) a custom tag from scratch is beyond the scope of this tutorial, therefore we will make use of an existing tag that is delivered with the Web Toolkit. The tag we will use is called the DoTag and is designed to mimic the iterative functionality of the do: method of a collection. If you are interested in viewing the source code for this tag libary, the DoTag class can be found in the Web Toolkit-JSP category. 6. The first order of business is to create the tag library descriptor file that maps XML element names to the DoTag class. The file would look something like this:
<?xml version="1.0" encoding="ISO-8859-1" ?> <!--<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd"> --> <taglib> <tlibversion>1.0</tlibversion> <jspversion>1.1</jspversion> <shortname>cincom</shortname> <uri></uri> <info>An example tag library provided by Cincom </info> <tag> <name>do</name> <tagclass>VisualWave.DoTag</tagclass> <info>Like a getProperty, but expects a collection and iterates over the result, assigning to a loop variable</info> <bodycontent>empty</bodycontent> <attribute> <name>name</name> <required>true</required> </attribute> <attribute> <name>property</name> <required>true</required> </attribute> <attribute> <name>variable</name> <required>false</required> </attribute> </tag> </taglib>
Figure 4. The XML elements in the map file are instance variables 7. Save this file as producttags.tld. The tld extention stands for tag library descriptor. 8. Since custom tag libraries are specific to the JSP/J2EE model, they are designed to be used with beans and the getproperty directive of the bean (object). This means that we must move the code in our SSP page into a custom class. This is no different that what we did in the SSP fundamentals lesson and should come as no surprise since the HTML author wants absolutely no "code" in the page. 9. Below are the customs classes that we will create for returning a collection of products.
Figure 5. The custom classes for our tag libary / products example
10. Once these classes (and methods) have been created, it will take a lot less code in our SSP to create a list of employees. As you can see, if it doesn't take much less code to retrieve the list of employees in a workspace, the same will be true in the SSP.
Figure 6. A workspace solution 11. Below is a solution that uses a combination of custom classes and SSP. With this solution, there is much less code in the SSP to list products. In short, objects do the work; SSP does the display.
<html> <head><title>Products</title></head> <body> <center> <h2>List of Products using Custom Classes</h2> <table border=1> <tr> <th align=center><b>Product Category</b></th> <th align=center><b>Product Number</b></th> <th align=center><b>Product Name</b></th> <th align=center><b>Product Description</b></th> </tr> <% products := (TagStuff new) products. products do: [ :each | response write: '<tr>'. response write: ('<td>',each category,'</td>'). response write: ('<td>',each number,'</td>'). response write: ('<td>',each name,'</td>'). response write: ('<td>',each description,'</td>'). response write: '</tr>'. ]. %> </table </center> </body> </html>
<html>
<head><title>List of Products Using Tags</title></head> <body> <%@ taglib uri="file:producttags.tld" prefix="cincom" %> <jsp:usebean id="products" class="TagStuff" scope="page"/> <center> <h2>List of Products Using Tags</h2> <table border=1> <tr> <th align=center><b>Product Category</b></th> <th align=center><b>Product Number</b></th> <th align=center><b>Product Name</b></th> <th align=center><b>Product Description</b></th> </tr> <cincom:do name="products" property="products" variable="each"> <!-- [DO-Tag] Generates one table row --> <tr> <td> <jsp:getproperty name="each" property="category"> Product Category </jsp:getproperty> </td> <td> <jsp:getproperty name="each" property="number"> Product Code </jsp:getproperty> </td> <td> <jsp:getproperty name="each" property="name"> Product Name </jsp:getproperty> </td> <td> <jsp:getproperty name="each" property="description"> Product Description </jsp:getproperty> </td> </tr> </cincom:do> </table> <br><br> </center> </body> </html> Save this file as products_tags.jsp. |
|
Indeed, there is a lot going on here. Let's look at all this code line by line
(or chunk by chunk) and make sure you understand what each line (or chunk) does.
<%@ taglib uri="file:producttags.tld" prefix="cincom" %>
This line identifies the XML mapping file to use. The prefix of cincom will be used later in the page as a tag library identifier.
<jsp:usebean id="prods" class="TagStuff" scope="page"/>
This line which class we will use (TagStuff) and the name by which we will reference the class (prods) later on in the page. The scope of page is used since all we are trying to do is get the tag library to work on just one page. However, if the list of products is needed in other parts of our application, then a scope of session would be more efficient.
<cincom:do name="prods" property="products" variable="each">
This line starts our looping block. Although not shown here, the looping block ends with </cincom:do>. This line has many similarities (references) to the standard Smalltalk iteration code of:
<jsp:getproperty name="each" property="category">
Product Category </jsp:getproperty> These lines use the standard JSP directory of getproperty and identify the name of the iteration variable (each) and the name of the instance variable - or getter method - (category) to fetch and display the item of your choice. Note also this is repeated for number, name and description. And never mind about the text between the jsp:getproperty tags; that text will never get displayed since the VisualWave engine will replace this text with the text that gets recieved from the method identified by the property attribute.Below are 2 diagrams that depicts the relationship bewteen all these tags.
Figure 7. How all the tags point to one another
Figure 8. More interrelationships |
|
Summary
As you can now see, tag libraries are mechanisms by which you can replaced code with HTML-looking constructsthat do the same thing as the code. The benefis are that these libraries can be re-used in multiple SSP pages and they lend themselves to a team development environment. |