• Aucun résultat trouvé

Bodyless Custom Actions

Dans le document Beginning JSP, JSF and Tomcat (Page 104-108)

A bodyless action is an element that, not having an end tag, cannot enclose a body between start and end tags. As an example, let’s say you want to develop an action that prints the day of the week of any given date:

<wow:weekday date="date"/>

With the date attribute accepting values in the form yyyy-mm-dd and defaulting to the current date.

All the examples of this section on bodyless actions and the following section of bodied actions are in the software package for this chapter. To test them, copy the folder tags to Tomcat’s webapps folder.

Step 1: Define the Tag Handler

A tag handler for a bodyless custom tag is a class that implements the interfaces java.io.Serializable and javax.servlet.jsp.tagext.Tag. Remember that to satisfy an interface, you have to implement all the methods it defines.

To satisfy Serializable, you only need to define a unique identifier, like this:

static final long serialVersionUID = 1L;

The value identifies the version of your class and the objects you instantiate from it. It is then used when deserializing objects to check that class and object match. As long as you don’t have several versions of the class and swap objects between JVMs, you don’t really need to worry about it. However, to satisfy the Tag interface, you have to define the methods listed in Table 4-1.

Table 4-1. The Methods of the Tag Interface

Method Description

int doEndTag() Processes the end tag

int doStartTag() Processes the start tag

Method Description

Tag getParent() Provides a reference to the closest enclosing tag handler

void release() Removes all the references to objects

void setPageContext(PageContext pc) Sets the current page context void setParent(Tag t) Sets the closest enclosing tag handler

Fortunately, the javax.servlet.jsp.tagext.TagSupport class makes life easier by implementing the Tag interface with default methods and other useful methods. Therefore, you only need to extend TagSupport and overwrite the methods you need for your weekday action. You certainly don’t need getParent, because the action isn’t going to be used in the body of other actions. You don’t need doStartTag either, because the action is bodyless, and, as a consequence, you don’t have separate start and end tags. In conclusion, you only need to overwrite doEndTag with a method containing all the functionality of the weekday tag.

Listing 4-11 shows you the code of the whole tag handler.

Listing 4-11. WeekdayTag.java

package tags;

import javax.servlet.jsp.JspException;

import javax.servlet.jsp.tagext.TagSupport;

import java.util.Date;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.GregorianCalendar;

public class WeekdayTag extends TagSupport { static final long serialVersionUID = 1L;

static final String[] WD = {"","Sun","Mon","Tue","Wed","Thu","Fri","Sat"};

private String date;

public void setDate(String date) { this.date = date;

}

public int doEndTag() throws JspException { GregorianCalendar cal = new GregorianCalendar();

SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");

fmt.setLenient(true);

if (date != null && date.length() > 0) { Date d = new Date();

try {

d = fmt.parse(date);

}

catch (Exception e) {

throw new JspException("Date parsing failed: " + e.getMessage());

}

cal.setTime(d);

} try {

pageContext.getOut().print(WD[cal.get(Calendar.DAY_OF_WEEK)]);

}

catch (Exception e) {

throw new JspException("Weekday writing failed: " + e.getMessage());

}

return EVAL_PAGE;

} }

You need the setDate method because Tomcat uses it to pass the value of the action’s date attribute to the tag handler. The corresponding getDate method isn’t present, because it is never used and can be omitted. That said, you might argue that working with incomplete Java beans, sooner or later, will get you into trouble. If the action is executed without the date attribute, the date variable defined in doEndTag remains set to null, and the calendar cal, which is used to determine the day of the week, remains set to the current date. On the other hand, if a date attribute is specified in the action, its value is parsed and used to set the calendar.

Notice that the tag handler is named like the tag but with the first letter capitalized and with the Tag suffix. This is a good practice to follow, although you can name your handlers whatever you like. You’ll see in a moment how to make the association between a tag and its handler.

The return value EVAL_PAGE means that execution should continue with the page code following the custom action. Use SKIP_PAGE to abort the page.

In any case, you must place your handlers in WEB-INF\classes\. For example, as WeekDayTag.java belongs to the package named tags, its compiled class must go into the folder WEB-INF\classes\tags\.

Step 2: Define the TLD

The TLD is an XML file that describes your tags so that Tomcat knows how to deal with them. Listing 4-11 shows the full TLD for the custom tag library.

Listing 4-11. wow.tld

<?xml version="1.0" encoding="UTF-8"?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ~CCC http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_1.xsd"

version="2.1">

<description>Example of a simple tag library</description>

<tlib-version>1.0</tlib-version>

<short-name>wow</short-name>

<tag>

<description>Displays the day of the week</description>

<display-name>weekday</display-name>

<name>weekday</name>

<tag-class>tags.WeekdayTag</tag-class>

<body-content>empty</body-content>

<attribute>

<name>date</name>

<type>java.lang.String</type>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

</taglib>

As you can see, the outermost element is taglib, which contains a tag element for each custom action (in this case, only weekday). Apart from tag, all taglib sub-elements in the example are for information purposes or to be used by tools and can be omitted.

The tag element contains an attribute sub-element for each action attribute (in this case, only date). Of the tag elements in the example, you can omit description and display-name. The sub-element name defines the custom action name; tag-class specifies the fully qualified class name of the tag handler; and body-content specifies the action to be bodyless.

The sub-element tag-class is what gives you the freedom to name your tag handlers anything you like. The sub-element body-content is mandatory and can only have one the following three values:

empty, scriptless, or tagdependent. The value scriptless is the default and means that the body cannot contain scripting elements, while EL expressions and JSP actions are accepted and processed normally.

The value tagdependent means that the body content is passed to the tag handler as it is, without any processing. This is useful if the body contains character sequences, such as <%, that would confuse Tomcat.

Note that up to JSP 2.0, body-content was mandatory, and body-content="JSP" was valid. This is no longer the case with JSP 2.1.

The attribute element in the example has three sub-elements: name, which sets the action attribute name; type, which sets the class name of the attribute value; and rtexprvalue, which decides whether the attribute accepts values at request time.

If you had used a type other than String, the value passed to the tag handler would have been of that type. For example, with an attribute defined like this:

<attribute>

<name>num</name>

<type>java.lang.Integer</type>

</attribute>

you would have included the following code in the tag handler:

private int num;

public void setNum(Integer num) { this.num = num.intValue();

}

When processing the start tag of the custom action, Tomcat would have parsed the string passed to the action (as in num="23") to obtain the Integer value for the tag handler.

If you had omitted the rtexprvalue sub-element or set it to false, you would have been forced to pass to the date attribute only constant values, such as "2007-12-05", instead of runtime values such as

"<%=aDate%>". (rtexpr stands for real-time expression).

Inside WEB-INF, create a folder named tlds and place wow.tld there.

Step 3: Use the Custom Action

Listing 4-12 shows you a simple JSP page to test the weekday custom action.

Listing 4-12. weekday.jsp

1: <%@page language="java" contentType="text/html"%>

2: <%@taglib uri="/WEB-INF/tlds/wow.tld" prefix="wow"%>

3: <% String d = request.getParameter("d"); %>

4: <html><head><title>weekday bodyless tag</title></head><body>

5: weekday today: <wow:weekday/><br/>

6: weekday <%=d%>: <wow:weekday date="<%=d%>"/>

7: </body></html>

Line 2 contains the taglib directive, line 4 uses weekday without the date attribute, and line 6 passes the request parameter d to the action. It’s as simple as that.

If you type in your browser http://localhost:8080/tags/weekday.jsp?d=2012-12-25, you get two lines, such as Today: Wed and 2012-12-25: Tue. If you type the URL without the query, the second line of the output becomes null: Wed. On the other hand, if you type a query with a bad date, such as d=2012-1225, Tomcat shows you an error page with a back trace that begins as follows:

org.apache.jasper.JasperException: javax.servlet.ServletException: ➥ javax.servlet.jsp.JspException: ➥

Date parsing failed: Unparseable date: "2012-1225"

To try out the example, you can simply copy the folder named tags from the code of Chapter 4 to Tomcat’s webapps folder. You can then execute the example by typing in your browser

localhost:8080/tags/weekday.jsp.

Note that if you modify the tag handler, you need to recompile it from the command line. To do so, type the following two commands:

cd c:\program files\apache software foundation\tomcat\webapps\tags\web-inf\classes\tags javac -classpath "C:\Program Files\Apache Software Foundation\Tomcat\lib\jsp-api.jar" ➥ WeekDayTag.java

You then also have to restart Tomcat.

Dans le document Beginning JSP, JSF and Tomcat (Page 104-108)