Bug 22188

Summary: Type conversion rules not properly applied to <c:set>
Product: Taglibs Reporter: Pierre Delisle <pierre.delisle>
Component: Standard TaglibAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P3    
Version: 1.1   
Target Milestone: ---   
Hardware: All   
OS: All   

Description Pierre Delisle 2003-08-06 19:12:33 UTC
The <c:set> action in JSTL needs the capability to coerce an Object
to an expected type using the EL "type conversion rules"
when used as follows:

 <c:set target="${myBean}" property="prop" value="somevalue"/>

The JSTL spec says:

"... set the value of the property property of the JavaBeans object
target. If the type of the value to be set does not match the type of the bean
property, conversion is performed according to the conversion rules defined in
the expression language. With the exception of a null value,
setting a bean property with <c:set> is therefore exactly the same as setting an
attribute value of an action using the EL. A failure of these conversion rules to
determine an appropriate type coersion leads to a JspException at runtime."

The JSTL 1.1 code currently uses the 1.0 ExpressionEvaluator to perform the
coercion. 
This is a bug. It must rely on the JSP 2.0 ExpressionEvaluator
to perform this type conversion.

This issue fell through the cracks because using the 1.0 ExpressionEvaluator
works fine as long as no new coercion rules (defined in the EL of JSP 2.0)
are being used. The following example with BigDecimal triggers the
issue.

-----------------------------------------------------------------
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page import="java.math.*" %>

<%!
public class MyBean {
  private BigDecimal rate;
  public void setRate( BigDecimal rate ) {
    this.rate = rate;
  }
  public BigDecimal getRate() {
    return this.rate;
  }
}
%> 

<h3>test conversion 2</h3>
<% MyBean bean = new MyBean();
   bean.setRate(new BigDecimal("1.23456"));
   pageContext.setAttribute("bean", bean);
%>
rate is: ${bean.rate} <br>
<jsp:setProperty name="bean" property="rate"
                 value="${param.amount1}" />
new rate1: ${bean.rate} <br>

<c:set target="${bean}" property="rate"
                 value="${param.amount2}" />
new rate2: ${bean.rate} <br>

-----------------------------------------------------------------
Comment 1 Pierre Delisle 2003-08-06 19:21:48 UTC
Would be nice if a type conversion method would be exposed by 
the ExpressionEvaluator interface in JSP 2.0.

 For example:

 java.lang.Object convertToExpectedType(java.lang.Object value,
                                        java.lang.Class expectedType)
                 throws javax.servlet.jsp.el.ELException; 

Made the suggestion to Mark Roth, the JSP spec lead.

In the meantime, I'm using the following (clever) fix suggested by Mark:

    /**
     * Convert an object to an expected type according to the conversion
     * rules of the Expression Language.
     */
    private Object convertToExpectedType( final Object value,
    Class expectedType )
    throws javax.servlet.jsp.el.ELException {
        ExpressionEvaluator evaluator = pageContext.getExpressionEvaluator();
        return evaluator.evaluate( "${result}", expectedType,
        new VariableResolver() {
            public Object resolveVariable( String pName )
            throws ELException {
                return value;
            }
        }, null );
    }