|
<taglib:tutorial lesson="17"/>
In this part of the tutorial, we will look at how dynamic attribute names can be utilized
1 Lesson 17, Dynamic attribute names
In this part of the tutorial we will look closer at the DynamicAttributes interface and how this can be utilized by classic and simple Tag Handlers to allow for page authors to specify attributes that is not listed in the Tag Handlers descriptor. We will continue to use the setup previously defined for this tutorial. During this lesson you will implement a SimpleTag that can be uses to handle Exceptions specified by the page author. You will then learn how to describe that the Tag Handler accepts dynamic attributes in its Taglibrary descriptor. Finally you will get to write a JSP view that can be used to try it out.
2 What are Dynamic attribute names?
With JSP 2.0 came the possiblity for Tag Handlers to accept attributes other than those explicidly named in the Tag Handlers descriptor. This can be acomplished by letting the Tag Handler implement the javax.servlet.jsp.tagext.DynamicAttributes interface and adding a <dynamic-attributes> element to the Tags descriptor with a body of "true".
 Figure 1. The DynamicAttributes interface
Instead of throwing an Exception at translation time, the Container will pass any undeclared variables to the setDynamicAttribute method of the Tag Handler that implements the DynamicAttribute interface with the namespace (if not default), name and value of the attribute. The Tag Handler can then decide what action to take, as it is up to the Tag Handler to remember the dynamic attributes passed to it.
So given that the Tag Handler implements the DynamicAttributes interface and has been configured to handle dynamic attributes, the Container will call the setter method of all attributes that has an corresponding attribute element in the TLD. For attributes that does not have an attribute element in the TLD, the container will call the Tag Handlers setDynamicAttribute method.
Notice though, that specifying the same attribute name more than once is still illegal and will throw an Exception at translation time.
With this ends the introduction of the DynamicAttributes interface. If you want to learn more or gain a deeper understanding about the interface, consult the
JSP 2.0 API or the
JSP 2.0 specification.
no duplicate attribute name (translation time exception)
3 Creating the SimpleCatchTag
To demonstrate how dynamic attribute names can be used we will now write a new version of the ErrorTag that we used as sample for the TryCatchFinally interface back in lesson 11. The new version will be a Simple Tag Handler that implements the DynamicAttributes interface. As the TryCatchFinally interface can only be utilized by Classic Tag Handlers we will implement the same functionality on our own.
 Figure 1. The SimpleCatchTag extends the SimpleTagSupport class and implements the DynamicAttributes interface
As can be seen in the UML diagram above, the SimpleCatchTag is based on the SimpleTagSupport class that implements the DynamicAttributes interface.
The SimpleTagSupport class is extended in order to take advantage of some of its utility methods, such as the getJspContext and getJspBody mehtods.
The DynamicAttributes interface is implemented in order to be able to accept any number of Exceptions that the Tag Handler should catch.
The Tag Handler will let the user specify two aditional attributes in the form of JspFragments:
catch - a JspFragment (see lesson 16)that if specified will be invoked instead of the body if a Exception is thrown that the Tag Handler is told to catch.
finally - a JspFragment that if specified will be invoked after that the body (or catch fragment) has been invoked.
Thanks to the use of the dynamic attribute names, a page author will be able to specify any number of Exceptions that the Tag Handler should catch by specifying attributes whos names should start with the characters "exception" and the value should be the classname of the Exception to catch.
-
In the '/WEB-INF/classes/com/acme/tag/' directory, create a new class called 'SimpleCatchTag.java' with the following content:
package com.acme.tag;
import javax.servlet.jsp.tagext.SimpleTagSupport; import javax.servlet.jsp.tagext.DynamicAttributes; import javax.servlet.jsp.tagext.JspFragment; import javax.servlet.jsp.JspException; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.List;
public class SimpleCatchTag extends SimpleTagSupport implements DynamicAttributes { private JspFragment catchFragment; private JspFragment finallyFragment; List exceptions = new ArrayList();
|
Listing 1: The start of the SimpleCatchTag.
In the listing above we define the variables that will be used to hold the catch and finally fragments, as well as a list of all Exceptions that should be caught.
-
Continue with the following:
public void setCatch(JspFragment fragment) { this.catchFragment = fragment; }
public void setFinally(JspFragment fragment) { this.finallyFragment = fragment; }
|
Listing 2: Setters for the defined attributes.
Above we define the two setter-methods that the Container will use to set the two attributes catch and finally that will be defined in the Taglibrary descriptor.
-
Continue with the following:
public void doTag() throws JspException, IOException { try { StringWriter writer = new StringWriter(); this.getJspBody().invoke(writer); this.getJspContext().getOut().write(writer.toString()); }
|
Listing 3: The try clause.
In the listing above, we use a StringWriter to hold the output from the evaluated body in order to avoid that any part of the body is outputted in case of an Exception. Directly after the invocation of the body JspFragment, the output is written to the current JspWriter stream. In case of an Exception any generated output is discarded.
-
Continue with the following:
catch(Throwable t) { if(exceptions.contains(t.getClass().getName())) { if(catchFragment != null) { catchFragment.getJspContext().setAttribute("excep", t); catchFragment.invoke(null); } } }
|
Listing 4: The catch clause.
The catch clause above first checks if the classname of the Exception thrown is amongst the classnames of the Exceptions the Tag Handler is supposed to catch. If this is the case, and a catch fragment has been given, the Throwable is added to the context of the catch fragment whereafter the fragment is invoked.
-
Continue with the following:
finally { if(finallyFragment != null) finallyFragment.invoke(null); } }
|
Listing 5: The finally clause.
The finally clause above invokes the given finally fragment.
-
End the SimpleTag with the following:
public void setDynamicAttribute(String uri, String localName, Object value) throws JspException { if(localName.startsWith("exception")) { exceptions.add(value); } } }
|
Listing 6: Handing the dynamic attribute names.
In the listing above, any dynamic attribute with a name that starts with "exception" will have its value (which should be the name of an Exception) added to the list of Exceptions the Tag Handler is supposed to catch.
|
By now, your SimpleCatchTag.java should look like this. Store the sourcecode in the /WEB-INF/classes/com/acme/tag/ directory as SimpleCatchTag.java
|
-
Compile the SimpleTag. If needed, details are given here. The result should be a file named SimpleCatchTag.class in the /WEB-INF/classes/com/acme/tag/ directory.
4 Update the Tag Library Descriptor
5 Presenting the new Tag
In order to use your new SimpleTag you will need a JSP page that uses it. We will therefore write a modified version of the ErrorTag.jsp file that we created in lesson 11.
-
Create a file called catch.jsp in the taglib-tutorial-web/ directory with the following content:
<%@ taglib uri="http://www.orionserver.com/tutorials/mytags3.jar" prefix="mt" %> <%@ taglib uri="mytags2" prefix="mt-old" %> <HTML> <HEAD> <TITLE>Page with error on it</TITLE> </HEAD> <BODY> <h1>before</h1> <mt:try exception1="javax.servlet.jsp.JspException" exception2="java.lang.NullPointerException" > <jsp:attribute name="catch"> <h2>Exception was: ${excep.message}</h2> </jsp:attribute> <jsp:attribute name="finally"> <h2>Always seen, Exception thrown or not</h2> </jsp:attribute> <jsp:body> <hr> <mt:throw/> <hr> </jsp:body> </mt:try> <h1>after</h1> </BODY> </HTML>
|
Listing 6: The catch.jsp file
As writing a Scriptlet that throws an Exception is illegal (the body of a SimpleTag may not hold Scriptlets), we use the ExceptionThrowingTag from lesson 11 to throw a suitable Exception for us.

|
By now, your catch.jsp should look like
this. Store the file in the
taglib-tutorial-web/ directory as
catch.jsp.
|
6 Using your new Tag
We are now ready to use your new Tag.
|
Open the URL
http://localhost/taglib/catch.jsp in a normal web browser. Hopefully the result looks like
this.
|
Continue with lesson 18", "Writing EL functions".
Copyright ©
2005 IronFlare AB
|