You are viewing a plain text version of this content. The canonical link for it is here.
Posted to taglibs-dev@jakarta.apache.org by James Strachan <ja...@metastuff.com> on 2001/02/12 19:26:29 UTC

Proposal: RunnableTag custom JSP tags interface (RE: was Using JS P in functions ...)

<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: james@metastuff.com
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.
__________________________________________________________________
          


Re: Proposal: RunnableTag custom JSP tags interface (RE: was Using JSP in functions ...)

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
James,

The best way to ensure that this proposal gets considered by the JSR-053 expert
group (since you are proposing JSP specification changes) is to send it to:

    jsp-spec-comments@eng.sun.com

which is the official feedback address for comments and suggestions on the JSP
specifications.

Given that JSP 1.2 is in "proposed final draft" state at the moment, I don't know
how likely inclusion of new functionality would be, but submitting it to the
feedback address above is how to kick off consideration of these ideas.

Craig McClanahan



James Strachan wrote:

> <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: james@metastuff.com
> 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.
> __________________________________________________________________
>
>
>   ------------------------------------------------------------------------
>                      Name: TagRunner.java
>    TagRunner.java    Type: unspecified type (application/octet-stream)
>                  Encoding: quoted-printable
>
>                               Name: RunnableTagSupport.java
>    RunnableTagSupport.java    Type: unspecified type (application/octet-stream)
>                           Encoding: quoted-printable
>
>                        Name: RunnableTag.java
>    RunnableTag.java    Type: unspecified type (application/octet-stream)
>                    Encoding: quoted-printable
>
>                    Name: CaseTag.java
>    CaseTag.java    Type: unspecified type (application/octet-stream)
>                Encoding: quoted-printable
>
>                    Name: LoopTag.java
>    LoopTag.java    Type: unspecified type (application/octet-stream)
>                Encoding: quoted-printable