I was also confused initially but finally I found the solution!
1'st let me explain the process.
1)When doStartTag() returns EVAL_BODY_BUFFERED , setBodyContent() is called.At this point, container passes an instance of BodyContent to the tag handler class.
(Point to be noted here is that when this method completes, we just have a new instance of bodyContent. it still does not have evaluated body
string)
2)Then, doInitBody() is called. At this time, still the bodyContent does not contain the evaluated body string(i.e. bodyContent.getString() would return empty String).
This method can be used to initialize or add to the bodyContent( which is again a subclass of JspWriter.)
3)Then the body is evaluated by the container and appended to the bodyContent instance.
4)Then, doAfterBody() is called, which can perform post-evaluation of the bodyContent. This method can return SKIP_BODY or EVAL_BODY_AGAIN . In latter case, the body will be evaluated again, and appended to the bodyContent.
5)Finally doEndTag() is called.
Here is my version:
*******************************************************
package tag;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.*;
public class ClassicBodyTagHandler extends BodyTagSupport
{
JspWriter out;
int counter;
public int doStartTag() throws JspException
{
//out = pageContext.getOut(); // this will also work!!
counter=0;
return EVAL_BODY_BUFFERED;
}
public void doInitBody() throws JspException
{
try{
bodyContent.print("ADD");
}
catch(IOException ex){
throw new JspException("<BR> IOException = "+ex.toString());
}
}
public int doAfterBody() throws JspException
{
try
{
out=bodyContent.getEnclosingWriter();
StringBuffer text=new StringBuffer(bodyContent.getString());
out.println("<BR>\t the initial bodyContent :"+text);
text.reverse();
out.println("<BR>\t the modified bodyContent :"+text);
counter++;
}
catch(IOException ex)
{
throw new JspException("IOException = "+ex.toString());
}
if(counter==2)
return SKIP_BODY;
else
return EVAL_BODY_AGAIN;
}
public int doEndTag() throws JspException
{
return EVAL_PAGE;
}
}
Output:
the initial bodyContent :ADDI have a Body
the modified bodyContent :ydoB a evah IDDA
the initial bodyContent :ADDI have a BodyI have a Body
the modified bodyContent :ydoB a evah IydoB a evah IDDA
Here you can see that ADD is prefixed to the tag body which I appended in doInitBody().
Also,when counter is 1, body is evaluated again and appended to existing bodyContent instance.
I hope this will answer your question that why we can't access bodyContent in doInitBody(). When doInitBody is called bodyContent is empty i.e body is not yet evaluated.
I have referred SCWCD Study Kit by Manning and the online links given earlier.. but the things were clear only when I tried different experiments.
Regards,
Amit
*****************************************************