<document>
<header>
<product>resin</product>
<version>Resin 3.0</version>
<type>tutorial</type>
<title>Tag Reuse</title>
<description>
<p>Tag libraries must follow important conventions for initializing
tag fields.  The JSP specification lets a JSP container, like Resin,
reuse tag handler instances for efficiency and performance.
Because this optimization restricts how tags can use fields,
even experienced developers will benefit from this tutorial.
</p>

</description>
 <tutorial-startpage>index.jsp</tutorial-startpage>
</header>

<body>
<summary/>
<s1 title="Files in this tutorial">
<deftable>
<tr><td><viewfile-link file="index.jsp"/>
    </td><td>The jsp page that uses the tags
</td></tr><tr><td><viewfile-link file="WEB-INF/message.tld"/>
    </td><td>The taglib descriptor
</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/taglib/MessageTag.java"/>
    </td><td>The class corresponding to &lt;msg:message&gt;
</td></tr><tr><td><viewfile-link file="WEB-INF/classes/example/taglib/MessageAddTag.java"/>
    </td><td>The class corresponding to &lt;msg:add&gt;, used within the body of &lt;msg:message&gt;
</td></tr></deftable>
</s1>

<s1 title="Resin reuses tag handler instances">
<glossary title="tag handler instance">
An instance of the class that is associated with an xml-style custom JSP tag.
</glossary>

<p>Resin aggressively reuses tag handler instances. Any tag with the same
set of attributes is a candidate for reuse.  For example, a tag
&lt;msg:message&gt; with an attribute title="Test-1" may share the same
tag handler instance as a &lt;msg:message&gt; with an attribute title="Test-2".
</p>

<p>This ability for Resin to reuse instances of the tag handler is
described in the JSP specification.</p>
<blockquote title="From the JSP 2.0 specification">
"The JSP container may reuse classic tag handler instances for multiple
occurrences of the corresponding custom action, in the same page or in
different pages, but only if the same set of attributes are used for
all occurrences."
</blockquote>
<p>In this tutorial, the &lt;msg:message&gt; prints its id to show
the instance of the object that is created.</p>

<example title="index.jsp">
  &lt;msg:message title="Test Message"&gt;
    &lt;msg:add text="Hello"/&gt;
    &lt;msg:add text="World"/&gt;
  &lt;/msg:message&gt;

  &lt;msg:message&gt;
    &lt;msg:add text="Hello Again"/&gt;
    &lt;msg:add text="World"/&gt;
  &lt;/msg:message&gt;

  &lt;msg:message title="Test Message"&gt;
    &lt;msg:add text="Goodbye"/&gt;
    &lt;msg:add text="World"/&gt;
  &lt;/msg:message&gt;
</example>

<p>The instance created for the first &lt;msg:message&gt; tag,
<code>MessageTag@10000</code>, is reused for the third &lt;msg:message&gt; tag.
Resin can reuse the tag handler instance the attributes set for the
first and third objects are the same: {title}.  The second tag uses a
new instance, <code>MessageTag@100000</code>, because it has
a different attribute set: {text}.</p>

<results>
 +--------------------------------------------+
 | instance: example.taglib.MessageTag@10000  |
 |--------------------------------------------|
 | Test Message                               |
 |--------------------------------------------|
 | Hello                                      |
 | World                                      |
 +--------------------------------------------+

 +---------------------------------------------+
 | instance: example.taglib.MessageTag@29000   |
 |---------------------------------------------|
 | default title                               |
 |---------------------------------------------|
 | Hello Again                                 |
 | World                                       |
 +---------------------------------------------+

 +--------------------------------------------+
 | instance: example.taglib.MessageTag@10000  |
 |--------------------------------------------|
 | Test Message                               |
 |--------------------------------------------|
 | Goodbye                                    |
 | World                                      |
 +--------------------------------------------+
</results>

<s2 title="Lifecycle">

<ol>
<li>Handle the first &lt;msg:message&gt; tag:
<ol>
<li>Instantiate the tag handler instance, <code>MessageTag@9681e0</code>
</li><li>Set the attributes, <code>setTitle("Test Message")</code>
</li><li>Call the <code>doStartTag</code> method.
</li><li>Process the contents
</li><li>Call the <code>doEndTag</code> method.
</li></ol>
</li><li>Handle the second &lt;msg:message&gt; tag
</li><li>Handle the third &lt;msg:message&gt; tag:
<ol>
<li>Set any attribute values which differ from the first tag.
In this case, all the values are the same the same, so Resin doesn't
call any setter.
</li><li>Call the <code>doStartTag</code> method.
</li><li>Process the contents
</li><li>Call the <code>doEndTag</code> method.
</li></ol>
</li><li>At the end of the page, clean up the tag handler instances:
<ol>
<li>Call <code>release()</code> for the first instance, <code>MessageTag@10000</code>
</li><li>Call <code>release()</code> for the second instance, <code>MessageTag@29000</code>
</li><li>Call <code>release()</code> for the &lt;msg:add&gt; instances.
</li></ol>
</li></ol>

<p>Resin <b>does not</b> call <code>release()</code> between the first and
third &lt;msg:message&gt; tags.  It only calls <code>release()</code> 
at the end of the page.  This behavior follows the JSP spec, but
surprises some tag library developers.</p>

</s2>

</s1>

<s1 title="Treat attributes as read-only"> 

<p>Since tag handler instances are reused, the fields
corresponding to tag attributes must be read-only.  Only
Resin may call the attribute setters; the tag's code must never
modify the corresponding fields.</p>

<example title="WEB-INF/classes/example/taglib/MessageTag.java" language="java">
  /* tag attributes
   *
   * member variables to store the value of tag attributes are treated
   * as read-only.  Resin will set the values using setXXXX() based on
   * the values passed as attributes to the tag, and the code in the
   * class will never change the values.
   */
  private String _attrTitle;
  
  public void setTitle(String title) 
  {
    // this is the only place where _attrTitle is ever set
    _attrTitle = title;
  }
</example>
</s1>

<s1 title="Initializing member variables in doStartTag">

<p>Tags must initialize internal variables in the first action method called,
for example <code>doStartTag</code>. Because of tag instance reuse,
the tag must assume that all internal variables are unset, i.e. set to
unknown, bogus values.  The initialization code must initialize those
values.</p>

<p>Often in a tag it is necessary to have additional member variables
other than those that hold the value of tag attributes.  In this case,
the only safe way to initialize the variables is in the
<code>doStartTag()</code>, before anything else is done.</p>

<p>Because the tag instance will be reused, you cannot simply initialize
the tag in the constructor.  And, because the <code>release()</code> method
is only called at the end of the page, the tag cannot call initialization
code in the <code>release()</code> method.
There may be many calls to <code>doStartTag()</code> and
<code>doEndTag()</code> before <code>release()</code> is called.</p>

<p>In this tutorial, an <code>init()</code> method is used for
initialization of these internal member variables, and a call to
<code>init()</code> is the first thing done in
<code>doStartTag()</code>.

<example title="WEB-INF/classes/example/taglib/MessageTag.java" language="java">
  String _title;
  <b>StringBuffer _msg;</b>

  <b>void init()</b>
  {
    _title = _attrTitle;
    if (_title == null)
      _title = "Default Title";

    <b>_msg = new StringBuffer();</b>

  }

  public int doStartTag() 
    throws JspException 
  {
    // initialize internal member variables
    <b>init();</b>

    return EVAL_BODY_BUFFERED;
  }
</example>

</p></s1>

<s1 title="Initializing member variables in doEndTag">

<p>Tag libraries need to initialize their variables in the first
tag method called.  Most often, this will be in <code>doStartTag</code>,
but some tags only implement <code>doEndTag</code>.  Tags which
only have a <code>doEndTag</code> may initialize in <code>doEndTag</code>.</p>

<p>Because Resin can analyze which methods are implemented by a tag and
generated better code for the default <code>TagSupport</code> methods,
it's a good idea to only implement those tag methods which are absolutely
necessary.</p>

</s1>

<s1 title="Default values for attributes">

<p>If an attribute of a tag is not used, the corresponding setter will
not be called.  In many causes you will want to provide a default
value for the attribute, and then the default value will be dependent
on other member variables.  Even though it is not always necessary,
the best way to set a default value for a missing attribute is the
same way the internal member variables are set in the previous
example.</p>

<example title="WEB-INF/classes/example/taglib/MessageTag.java" language="java">
  // read-only attribute field
  private String _attrTitle;

  // tag field initialized by init()
  private String _title;
  
  public void setTitle(String title) 
  {
    _attrTitle = title;
  }

  public int doStartTag() 
    throws JspException 
  {
    // initialize internal member variables
    <b>init();</b>

    ... // main tag processing

    return EVAL_BODY_BUFFERED;
  }

  protected void init()
  {
    <b>_title = _attrTitle;
    if (_title == null)
      _title = "Default Title";</b>

    _msg = new StringBuffer();
  }
</example>
</s1>


</body>
</document>
