Classic Custom TAG

Almost every developer has his own library of methods. And I wonder that few use their own tags on JSP page called custom tags. Any custom tag developer can reuse like any other method.
In the first part of my article I’d like to describe Classic Custom tags.
When you create Classic Custom tag than your class may implement one of three interfaces: Tag, IterationTag, and BodyTag or extends one of two classes TagSupport or BodyTagSupport. I advise you to use classes because in this case you should not implement all methods from interfaces.
Classes and interfaces from servlet.jsp.tagext package have the following hierarchy:

Tag
|
IterationTag TagSupport
|
BodyTag BodyTagSupport

 

You can create very simple tags if your class implements Tag interface. This tag does not allow to analyze and manipulate tag body (text between open and closed tag <mytag:tag> body </mytag:tag>) or use iterations to display body. First I will show how JSP container processes implemented tag called a tag handler and than I will write first simple tag.
1. setPageContext(PageContext pc) – we need PageContext to get JspWriter object for output
2. setParent(Tag t) – this method will help to get the predecessor of tag if necessary
3. setAttr (. . .) – to set and get attributes if our tag has it (<mytags:tag attr=”value”/>)
4. int doStartTag() – use this method to show something before body
if EVAL_BODY_INCLUDE returned – [JSP container processes body contents from opening and closing tags]
if SKIP_BODY returned – [skip body and go to doEndTag(), no output of body will be present]
5. int doEndTag() – use this method to show something after body
if EVAL_PAGE returned – [JSP processes the rest of page after the tag]
if SKIP_PAGE returned – [JSP container does nothing with the rest of the page after the tag]

To create the simplest custom tag need to execute four essential steps:
1. Write tag handler
2. Define the tag within a tag library definition (TLD) file
3. Provide details of where to find the TLD file in the deployment descriptor web.xml
4. Referencing the TLD file in JSP page and use tag

The simple tag just will output on page “Simple tag”.
1. As I sad before I will use class TagSupport instead of Tag interface.

2. The TLD file will be in /WEB-INF/tags/mytags.tld and will contain

I’d like to bring the special attention to elements <body-content>. It may have 4 different values empty, scriptless, tagdependent, JSP. The tag from example will not have body and I set it as emptyTagdependent means that everything inside body of tag is considered as template text and jsp container does not evaluate it. Scriptless – the body of the tag does contain regular JSP source, but no scripting language. JSP – any kind of JSP.
The second important element is <attribute>. It is sub element of <tag> and I will use it in the next example. It shows what kind attributes may have custom tag.

3. add reference to web.xml

4. JSP page custom-tag.jsp

Now I will show what brings IterationTag interface. It adds a method doAfterBody() which may return EVAL_BODY_AGAIN. We need this interface if we would like to use body of tag more than once.
Processing of JSP container IterationTag Interface
1. setPageContext(PageContext pc)
2. setParent(Tag t)
3. setAtr(. . .)
4. int doStartTag()
if EVAL_BODY_INCLUDE returned – [container processes body contents]
if SKIP_BODY returned – skip body and go to doEndTag()
5. doAfterBody()
if EVAL_BODY_AGAIN returned – [JSP processes body contents again ]
if SKIP_BODY returned – [exit from loop and go to doEndTag]
6. int doEndTag()
if EVAL_PAGE returned – [ JSP processes remainder of page]
if SKIP_PAGE returned – [ JSP container does nothing with the rest of the page]

The example with iteration will be tag mytags:iterate that print all elements of a collection in a new line.
The Jsp code will be as

Tag handler class will have name SimpleIterateTag. I’d like to notice that the first element of collection will print in doStartTag and others in doAfterBody method.

In TLD the description of tag will be as

Of cause you can use JSTL library core with the same effect but I repeat that it’s just example and I sure that your creativity will help to invent very interesting and necessary tags.

The third interface BodyTag helps to get body content in tag handler. The main object of BodyTag interface is the BodyContent object. A new return type for this interface is EVAL_BODY_BUFFERED. We use it in doStartTag() to create BodyContent object.
BodyContent has method getString() that returns the tag’s body.
And getEnclosingWriter() returns a type of JspWriter, with an important distinction: The contents are buffered.
The example for this interface will be more interesting. For division operation
EL convert float number to double and the result of ${9.21 / 3} =
3.0700000000000003
I will implement <mytags:divideNumber>${9.21 / 3} </mytags:divideNumber> = 3.07

Create DivideNumbers tag handler:

Description divideNumber tag in TLD:

The other examples of using BodyTag interface are tags with sql query:
<mytags:execSQL>select * from products</mytags:execSQL>
Or convert body of tag to lower case.
<mytags:tolowercase> tO loWeR CaSe </mytags:tolowercase>

The last example of this article shows how to use getParent method of Tag interface. User can implement dependency of tags (cooperating tags) when inner tag depends on outer tag.
For example:

Tag “message” prints value of attribute message of redColor tag. And redColor tag add <font size=’10’ color=’blue’> … </fonr> text. If “message” tag has two possible outer tags (redColor and blueColor) developer should use static method findAncestorWithClass or instanceof in tag handler. With findAncestorWithClass can get parent, or grandparent, or great-great-grandparent of inner tag.
Tag handler for “message” tag is SimpleMessage.java

Tag handlers for ColorBlueTag and ColorRedTag

TLD looks like:

That’s all! Thank you!

 

Leave a Reply

Your email address will not be published. Required fields are marked *