<overview>
This proposal introduces a new kind of JSP tag interface in addition to the
standard set (Tag, BodyTag and IterationTag) which allows more flexible JSP
flow control and more lightweight communication between JSP custom tags. It
allows a tag to call the body of another "runnable" tag explicitly to
achieve more efficient flow control in situations such as implementing
switch statements, exception handling or other looped processing
efficiently.
</overview>

<description>
The proposal adds 2 new interfaces and one new abstract base class to the
javax.servlet.jsp.tagext package.

    RunnableTag
    RunnableTagSupport
    TagRunner

I've attached sample implementations of the above to this mail.

The basic idea is that RunnableTag is a new kind of tag where the body is
not generated by default; the code required to output the body is generated
inside a function in the servlet which can be called via the RunnableTag
interface.

It is then the responsibility of an outer tag to generate the body whenever
it decides. An IterationTag / BodyTag loops through its body until it
decides its done, whereas the RunnableTag defers all responsibilty of
deciding when to produce its body to an outer tag who can create the body
whenever it wishes (such as during an interation, switch statement, inside a
try / catch / finally blocks etc).

I'll illustrate the idea with an example:-
</description>

<example>
Let us imagine that we have a piece of JSP using a custom tag library as
follows:-

<foo:loop>
    <foo:case value="1">
        this is value 1
    </foo:case>
    <foo:case value="2">
        this is value 2
    </foo:case>
    ...
    <foo:case value="N">
        this is value N
    </foo:case>
</foo:loop>


And that the <foo:case> tag implements the RunnableTag interface. The JSP
code that gets generated would be as follows:-

// generated .java code from the above JSP file...

LoopTag loop = new LoopTag();
loop.setPageContext(...);
loop.setParent(...);
loop.setAttribute1(value1);
loop.setAttribute2(value2);
loop.doStartTag();

-- now we define all of the case tags
CaseTag case1Tag = new CaseTag();
case1Tag.setPageContext(...);
case1Tag.setParent(loop);
case1Tag.setValue("1");
case1Tag.setTagRunner( 
    new ReflectionTagRunner( this, "_case1_body_fn" case1Tag )
);
case1Tag.doRegister();

CaseTag case2Tag = new CaseTag();
case2Tag.setPageContext(...);
case2Tag.setParent(loop);
case2Tag.setValue("2");
case2Tag.setTagRunner( 
    new ReflectionTagRunner( this, "_case2_body_fn" case2Tag )
);
case2Tag.doRegister();

...
CaseTag caseNTag = new CaseTag();
caseNTag.setPageContext(...);
caseNTag.setParent(loop);
caseNTag.setValue("N");
caseNTag.setTagRunner( 
    new ReflectionTagRunner( this, "_caseN_body_fn" caseNTag )
);
caseNTag.doRegister();

-- now the loop tag performs its loop
-- calling the case tags directly as they are 
-- required
loop.doEndTag();

-- release all the tags 
...


-- now define all the functions
-- to make the bodies

/** This function is called by reflection in this example
  * whenever the tag: caseNTag has its run() method called.
  */
public void _caseN_body_fn(RunnableTag runnableTag) {
    PageContext pageContext = runnableTag.getPageContext();
    // declare all the implicit variables
    JspWriter out = pageContext.getOut();
    ...

    // now the code to generate the body goes here...    
    // this is a simple example though could be complex
    // using other tags, scriptlets etc.
    out.print( "This is value N" );
}

I've attached example implementations of the tags, LoopTag and CaseTag with
this email.

The only class not implemented in this mail is ReflectionTagRunner which
just calls the tag body function (e.g. _caseN_body_fn()) via reflection.
Inner classes is another alternative.
</example>

<implications>
2 new interfaces and 1 new class in package javax.servlet.jsp.tagext.
JSP compilers would need to test for new Tag interface (just as they have to
with IterationTag).


Using this new technique, tag library authors can generate efficient
switch/branching/looping structures using JSP custom tags.
</implications>

<to-do>
Get something like this accepted by the JSR 52/53 and I'll happily submit a
patch to Tomcat to implement it ;-)
</to-do>

Any comments on this proposal? It seems the next logical step from being
able to do simple if blocks and simple looping in JSP custom tags is to be
able to some form of "functions". Do others concur?

If anyone reading this is a member of JSR 52/53 could you please pass this
along for consideration?

<James/>



James Strachan
=============
email: [EMAIL PROTECTED]
web: http://www.metastuff.com



__________________________________________________________________

If you are not the addressee of this confidential e-mail and any 
attachments, please delete it and inform the sender; unauthorised 
redistribution or publication is prohibited. 
Views expressed are those of the author and do not necessarily 
represent those of Citria Limited.
__________________________________________________________________
          

TagRunner.java

RunnableTagSupport.java

RunnableTag.java

CaseTag.java

LoopTag.java

Reply via email to