Head first Servlets and Jsp Chapter 10 Short Notes
May 25, 2011 at 9:36 am Leave a comment
Note: Feel free to copy the post, modify and comment
Custom Taglibraries
Classic custom tag event model
Using PageConext API to access implicit variables
Accessing Parent Tag
semantics of Tag File model
1. Tag Files
Alternative and better way to implement <jsp:include> or is to use tag file.
This helps including the reusable components using just a tag and not using standard actions.
Example:
1. Create a Header.jsp and rename it to Header.tag
2. Place the tag file under web-inf directory and under tags directory
3. Now Use the tag include in the Main.jsp like below
<%@ taglib prefix=”myTags” tagDir=”/WEB-INF/tags” %>
<myTags:Header/> — This includes the re-usable content dynamically
But how do we pass the parameters ? remember <jsp:param> element we used while using and ?
Here we use attrubute directly,
<myTags:Header subTitle=”This is the subtitle given to page dynamically” />
In Header.tag, use the following to retrieve the value passed by above statement
<em>${subTitle}</em>
* PS: Once the tag is closed, the tag attribute goes out of scope
* In the approach one good thing is the attribute that is passed has lesser scope and restricted to only the tag file associated,
whereas in the earlier approach of <jsp:include>, a new request parameter is created which is exposed to all jsps and servlets that interact with the page.
Using Attribute Directive in Tag file:
When you want to force the attribute usage of the tag, we can do that by using attribute directive
In Header.tag
<%@ attribute name=”subTitle” required=”true” rtexprvalue=”true”%>
<em>${subTitle}</em>
in Main.jsp
<%@ taglib prefix=”myTags” tagDir=”/WEB-INF/tags” %>
<myTags:Header subTitle=”This is the subtitle given to page dynamically”/>
doBody> :
In case if the attribute value is too long.. like a paragraph, then use the tag in the tag file and do not use attrubute directive
In Header.tag
<em><jsp:doBody/></em>
in Main.jsp
<%@ taglib prefix=”myTags” tagDir=”/WEB-INF/tags” %>
<myTags:Header>
This is the subtitle given to page dynamically,This is the subtitle given to page dynamically,This is the subtitle given to page dynamically
<!–myTags:Header>
How to force the body-content rule then ?
Use the tag directive !
In Header.tag
<%@ attribute name=”fontColor” required=”true”%>
<%@ tag body-content=”tagdependant”%>
in Main.jsp
<%@ taglib prefix=”myTags” tagDir=”/WEB-INF/tags” %>
<myTags:Header fontColor=”blue”>
This is the subtitle given to page dynamically,This is the subtitle given to page dynamically,This is the subtitle given to page dynamically
</myTags:Header>
body-content,
tagdependant – Scriptlets, EL and tags are not evaluated
empty – nothing should be there in body
scriptless – only scripts are not evaluated
Where does container search for tag files:
1. Directly inside WEB-INF/tags
2. Inside a subdirectory of WEB-INF/tags
3. Inside META-INF/tags directory inside a jar file thats inside WEB-INF/lib
4. Inside subdirectory of META-INF/tags directory inside a jar file thats inside WEB-INF/lib
5. If the tag is deployed inside a jar, there must be a tld for the tag file
* The tag file have access to request and response
* EL works
* And we have access to JspContext instead of ServletContext
* We can combine tld and tag files to be considered by container as a same library. Use tag reference inside TLD
Referring tag file inside a tld
<tag-file>
<name>Header</name>
<path>/META-INF/tags/Header.tag</path>
</tag-file>
2. Simple Tag Handler:
1. Write a class that extends SimpleTagSupport
2. Override the doTag() method
3. Create a TLD for the tag
4. Deploy the tag handler and the TLD
5. Write the jsp that uses the TLD
Simple Tag API Hierarchy:
JspTag (Interface) -> SimpleTag (Interface) -> SimpleTagSupport(Class)
Life Cycle of Simple Tag Handler:
1. Load the class SimpleHandler
2. Instantiate class object of your class (tag handler)
3. Call setJspContext(JspContext) – gives the handler a reference to PageContext (subclass of JspContext)
4. If the tag is nested, then call the setParent(JspTag) method (nested tags can communicate with parent tags)
5. If the tag has setters, then call them (remember java Bean standard ?)
6. If the tag can have body, then call setJspBody() method
7. Then finally the overrided method doTag()
What if the tag body uses an expression ?
in public void doTag() {
getJspContext().setAttribute(“message”,”this is a message from class to the jsp”);
getJspBody().invoke (null); // sets attribute and invokes the body
}
<myTags:simple>
Message is: ${message}
</myTags:simple>
Or
Can also loop the body call with for loop and print an array of messages. But every time remember to call invoke()
What about attributed of the Tag ?
Set the attribute value in bean setter method and later can also be used in body evaluation !
SkipPageException:
throw this exception if you feel some value is not supplied properly.
* It shows everything upto the point of exception is thrown !
* And when u throw this exception in an included page, then main page functions or continues after the exception in included page
* If you wish to specify attribute type as non primitive, then use <rtrexprvalue>true</rtrextrvalue>
If the body is declared to have content and if we do not give body then setJspBody() will not be called
JspFragment has 2 methods -> invoke() and getJspContext()
3. Classic Tag Handler:
It has 5 interfaces and 3 support classes. We would always be extending the support classes for tlds.
* Create the TLD v.similar to the simple tag handler
* Create the tag handler class to extend TagSupport
* Override the doStartTag() method which throws JspException and not IOException. Hence need to handle IO errors.
Return type is int which tells the container what to do next.
* return int to instruct the container. Ex. SKIP_BODY
* Override the doEndTag() method and return EVAL_PAGE (to evaluate rest of the page)
When the tag has Body !
* In the doStartTag() method, return EVAL_BODY_INCLUDE to evaluate the body
Classic tags lifecycle:
* Container loads the ClassicTagHandler.class
* Instantiate the class
* Call the setPageContext() method -> This gives handle reference to Context object
* If tag is nested, then call setParent(Tag) method
* If tag has attributes, then call the attribute setters
* Call doStartTag() method
* If the tag tld does not say empty body and if the body is not empty and if doStartTag() returns EVAL_BODY_INCLUDE, body is evaluated
* If body is evaluated, the calls doAfterBody() method
* Call doEndTag() method
Possible Return values:
doStartTag()
SKIP_BODY
EVAL_BODY_INCLUDE
doAfterBody()
SKIP_BODY
EVAL_BODY_AGAIN – only constant declared in IterationTag interface
doEndTag()
SKIP_PAGE
EVAL_PAGE
Example:-
int movieCounter=0;
String movies[] = new String []{“Spider man”,”Amelie”};
public int doAfterBody() throws JspException {
if (moieCounter < movies.length) {
pageContext.setAttribute(“movie”,movies[movieCounter]);
movieCounter++;
return EVAL_BODY_AGAIN;
}else {
return SKIP_BODY;
}
………..
}
JSP that invokes;
<%@ taglib prefix=”my” uri=”ClassicTagsTest” %>
<html><body>
<my:iterateMovies>
${movie}
</my:iterateMovies>
</body></html>
This calls the movie to get printer 2 times
Default return values of the methods:
doStartTag() -> SKIP_BODY
doAfterBody() -> SKIP_BODY -> body evaluated only once !
doEndTag() -> EVAL_PAGE
Dynamic Attributes:
To handle any non-mandatory attributes, implement DynamicAttributes interface and use a hashmap to set the key(attribute name) and value in it.
This can later by used within the doTag() method
In the tld file we need entry like below.
<attribute>
<dynamic-attributes>true</dynamic-attributes> // this says any number of dynamic attributes are allowed
</attribute>
Entry filed under: Education, programming, web. Tags: .
Trackback this post | Subscribe to the comments via RSS Feed