You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@struts.apache.org by Nicolas De Loof <ni...@cgey.com> on 2002/04/03 17:25:08 UTC

strust.taglib.bean proposal

I've developped an ArgumentTag that allow to set attributes of the direct
parent tag.
so, with little evolution in MessageTag code (move "doStartTag" to
"doEndTag" and inherit BodyTagSupport) + in struts-bean.tld (set bodycontent
to "JSP" instead of "empty"), I can set bean:message arguments with a
bean:write tag


<bean:message key="welcome">
    <bean:argument arg="arg0">
        <bean:write name="user" property="name"/>
    </bean:argument>
</bean:message>


I think it could be used for other tags where attribute value could be
dynamically setted without scriptlet notation.


Here is the code from my argument tag :


import java.io.IOException;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.*;
import java.lang.reflect.*;

/**
 * Custom tag that sets attributes of it's parent tag
 * to allow use of bean:write tag to set attribute value.
 *
 * @author Nicolas De Loof
 */
public class ArgumentTag extends BodyTagSupport {

    // -------------------------------------------- Properties


    protected String arg = null;

    public String getArg() {
       return (this.arg);
    }

    public void setArg(String arg) {
       this.arg = arg;
    }

    // -------------------------------------------- Public Methods

    /**
     * Process the start tag.
     *
     */
    public int doStartTag() {
       // Process the body of this tag
       return (EVAL_BODY_TAG);
    }

    /**
     * Process the end tag.
     *
     */
    public int doEndTag() throws JspException {

       // Set argument to parent tag
       Tag parentTag = getParent();

       if (arg == null) {
          JspException e = new JspException
             ("arg is a mandatory attribute");
       }

       String setterName = "set"
          + arg.substring(0,1).toUpperCase()
          + arg.substring(1);
       try {
          System.out.println("setterName "+setterName);
          Method setter = parentTag.getClass().getMethod(
             setterName, new Class[] { String.class } );

          setter.invoke(parentTag,
             new Object[] {getBodyContent().getString()} );

        }
        catch (NoSuchMethodException nsme) {
           JspException e = new JspException
           ("incorrect argument name");
        }
        catch (IllegalAccessException iae) {
           JspException e = new JspException
             ("java.lang.reflect exception");
        }
        catch (InvocationTargetException ite) {
           JspException e = new JspException
              ("incorrect parent tag or argument name");
        }
        return (EVAL_PAGE);
     }


     /**
      * Release any acquired resources.
      */
     public void release() {
        super.release();
        arg = null;
     }

}


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: strust.taglib.bean proposal

Posted by Nicolas De Loof <ni...@cgey.com>.
>
>     Nicolas>        String setterName = "set"
>     Nicolas>           + arg.substring(0,1).toUpperCase()
>     Nicolas>           + arg.substring(1);
>     Nicolas>        try {
>     Nicolas>           System.out.println("setterName "+setterName);
>     Nicolas>           Method setter = parentTag.getClass().getMethod(
>     Nicolas>              setterName, new Class[] { String.class } );
>
>     Nicolas>           setter.invoke(parentTag,
>     Nicolas>              new Object[] {getBodyContent().getString()} );
>
> I believe the functionality in this block is basically what
> "BeanUtils.populate()" does, although with a little more overhead.
>

Your right,
BeanUtils.populate() uses a cleaner PropertyDescriptor interface to get
setter method, but BeanUtils.populate() needs a Map for bean attributes /
values and so is not easy to use for an attribute declaration using JSP Tag
syntax.

To set "arg0" attribute of parent Tag with the value of a bean property, it
would look like :

<parent tag>
    <attr:setAttribute>
        <attr:oneAttribute attr="arg0">
            <bean:write name="" property="" />
        <attr:oneAttribute>
    <attr:setAttribute >
</parent tag>



--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: strust.taglib.bean proposal

Posted by Nicolas De Loof <ni...@cgey.com>.
I didn't know about this cache mecanism and "multiple capital letters"
constraints.

For use in my JSP Tag to set parent tag Attribute (known value type:
String), do you think

PropertyUtils.setSimpleProperty(parentTag, arg, bodyContent)

is a good replacement from the reflection code ? So it will re-use
PropertyUtil cache and introspection mecanism.

> >
> >     Nicolas>        String setterName = "set"
> >     Nicolas>           + arg.substring(0,1).toUpperCase()
> >     Nicolas>           + arg.substring(1);
> >     Nicolas>        try {
> >     Nicolas>           System.out.println("setterName "+setterName);
> >     Nicolas>           Method setter = parentTag.getClass().getMethod(
> >     Nicolas>              setterName, new Class[] { String.class } );
> >
> >     Nicolas>           setter.invoke(parentTag,
> >     Nicolas>              new Object[] {getBodyContent().getString()} );
> >
> > I believe the functionality in this block is basically what
> > "BeanUtils.populate()" does, although with a little more overhead.
> >
>
> BeanUtils and PropertyUtils actually do somewhat more than this:
>
> * Property setter names do *not* have to start with "set" -- bean
>   developers can supply an additional BeanInfo class to define the
>   get and set method names.  BeanUtils uses the standard introspection
>   capabilities to do this lookup.
>
> * There are some special case rules for property names that start with
>   multiple capital letters that the introspection code deals with.
>
> * Because the introspection is the expensive part, the results are cached.
>   Therefore, BeanUtils will execute repeated property sets on the same
>   bean class much faster than the above code, which does a
>   getMethod() lookup every single time.
>
> * The BeanUtils version of the property setters (including the ones
>   called in populate()) do automatic type conversion for you, while
>   the PropertyUtils version of the property setters assumes you already
>   have the right data type.
>
> * The library methods know how to deal with indexed and mapped setters
>   as well as scalar properties.
>
> So, the above code (if included in the tag) would most likely be replaced
> by a call to PropertyUtils.getProperty() to take advantage of what the
> library can do.
>
> Craig
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: strust.taglib.bean proposal

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On Thu, 4 Apr 2002, Nicolas De Loof wrote:

> Date: Thu, 4 Apr 2002 16:40:57 +0200
> From: Nicolas De Loof <ni...@cgey.com>
> Reply-To: Struts Developers List <st...@jakarta.apache.org>
> To: Struts Developers List <st...@jakarta.apache.org>
> Subject: Re: strust.taglib.bean proposal
>
> I didn't know about this cache mecanism and "multiple capital letters"
> constraints.
>
> For use in my JSP Tag to set parent tag Attribute (known value type:
> String), do you think
>
> PropertyUtils.setSimpleProperty(parentTag, arg, bodyContent)
>
> is a good replacement from the reflection code ? So it will re-use
> PropertyUtil cache and introspection mecanism.
>

I'd say that it would be (assuming that bodyContent has already been
converted to a String, and arg is the property name of one of the parent
tag property setters).

Craig


> >
> > BeanUtils and PropertyUtils actually do somewhat more than this:
> >
> > * Property setter names do *not* have to start with "set" -- bean
> >   developers can supply an additional BeanInfo class to define the
> >   get and set method names.  BeanUtils uses the standard introspection
> >   capabilities to do this lookup.
> >
> > * There are some special case rules for property names that start with
> >   multiple capital letters that the introspection code deals with.
> >
> > * Because the introspection is the expensive part, the results are cached.
> >   Therefore, BeanUtils will execute repeated property sets on the same
> >   bean class much faster than the above code, which does a
> >   getMethod() lookup every single time.
> >
> > * The BeanUtils version of the property setters (including the ones
> >   called in populate()) do automatic type conversion for you, while
> >   the PropertyUtils version of the property setters assumes you already
> >   have the right data type.
> >
> > * The library methods know how to deal with indexed and mapped setters
> >   as well as scalar properties.
> >
> > So, the above code (if included in the tag) would most likely be replaced
> > by a call to PropertyUtils.getProperty() to take advantage of what the
> > library can do.
> >
> > Craig
> >
> >
> > --
> > To unsubscribe, e-mail:
> <ma...@jakarta.apache.org>
> > For additional commands, e-mail:
> <ma...@jakarta.apache.org>
>
>
> --
> To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
> For additional commands, e-mail: <ma...@jakarta.apache.org>
>
>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: strust.taglib.bean proposal

Posted by Nicolas De Loof <ni...@cgey.com>.
I didn't know about this cache mecanism and "multiple capital letters"
constraints.

For use in my JSP Tag to set parent tag Attribute (known value type:
String), do you think

PropertyUtils.setSimpleProperty(parentTag, arg, bodyContent)

is a good replacement from the reflection code ? So it will re-use
PropertyUtil cache and introspection mecanism.

>
> BeanUtils and PropertyUtils actually do somewhat more than this:
>
> * Property setter names do *not* have to start with "set" -- bean
>   developers can supply an additional BeanInfo class to define the
>   get and set method names.  BeanUtils uses the standard introspection
>   capabilities to do this lookup.
>
> * There are some special case rules for property names that start with
>   multiple capital letters that the introspection code deals with.
>
> * Because the introspection is the expensive part, the results are cached.
>   Therefore, BeanUtils will execute repeated property sets on the same
>   bean class much faster than the above code, which does a
>   getMethod() lookup every single time.
>
> * The BeanUtils version of the property setters (including the ones
>   called in populate()) do automatic type conversion for you, while
>   the PropertyUtils version of the property setters assumes you already
>   have the right data type.
>
> * The library methods know how to deal with indexed and mapped setters
>   as well as scalar properties.
>
> So, the above code (if included in the tag) would most likely be replaced
> by a call to PropertyUtils.getProperty() to take advantage of what the
> library can do.
>
> Craig
>
>
> --
> To unsubscribe, e-mail:
<ma...@jakarta.apache.org>
> For additional commands, e-mail:
<ma...@jakarta.apache.org>


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: strust.taglib.bean proposal

Posted by "Craig R. McClanahan" <cr...@apache.org>.

On 3 Apr 2002, David M. Karr wrote:

> Date: 03 Apr 2002 16:49:12 -0800
> From: David M. Karr <dm...@earthlink.net>
> Reply-To: Struts Developers List <st...@jakarta.apache.org>
> To: struts-dev@jakarta.apache.org
> Subject: Re: strust.taglib.bean proposal
>
> >>>>> "Nicolas" == Nicolas De Loof <ni...@cgey.com> writes:
>
>     Nicolas>        String setterName = "set"
>     Nicolas>           + arg.substring(0,1).toUpperCase()
>     Nicolas>           + arg.substring(1);
>     Nicolas>        try {
>     Nicolas>           System.out.println("setterName "+setterName);
>     Nicolas>           Method setter = parentTag.getClass().getMethod(
>     Nicolas>              setterName, new Class[] { String.class } );
>
>     Nicolas>           setter.invoke(parentTag,
>     Nicolas>              new Object[] {getBodyContent().getString()} );
>
> I believe the functionality in this block is basically what
> "BeanUtils.populate()" does, although with a little more overhead.
>

BeanUtils and PropertyUtils actually do somewhat more than this:

* Property setter names do *not* have to start with "set" -- bean
  developers can supply an additional BeanInfo class to define the
  get and set method names.  BeanUtils uses the standard introspection
  capabilities to do this lookup.

* There are some special case rules for property names that start with
  multiple capital letters that the introspection code deals with.

* Because the introspection is the expensive part, the results are cached.
  Therefore, BeanUtils will execute repeated property sets on the same
  bean class much faster than the above code, which does a
  getMethod() lookup every single time.

* The BeanUtils version of the property setters (including the ones
  called in populate()) do automatic type conversion for you, while
  the PropertyUtils version of the property setters assumes you already
  have the right data type.

* The library methods know how to deal with indexed and mapped setters
  as well as scalar properties.

So, the above code (if included in the tag) would most likely be replaced
by a call to PropertyUtils.getProperty() to take advantage of what the
library can do.

Craig


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>


Re: strust.taglib.bean proposal

Posted by "David M. Karr" <dm...@earthlink.net>.
>>>>> "Nicolas" == Nicolas De Loof <ni...@cgey.com> writes:

    Nicolas>        String setterName = "set"
    Nicolas>           + arg.substring(0,1).toUpperCase()
    Nicolas>           + arg.substring(1);
    Nicolas>        try {
    Nicolas>           System.out.println("setterName "+setterName);
    Nicolas>           Method setter = parentTag.getClass().getMethod(
    Nicolas>              setterName, new Class[] { String.class } );

    Nicolas>           setter.invoke(parentTag,
    Nicolas>              new Object[] {getBodyContent().getString()} );

I believe the functionality in this block is basically what
"BeanUtils.populate()" does, although with a little more overhead.

-- 
===================================================================
David M. Karr          ; Java/J2EE/XML/Unix/C++
dmkarr@earthlink.net


--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>