Professional Documents
Culture Documents
In this session, we will look into how to build and deploy custom tags based on JSP 1.2. Later, in a separate session, we will talk about newly introduced custom tag features in JSP 2.0.
08/01/2006
Even though Sang Shin is a full-time employees of Sun Microsystems, the contents here are created as his own personal endeavor and thus does not reflect any official stance of Sun Microsystems. Sun Microsystems is not responsible for any inaccuracies in the contents. Acknowledgements The slides, speaker notes, and example code of this presentation are created from ? Core Servlets and JavaServer Pages book written by Marty Hall
?
Custom Tags section of Java WSDP 1.2 tutorial written by Stephanie Bodoff of Sun Microsystems
Many slides are borrowed from Sevlet/JSP codecamp material authored by Doris Chen of Sun Microsystems
2
08/01/2006
Revision History
? ?
10/13/2003: version 1: created by Sang Shin Things to do speaker notes need to be added and polished some concepts need to be explained better advanced usage scenarios (tag variables, listener, etc in JSP 1.2) still need to be discussed how does it work part needs to be polished up a bit
08/01/2006
Agenda I
? ? ?
Evolution of Web-tier technology What is and why custom tags? Components that make up custom tag architecture How to build, configure, and deploy custom tag library? How does it work?
4
08/01/2006
Agenda II
?
Defining a tag without attributes or tag bodies Assigning attributes to tags Including tag body Optionally including tag body Manipulating tag body Including or manipulating tag body multiple times Using nested tags
5
The majority of this session is devoted to explain usage scenarios of custom tags in increasingly order of complexity. For example, we will define first simplest tag which does not have any attributes nor tag bodies. Then we will create a tag that receive attributes from the calling JSP page. Then we will create a tag that includes a tag body. Next we will see how we can create a tag that can optionally include tag body depending on some business logic or input parameter. Next we will build a tag that manipulates and modify the tag body. And then we will see how we can include or manipulate tag body multiple times. Finally we will see how we can use nested tags.
08/01/2006
OK, let's talk about where JSP fits in from a big picture perspective of J2EE architecture.
08/01/2006
This picture shows the evolution of web application starting from a simplest one which then evolves into more sophisticated and more robust design. So in the first phase of the evolution, just static HTML pages were used to display static information. Then in the subsequent evolution phase, dynamic contents generation technologies such as CGI initially, then servlet and JSP are introduced to generate and display dynamic contents along with static contents. When you are using JSP pages, you can use only the basic features that come with it. Or you can leverage more sophisticated features such as component-based dynamic contents generation, for example, leveraging JavaBeans or custom tags, which provide more reusable, more maintainable, more flexible development and deployment options. Then in a more sophisticated environment, people use so-called template based design or eventually they might want to delegate their business logic processing to EJB tier.
08/01/2006
This picture shows how custom tags fit into the Web application architecture. Typically HTTP requests coming from the client are handled by the centralized controller, which in turn forwards them to JSP pages. The JSP pages then call server side objects for business logic processing. These server side objects can be either in the form of Java Beans or custom tags.
08/01/2006
<jsp:useBean>
Instantiate JavaBean object
<jsp:getProperty>
Allow accessing bean properties
<jsp:setProperty>
Allow setting bean properties
Now JSP container already provides simple but standard tags that allows JSP page designer to set and get properties of Java Beans instances. For example, the <jsp:useBean> tag instantiates Java Bean class without forcing page designers to use Java programming language. And <jsp:getProperty> and <jsp:setProperty> allows page designers to access and set properties of Java Bean instances.
08/01/2006
<jsp:forward>
Forwards request to another HTML page, JSP, or servlet
<jsp:include>
Includes output of another JSP file
<jsp:plugin>
Downloads Java plugin to browser to execute applet or bean
10
JSPalso provides standard tags for forwarding and including other JSP pages. <jsp:forward> tag forward request to other Web components while <jsp:include> includes data in a JSP page from another file. And <jsp:plugin> instructs the container to download Java plug-in to the browser to execute applet or bean.
10
08/01/2006
11
08/01/2006
? ?
User defined JSP language elements (as opposed to standard tags) Encapsulates recurring tasks Distributed in a custom made tag library
12
Custom tags are user-defined JSP language elements that encapsulate recurring tasks. Custom tags are distributed in a tag library, which defines a set of related custom tags and contains the objects that implement the tags.
12
08/01/2006
Be customized via attributes passed from the calling JSP page Pass variables back to the calling page Access all the objects available to JSP pages Communicate with each other
You can create and initialize a JavaBeans component, create a public EL variable that refers to that bean in one tag, and then use the bean in another tag
Custom tags have a rich set of features. They can * Be customized via attributes passed from the calling page. * Pass variables back to the calling page. * Access all the objects available to JSP pages. * Communicate with each other. You can create and initialize a JavaBeans component, create a public EL variable that refers to that bean in one tag, and then use the bean in another tag. * Be nested within one another and communicate via private variables.
13
08/01/2006
Getting/setting Implicit objects Processing forms Accessing database Flow control Iterations Many more
14
The standard JSP tags simplify JSP page development and maintenance. JSP technology also provides a mechanism for encapsulating other types of dynamic functionality in custom tags, which are extensions to the JSP language. Some examples of tasks that can be performed by custom tags include operations on implicit objects, processing forms, accessing databases and other enterprise services such as e-mail and directories, and flow control.
14
08/01/2006
Jakarta-Taglibs
15
Now there are ready to usable custom tag libraries. They are Java Standard Tag Library (JSTL), which contains custom tags for setting and getting attributes, handles iterations, and so on. It also contains tags for database access, tags for internationalized formatting and tags for XML manipulation. Also Jakarta tag library from Apache has been quite popular.
15
08/01/2006
Now let's talk about why you want to use custom tags.
16
08/01/2006
Provide
Portable semantics
17
Custom tags separate presentation from business logic in that page content is created by page designers while the business logic's are captured in the form of custom tags. Now custom tags is not just for business logic but it can encapsulate other relatively complex functionality such as complex display, iteration, formatting and so on. Because custom tags encapsulate business logic, they are reusable and easier to maintain. In fact, in most cases, you will use custom tags that are created by someone else. Because custom tags hide complexity from page authors, it is easier to author pages. And there are many tools that support custom tags. Custom tags provide portable semantics.
17
08/01/2006
Pros
Custom tags can manipulate JSP contents while beans cannot Complex operations can be reduced to a significantly simpler form with custom tags than beans Custom tags require quite a bit of more work to set up than do beans
Cons
18
18
08/01/2006
Quick Introduction on Components that make up Custom tag architecture (in JSP 1.2)
19
Now let's me give you a quick introduction on 3 components that make up custom tag architecture.
19
08/01/2006
Defines tag's behavior Maps XML elements to tag handler class Uses tags
20
To use a custom tag in a JSP page, you must: * Declare the tag library containing the tag before the usage of any custom tags from that tag library * Use custom tags using custom tag syntax in a JSP page It is assumed that the tag library has been configured and deployed with individual Web application or globally for all Web applications running on the server.
20
08/01/2006
Write tag handlers Write Tag library descriptor (TLD) file Package tag handlers and TLD file into tag library (either unpacked or packed form) Write JSP pages that use tags Configure and deploy tag library along with JSP pages
21
The steps you follow in order to implement and deploy custom tags are relatively straight-forward. First, you write tag handlers. Under JSP 1.2 architecture, tag handlers are Java classes. Second, you write so called tag library descriptor, TLD file, in short. Third, you package a set of tag handlers and TLD file into what is called tag library in either unpacked or packed form. Then, you write JSP pages that use these tags. Then you deploy the tag library along with JSP pages. Now let's talk about 3 things here by using examples - tag handler, TLD file, and JSP pages.
21
08/01/2006
Implements interface
/WEB-INF/classes/<package-directory-structure>
22
First, tag handler class. Tag handler class implement Tag interface or Bodytag interface. If you are writing your tag handler from scratch, you will typically extend utility classes, TagSupport or BodyTagSupport classes, which are implementation of the interfaces with some built-in set up functions. As you will learn later on, you will choose to use either TagSupport or BodyTagSupport class depending on whether you need to manipulate or modify the body content. (By the way, by body content, I mean the JSP fragment that reside between starting tag and ending tag.) The tag handler classes are normal Java classes that reside under /WEBINF/classes. The classes should follow normal package directory structure.
22
08/01/2006
This is the simplest tag handler, ExampleTag.java, from Marty Hall's sample code you can download free. The package structure is ./ moreservlets.tags.ExampleTag.class.
23
08/01/2006
24
The ExampleTag class extends TagSupport class. It does include doStartTag() method in which you get JspWriter object which you get from pageContext object. Since the ExampleTag does not include nor manipulate body contents, it returns SKIP_BODY. (We will talk about this again later on.)
24
08/01/2006
Container knows which tag is associated with which tag handler class via this file Located
25
Once you create a set of tag handlers, which can be packaged into a single tag library, then you are ready to create a corresponding Tag Library Descriptor, TLD file. TLD file is an XML file that describes each tag with tag name, information on how body content should be handled, information on attributes, and full path of tag handler class. The web container knows which tag is associated with which tag handler class via this file. The TLD file can be located in any place such as the same directory of JSP pages, but normally you want to keep the TLD file under /WEB-INF directory. And this location is specified in the uri attribute of taglib directive. So let's take a look an example.
25
08/01/2006
This is the starting page of the msajsp-tags.tld file for all the tag handler examples from Marty Hall's sample code. Here in this example, this TLD file is based on JSP 1.1 as indicated by <jspversion> tag, which will be understood by JSP 1.2 container.
26
08/01/2006
This is continuation of the TLD file. In this page, you can see descriptions on two tag handlers, ExampleTag.class and SimplePrimeTag. Since both tag handlers do not include nor manipulate the body content, the <bodycontent> element is set to empty.
27
08/01/2006
28
We already talked about tag library. A tag library is a collection of related tags. It is a customary that you package related tags into a single tag library. A tag library is typically packaged as a jar file which contains TLD file along with tag handler classes and any related classes. When a tag library is packaged as a jar file, the TLD file should reside under META-INF directory and the tag handler classes should reside under classes directory.
28
08/01/2006
JSP page
? ?
Declare the tag library via taglib directive Use tags using custom tag syntax
29
To use a custom tag in a JSP page, you must: * Declare the tag library containing the tag before the usage of any custom tags from that tag library * Use custom tags using custom tag syntax in a JSP page It is assumed that the tag library has been configured and deployed with individual Web application or globally for all Web applications running on the server.
29
08/01/2006
<%@ taglib prefix="myprefix" uri=myuri %> prefix: identifies the tag library uri: uniquely identifies the tag library descriptor (TLD) directly or indirectly
30
You declare that a JSP page will use tags defined in a tag library by including a taglib directive in the page before any custom tag from that tag library is used. If you forget to include the taglib directive for a tag library in a JSP page, the JSP compiler will treat any invocation of a custom tag from that library as template data, and simply insert the text of the custom tag call into the response. The syntax of taglib directive is as following: <%@ taglib prefix="tt" uri=URI %> The prefix attribute defines the prefix that distinguishes tags defined by a given tag library from those provided by other tag libraries. The tagdir attribute specifies the location of tag files. And uri attribute uniquely identifies the tag library descriptor (TLD) either directly or indirectly.
30
08/01/2006
Custom tags have the syntax <prefix:tag attr1="value" ... attrN="value" /> or <prefix:tag attr1="value" ... attrN="value" > body </prefix:tag> where prefix distinguishes tags for a library, tag is the tag identifier, and attr1 ... attrN are attributes that modify the behavior of the tag.
31
08/01/2006
32
This is the SimpleExample.jsp page which uses the tags. Here it declares the tag library it wants to use first through <% taglib .. %> directive. The location of the TLD file is specified via uri attribute and the prefix is set to msajsp. In this example, the TLD file, msajsp-taglib.tld file, resides under /WEB-INF directory. As for the usage of example tag, it is used twice in this JSP page. Now let's see the result of accessing this JSP page in the following slide.
32
08/01/2006
33
This picture shows when the JSP page in the previous slide is accessed.
33
08/01/2006
34
OK. Since you get some big picture on how custom tags are working, let's see how you can build, configure and deploy tag library from a developer standpoint.
34
08/01/2006
Use the following source directory structure (as in J2EE 1.4 Tutorial's web/iterator directory)
<j2ee14tutorial-install>/j2eetutorial14/examples/web ? iterator build.xml (ant build file) src (dir where *.java files with proper package structure reside) web (dir) ? WEB-INF (dir) ? *.tld ? tags (dir - needed for JSP 2.0 tag files) ? *.jsp
35
First, let's see what would be a desired source directory structure. Of course, how you structure your development directory structure is dependent on individual taste, a recommended approach is to have separate the source tree from the build/deployment tree. And that is what Java WSDP tutorial code is structured and that is what we will use here as well. Java WSDP 1.2 has iterator custom tag and it comes with ant build.xml file. So for our custom tag development, we will have a source directory structure mentioned in the slide. That is, build.xml is in the top directory. And we will have src directory which contains *.java source files. And the web directory has WEB-INF subdirectory which will contain the TLD file and JSP files will be under web directory.
35
08/01/2006
Use the following build directory structure (as in J2EE 1.4 Tutorial's web/iterator directory)
<j2eetutorial14-install>/j2eetutorial14/examples/web ? iterator build (unpacked *.war file) dist (packed *.war file)
36
OK, now let's see what would be the build directory structure. We will have build directory and dist directory. The build directory will reflect the unpacked form of the custom tag library while the dist directory contains the *.jar file.
36
08/01/2006
Now we will spend the rest of the class talking about usage scenarios of custom tags. These are from Marty Hall's book. I decided to use his approach of explaining custom tags since he explains the custom tags by explaining the most simple one first and then gradually move up the ladder with more sophisticated usage of custom tags.
37
08/01/2006
? ? ? ? ?
Assigning attributes to tags Including tag body Optionally including tag body Manipulating tag body Including or manipulating tag body multiple times Using nested tags
38
So Marty deals with the usage scenarios of custom tags as mentioned in this slide. This set of usage scenarios are for both JSP 1.1 and JSP 1.2. He also explained newly introduced features of custom tags in JSP 1.2 in later chapter of his book, more Servlets and JSP.
38
08/01/2006
Bundling listeners with tag libraries Checking syntax with TagLibraryValidator Handling Exceptions with TryCatchFinally interface Looping without generating BodyContent
39
So this is the list of custom tag features and usage scenarios that are newly supported in JSP 1.2.
39
08/01/2006
So let's start with the most simple tag usage scenario and we will call this as a basic tag.
40
08/01/2006
A tag without attributes or body Extend TagSupport class All you have to do is to override doStartTag () method
doStartTag() method defines code that gets called at request time at the place where the element's start tag is found doStartTag() returns SKIP_BODY since the tag does not have a body
?
It instructs the container to ignore any body content between start and end tags
41
Basic tag is a tag that does not have attribute nor body content. Since we do not manipulate or modify body content, the tag handler simply extends the TagSupport class. Now in order to display whatever you want to display to the client, the only method you have to override is doStartTag(). We will spend some time later on tag handler methods later on but it is important for you to understand when these methods are invoked by the container. The doStartTag() method gets called at request time. That is, when a client accesses the JSP page (actually servlet code) which contains tags, what happens behind the scene is that when the opening tag is encountered by the container, the container invokes the doStartTag() method of the tag handler. Now in this example, the doStartTag() method just returns SKIP_BODY since, in this simplest usage scenario, the tag either does not contain the body content or want to ignore the body content. By returning SKIP_BODY, the tag handler basically instructs the container to ignore any body content.
41
08/01/2006
42
Next, let's move on to the next usage example. In this example, we will see how to assign attributes to tags.
42
08/01/2006
Provides a way to pass attribute/value pairs from JSP pages to custom tag handlers Custom tag handlers can use them in whatever business logic they have
43
Now why do you assign attributes to tags? The reason is rather simple, you want to provide a way to pass attribute/value pairs from the calling JSP pages to the tag handlers. And the tag handlers can use them in whatever business logic they have.
43
08/01/2006
Use of an attribute X in a JSP page results in a call to a method setX() in the tag handler class
44
Now let's see how attribute/value pairs specified in the JSP pages are passed to the tag handler. The mechanism is rather simple. Whenever attribute X/value pairs are encountered in the JSP page, the container invokes setX() in the tag handler class. What this means is that the tag handler must implement setX () method. For example, if there is attribute X=value1 in the opening tag element, the tag handler is expected to have setX(String value1) method.
44
08/01/2006
So let's see an example tag handler, SimplePrimeTag.java, that contains setX() method. This code is actually made of two tag handler classes. The first one is SimplePrimeTag.java and the other one is PrimeTag.java which extends SimplePrimeTag.java.
45
08/01/2006
46
This is SimplePrimeTag.java. Here we have a variable called len, which will be set by the setLength() method. The default value is set to 50. This example code basically computes a prime number using the length as as the length of the random number. Now some point, you might want to change the length of the random number from the calling JSP page.
46
08/01/2006
47
47
08/01/2006
Here the length can be set via setLength() method. So if the calling page contains length=60, this method will be called with length set to String value to 60.
48
08/01/2006
TLD
?
Attributes must be declared inside tag element by means of attribute sub-elements Attribute element has 5 sub-elements of its own
name (required) required (required) rtexprvalue (optional) type (optional) example (optional)
49
Now how does the container knows that the calling JSP page could pass attribute/value pairs to the tag handler? This is where TLD file comes into the picture. That is, the attribute must be declared inside the tag element by means of attribute sub-element. Now the attribute subelement has its own subelements as mentioned in the slide above that specify the characteristics of the attribute. The name element is a required subelement and specifies the name of the attribute. The required element is a required subelement and specifies whether it is a mandatory element or not. That is, if specified with true, the calling page must to have the attribute. Now rtexprvalue and type elements are optional and deserves a bit detailed explanation. So let's do that in the following slides.
49
08/01/2006
rtexprvalue (optional)
false if attribute value is a fixed string (default) specifies the class to which the value of the rtexprvalue should be typecast only legal when rtexprvalue is set to true
type (optional)
50
If rtexprvalue element is set to true, the attribute value be set as an expression. That is, the attribute value can be determined at request time. By request time, I mean the time the JSP page is being accessed by HTTP request. You can consider the request time as runtime equivalent. If it is set to false, the value is considered as String type and this is the default. The type element when specified specifies the type (in the form of a Java class) that the resulting value of the expression that is specified with rtexprvalue is to be typecasted. So the type element is legal only when rtexprvalue is set to true.
50
08/01/2006
51
So let's take a look at an example of TLD file. The first page looks the same.
51
08/01/2006
52
Here the PrimeTag tag handler accepts an attribute called length. And the required element is set to false, which means this attribute is optional.
52
08/01/2006
This slide shows the calling JSP page. Here again, the tag library is declared with taglib directive first. Then the tag is called 4 times, three of which has length attribute set to 20, 40, 60, and the last one with a default. Please note that the values 20, 40, 60 are passed as String type instead of Integer type since rtexprvalue and type is not set in the TLD file. And that is why the setLength() method has to change the String type to Integer type.
53
08/01/2006
54
54
08/01/2006
55
So far in the past two use scenarios, we have not dealt with body content. Now let's move to the next level. This time, we will see how body content can be included (or sometimes called evaluated).
55
08/01/2006
<prefix:tagname>body</prefix:tagname> Body content contains typical JSP constructs JSP constructs inside of body content get translated at page translation time In this usage pattern, we are just including body content without any modification
56
By the way, by body content, I mean the JSP fragment between the starting tag and ending tag. For example, if you have <prefix:tagname>body</prefix:tagname> in the calling JSP page, the body content here is body. The body content contains typical JSP constructs. And these JSP constructs inside the body content get translated at page translation time, that is, at the time, the JSP page gets translated into servlet code, which typically happens when JSP pages are loaded into the system (as opposed to request time at which actual tag handler code is being invoked.) In this use scenario, we are just including the body content without any manipulation or modification.
56
08/01/2006
doStartTag() method should return EVAL_BODY_INCLUDE doEndTag() gets called after body is evaluated
return EVAL_PAGE for continued processing return SKIP_PAGE for aborting processing rest of the page
57
In this use case scenario, the doStarttag() method should return EVAL_BODY_INCLUDE. Otherwise, the container will skip evaluating the content. Now in addition to doStartTag() method that gets invoked by the container when the starting tag is encountered, you also want to override doEndTag() method after the body is evaluated. Here you return EVAL_PAGE for continued processing or SKIP_PAGE for aborting processing the rest of the JSP page.
57
08/01/2006
58
So let's take a look at the tag handler example. This is HeadingTag.java from the Marty Hall's sample code.
58
08/01/2006
Please note that we are still extending TagSupport since we are not manipulating or modifying the body content.
59
08/01/2006
60
This is doStartTag() method. Here we spit out various HTML tags that create starting part of table and then return EVAL_BODY_INCLUDE, which instructs the container to include the body content after that.
60
08/01/2006
61
After body content is written, the ending part of table HTML tags are written out via doEndTag() method. Since doEndTag() method returns EVAL_PAGE, the container continues processing with rest of the JSP page.
61
08/01/2006
TLD
?
<bodycontent>JSP</bodycontent>
62
The bodycontent element now must contain the value JSP instead of empty.
62
08/01/2006
Example: TLD
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE ...> <taglib> ... <tag> <name>heading</name> <tagclass>moreservlets.tags.HeadingTag</tagclass> <bodycontent>JSP</bodycontent> <info>Outputs a 1-cell table used as a heading.</info> <attribute> <name>bgColor</name> <required>true</required> <!-- bgColor is required --> </attribute> <attribute> <name>color</name> <required>false</required> </attribute> ...
63
63
08/01/2006
This is the calling JSP page. Here we call the heading tag with multiple times with different body content.
64
08/01/2006
65
65
08/01/2006
66
66
08/01/2006
67
Now let's move on to the next usage scenario - we want include body content depending on the value of the form input parameter.
67
08/01/2006
Decision of usage of body content is decided at request time Body content is not modified
68
So in this usage scenario, decision of including body content is decided at request time (runtime) instead of translation time. Also in this usage scenario, we are not modifying the body content.
68
08/01/2006
Typecast the return of getRequest() to HttpServletRequest since getRequest() returns ServletRequest type
69
So in this usage scenario, the tag hander method returns either EVAL_BODY_INCLUDE or SKIP_BODY depending on the value of the some request time expression or some business logic processing. Now how do you get hold of the HttpServletRequest object? You call getRequest() method of pageContext of TagSupport class. Now you would need to typecast the result of getRequest() method to HttpServletRequest since getRequest() returns ServletRequest type.
69
08/01/2006
70
70
08/01/2006
71
So here the doStartTag() method returns either EVAL_BODY_INCLUDE or SKIP_BODY depending on whether there is a input parameter debug is set to true.
71
08/01/2006
Example: TLD
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE ...> <taglib> ... <tag> <name>debug</name> <tagclass>moreservlets.tags.DebugTag</tagclass> <bodycontent>JSP</bodycontent> <info>Includes body only if debug param is set.</info> </tag> ...
72
This is TLD. As is the case of previous example, the value of <bodycontent> is set to JSP.
72
08/01/2006
73
08/01/2006
74
Here there is body content between starting debug tag and end tag. This bodycontent will be displayed only when there is debug input parameter set with value true at request time.
74
08/01/2006
75
This is the case where the client does not send any debug input parameter. So the bodycontent is not displayed.
75
08/01/2006
76
This is the case where the client is calling the JSP page setting the debug input parameter set to true. This time, the body content is displayed.
76
08/01/2006
77
Now let's move on to the next usage scenario. Here we are going to see how the body content can be manipulated (modified).
77
08/01/2006
Tag handler class should extend BodyTagSupport class BodyTagSupport class has 2 convenience methods
return SKIP_BODY if no further body processing is needed return EVAL_BODY_TAG (JSP 1.1) or EVAL_BODY_AGAIN (JSP 1.2) if the body content needs to be evaluated and handled again
In this usage scenario in which the body content needs to be manipualted and/or modified, the tag handler should extend BodyTagSupport class. The BodyTagSupport class provides 2 more methods - doAfterBody() and getBodyContent() method. Normally the doAfterBody() method returns SKIP_BODY to indicate that the body does not need to reevaluated.
78
08/01/2006
BodyContent class
?
? ?
An encapsulation of the evaluation of the body A subclass of JspWriter BodyContent class has 3 methods
getEnclosingWriter(): returns JspWriter getReader(): returns a Reader that can read tag body getString(): returns a String containing entire tag body
79
The BodyContent class is an encapsulation of the body. It is a subclass of JspWriter. The BodyContent class has three methods.
79
08/01/2006
This is the first page of the FilterTag.java tag handler code. Skip to the next slide.
80
08/01/2006
Here the FilterTag handler extends BodyTagSupport class. And the doAfterBody() method gets called by the container after the body content has been evaluated. Now the tag handler can access the evaluated body content in the form of BodyContent object by calling getBodyContent() method. And the body content can be returned in the form of String object via getString() method of the BodyContent object.
81
08/01/2006
Example: TLD
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE ...> <taglib> ... <tag> <name>filter</name> <tagclass>moreservlets.tags.FilterTag</tagclass> <bodycontent>JSP</bodycontent> <info>Replaces HTML-specific characters in body.</info> </tag> ...
82
Here the TLD file looks the same as in the cases of previous examples.
82
08/01/2006
83
83
08/01/2006
84
84
08/01/2006
To be added
85
85
08/01/2006
86
The next usage scenario is to include or manipulate the body multiple times.
86
08/01/2006
Tag handler class should extend BodyTagSupport class doAfterBody() now returns EVAL_BODY_TAG (EVAL_BODY_AGAIN in JSP 1.2)
87
The tag handler extend BodyTagSupport class. And the doAfterBody() method this time returns EVAL_BODY_TAG (under JSP 1.1) or EVAL_BODY_AGAIN (under JSP 1.2).
87
08/01/2006
88
88
08/01/2006
89
89
08/01/2006
The doAfterBody() keeps evaluating the body content until number of repetition is satisfied.
90
08/01/2006
Example: TLD
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE ...> <taglib> ... <tag> <name>repeat</name> <tagclass>moreservlets.tags.RepeatTag</tagclass> <bodycontent>JSP</bodycontent> <info>Repeats body the specified number of times.</info> <attribute> <name>reps</name> <required>true</required> <!-- rtexprvalue indicates whether attribute can be a JSP expression. --> <rtexprvalue>true</rtexprvalue> </attribute> </tag> ...
91
This the TLD file. Here the characteristics of reps attribute has been defined.
91
08/01/2006
92
92
08/01/2006
93
Here the body content which itself is a custom tag will be evaluated by the value of repeats input parameter.
93
08/01/2006
To be added
94
Here the value of repeats is set to 9 and the prime number is repeated 9 times.
94
08/01/2006
More detailed information on How to declare tag library using taglib directive
95
Now you should be relatively comfortable with taglib directive in the JSP page. Here let's go over the syntax of the taglib directive in a bit more detail.
95
08/01/2006
<%@ taglib prefix="tlt" uri="/tlt"%> Mapping of the logical name to path to the TLD file has to be defined in web.xml
<jsp-config> <taglib> <taglib-uri>/tlt</taglib-uri> <taglib-location>/WEB-INF/iterator.tld</taglib-location> </taglib> </jsp-config>
96
The uri attribute refers to a URI that uniquely identifies the tag library descriptor (TLD), a document that describes the tag library (See Tag Library Descriptors). Tag library descriptor file names must have the extension .tld. TLD files are stored in the WEB-INF directory or subdirectory of the WAR file or in the META-INF/ directory or subdirectory of a tag library packaged in a JAR. You can reference a TLD directly or indirectly. The following taglib directive directly references a TLD filename: <%@ taglib prefix="tlt" uri="/WEB-INF/iterator.tld"%> This taglib directive uses a short logical name to indirectly reference the TLD: <%@ taglib prefix="tlt" uri="/tlt"%>
96
08/01/2006
97
You can also reference a TLD in a taglib directive with an absolute URI. For example, the absolute URIs for the JSTL library are: * Core: http://java.sun.com/jsp/jstl/core * XML: http://java.sun.com/jsp/jstl/xml * Internationalization: http://java.sun.com/jsp/jstl/fmt * SQL: http://java.sun.com/jsp/jstl/sql * Functions: http://java.sun.com/jsp/jstl/functions When you reference a tag library with an absolute URI that exactly matches the URI declared in the taglib element of the TLD (see Tag Library Descriptors), you do not have to add the taglib element to web.xml; the JSP container automatically locates the TLD inside the JSTL library implementation.
97
08/01/2006
More detailed information on How to Configure tag library with Web application
98
Let's see how tag library can be configured with Web application.
98
08/01/2006
In unpacked form
tag handler classes are packaged under the /WEB-INF/classes/ directory *.tld file under the /WEB-INF/ directory *.jar file is in the /WEB-INF/lib/ directory
99
In addition to declaring the tag library, you also need to make the tag library implementation available to the Web application. There are several ways to do this. Tag library implementations can be included in a WAR in an unpacked format: tag files are packaged in the /WEB-INF/tag/ directory and tag handler classes are packaged in the /WEB-INF/classes/ directory of the WAR. Tag libraries already packaged into a JAR file are included in the /WEB-INF/lib/ directory of the WAR.
99
08/01/2006
100
Here in this segment of the presentation, we will look into internal mechanisms of custom tags. Much of the information is something that has been already talked about.
100
08/01/2006
JSP translator locates the TLD file via uri attribute of taglib directive
The TLD file describes the binding between an action (tag handler) and a Tag
101
Now when JSP page is loaded into the web container, the JSP translator translates the JSP page into the servlet code. Now when the translator encounters the taglib directive, it knows where to find the TLD file via uri attribute. As we know now, the TLD file describes the binding between an action (tag handler) and a tag. Now tags in a JSP page results in the appropriate servlet code which contains the tag handler.
101
08/01/2006
102
This slides shows the Tag interface's methods on the left side and how these methods are invoked in sequence by the container on the right side of the slide. Tag handler methods defined by the Tag and BodyTag interfaces are called by the JSP page's servlet at various points during the evaluation of the tag. When the start element of a custom tag is encountered, the JSP page's servlet calls methods to initialize the appropriate handler and then invokes the handler's doStartTag method. When the end element of a custom tag is encountered, the handler's doEndTag method is invoked for all but simple tags. Additional methods are invoked in between when a tag handler needs to manipulate the body of the tag.
102
08/01/2006
103
This slide shows the TagSupport class that implements Tag interface.
103
08/01/2006
doStartTag()
Processes starting element (semantics) Returns EVAL_BODY_INCLUDE to process body Returns SKIP_BODY to skip body
doEndTag()
Completes element processing (flush) Returns EVAL_PAGE to continue processing Returns SKIP_PAGE to terminate processing
104
08/01/2006
Release( Release())
Release( Release())
Stop
Continue Continue
105
This is the calling sequence from the container. The container obtains the tag handler and invokes setPageContext() and setParent() methods of Tag interface. It then calls methods for setting attributes (if attribute elements are defined in the TLD file). Then it calls doStartTag() method. If the doStartTag() method returns EVAL_BODY_INCLUDE, the container wll evaluate the body content. Then it calls doEndTag() method. And depending the return value, it will continue processing of the page or stop.
105
08/01/2006
? ? ?
JSP technology creates (or reuses) a Tag class instance associated with the element in the page source Class is named in the TLD Container calls setPageContext() and setParent() parent (possibly null, unless nested) PageContext provides access to: request, response, out, session, page and attributes Container calls setX() methods for attributes specified Container calls doStartTag() and doEndTag() Container invokes release() to free Tag instance for reuse
106
106
08/01/2006
107
The Tag interface defines the basic protocol between a tag handler and a JSP page's servlet. It defines the life cycle and the methods to be invoked when the start and end tags are encountered. The JSP page's servlet invokes the setPageContext, setParent, and attribute setting methods before calling doStartTag. The JSP page's servlet also guarantees that release will be invoked on the tag handler before the end of the page. Here is a typical tag handler method invocation sequence: ATag t = new ATag(); t.setPageContext(...); t.setParent(...); t.setAttribute1(value1); t.setAttribute2(value2); t.doStartTag(); t.doEndTag(); t.release();
107
08/01/2006
The output of the page is written into a JSPWriter provided by the page implementation This is flushed to the output stream of the ServletResponse. Output is buffered in the JSPWriter by default. Tags output to nested JSPWriter streams.
108
108
08/01/2006
BodyTag, BodyTagSupport
For manipulating or evaluating body multiple times,
109
The BodyTag interface extends Tag by defining additional methods that let a tag handler access its body. The interface provides three new methods: * setBodyContent--Creates body content and adds to the tag handler * doInitBody--Called before evaluation of the tag body * doAfterBody--Called after evaluation of the tag body
109
08/01/2006
110
A typical invocation sequence is: t.doStartTag(); out = pageContext.pushBody(); t.setBodyContent(out); // perform any initialization needed after body content is set t.doInitBody(); t.doAfterBody(); // while doAfterBody returns EVAL_BODY_AGAIN we // iterate body evaluation ... t.doAfterBody(); t.doEndTag(); out = pageContext.popBody(); t.release();
110
08/01/2006
BodyContent
111
111
08/01/2006
? ? ?
JSP technology creates a nested stream (BodyContent) to contain the body text The BodyContent is passed to the BodyTag via setBodyContent() doStartBody() is invoked doInitBody() is invoked The body text is evaluated into the BodyContent
112
If the tag handler needs to manipulate the body, the tag handler must implement BodyTag (or be derived from BodyTagSupport). When a tag handler implements the BodyTag interface, it must implement the doInitBody and the doAfterBody methods. These methods manipulate body content passed to the tag handler by the JSP page's servlet. Body content supports several methods to read and write its contents. A tag handler can use the body content's getString or getReader methods to extract information from the body, and the writeOut(out) method to write the body contents to an out stream. The writer supplied to the writeOut method is obtained using the tag handler's getPreviousOut method. This method is used to ensure that a tag handler's results are available to an enclosing tag handler. If the body of the tag needs to be evaluated, the doStartTag method needs to return EVAL_BODY_BUFFERED; otherwise, it should return SKIP_BODY.
112
08/01/2006
doAfterBody() is invoked:
It must process the content of the nested stream and write to nesting stream (out) It can cause the page to be re-evaluated (to support iterative tags) by returning EVAL_BODY_TAG
Invoke doEndTag().
113
The doAfterBody method is called after the body content is evaluated. doAfterBody must return an indication of whether to continue evaluating the body. Thus, if the body should be evaluated again, as would be the case if you were implementing an iteration tag, doAfterBody should return EVAL_BODY_AGAIN; otherwise, doAfterBody should return SKIP_BODY.
113
08/01/2006
doStartTag():
Same as Tag semantic, except:
Returns EVAL_BODY_TAG to process body
doBodyInit():
Prepare to process body
doAfterBody() :
Handle processed body in BodyContent Return EVAL_BODY_TAG to reprocess
DoEndTag() :
Same as Tag Semantics
114
114
08/01/2006
Passion!
115
115