struts-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Giovanni Azua <g...@imc.nl>
Subject Re: S2.1.x declarative validation and primitive types: is this a bug?
Date Thu, 06 Dec 2007 11:07:54 GMT
Hi Jeromy,

Many thanks for your thoughtful feedback on this issue.

Jeromy Evans wrote:
> Personally, I never expose primitives as properties of an action 
> because null values are always legal over this interface.  In the 
> special case of Boolean which can easily accidentally cause an NPE, I 
> always make the getter return false if the value is null..
>
> eg.
> Boolean getBooleanProperty() {
>  if (value != null) {
>     return value;
>  } else {
>      return false;
>  }
> }
Please note that the solution you propose above will not work with Struts
2 validation i.e. your proposed implementation will always produce a valid
non-null boolean type value and therefore the validation interceptor 
will never
complain when the "required" field validator is used. The framework forces
you to return null here.

I also found the cause for weird behavior of Boolean properties, the 
issue does
not really come from Struts but from the slightly unconventional Java 
1.5 type
coversion implementation in Boolean
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Boolean.html#valueOf(java.lang.String)

Boolean.valueOf returns e.g.

a) "true"         => Boolean.TRUE
b) "false"        => Boolean.FALSE
c) "whatever" => Boolean.FALSE
d) ""               => Boolean.FALSE
e) null             => Boolean.FALSE

Obviously if you don't take over this inconsistent conversion you run into
all of the troubles popping up on the OP. I can not disagree more with the
results of c) d) e) I would rather prefer getting null or better even a
BooleanFormatException orthogonal with other API e.g. NumberFormatException

I finally got the desired results by implementing a custom converter, 
see below.

regards,
Giovanni

********************* MyAction.java *************************
public
class MyAction
{
    
//------------------------------------------------------------------------
    /**
     * @param anAutoInitHitterMid the autoInitHitterMid to set
     */
    @TypeConversion(converter = 
"com.sag.optimizer.ui.web.support.BooleanConverter")
    public final void
    setAutoInitHitterMid(Boolean anAutoInitHitterMid)
    {
        theAutoInitHitterMid = anAutoInitHitterMid;
    }

    
//------------------------------------------------------------------------
    /**
     * @return the autoInitHitterMid
     */
    public final Boolean
    getAutoInitHitterMid()
    {  
        return theAutoInitHitterMid;
    }
}

****************** BooleanConverter.java *********************

public
class BooleanConverter
extends StrutsTypeConverter
{
    
//------------------------------------------------------------------------
    // public
    
//------------------------------------------------------------------------
    /** (non-Javadoc)
     * @see org.apache.struts2.util.StrutsTypeConverter#convertFromString(
     * java.util.Map, java.lang.String[], java.lang.Class)
     */
    @Override
    public Object
    convertFromString(Map aContext, String[] anArguments, Class aToClass)
    {
        if (anArguments.length != 1)
        {
            return super.performFallbackConversion(aContext, anArguments,
                aToClass);
        }
       
        String myStringValue = anArguments[0];
        Boolean myBooleanValue = null;
        if (myStringValue != null && myStringValue.trim().length() > 0 &&
            (myStringValue.equalsIgnoreCase(Boolean.TRUE.toString()) ||
                myStringValue.equalsIgnoreCase(Boolean.FALSE.toString())))
        {
            myBooleanValue = Boolean.valueOf(myStringValue);
        }           
       
        return myBooleanValue;
    }

    
//------------------------------------------------------------------------
    /** (non-Javadoc)
     * @see org.apache.struts2.util.StrutsTypeConverter#convertToString(
     * java.util.Map, java.lang.Object)
     */
    @Override
    public String
    convertToString(Map aContext, Object anObject)
    {
        String myStringValue = null;
       
        if (anObject != null && anObject instanceof Boolean)
        {
            myStringValue = ((Boolean) anObject).toString();
        }
       
        return myStringValue;
    }
}


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Mime
View raw message