uel
  1. uel
  2. UEL-20

ListELResolver.getValue() NumberFormatException

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: current
    • Fix Version/s: milestone 1
    • Component/s: www
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      20

      Description

      ListELResolver.getValue() is too greedy - it assumes if object implements List it can be
      indexed by supplied property. For example:
      #

      {employeeBean.clTestingAreas.map[employee.teaTeaId].name}

      clTestingAreas imlements List, but also contains field "map".

      The result of evaluation is:

      java.lang.NumberFormatException: For input string: "map"
      at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
      at java.lang.Integer.parseInt(Integer.java:449)
      at java.lang.Integer.parseInt(Integer.java:499)
      at javax.el.ListELResolver.toInteger(ListELResolver.java:407)
      at javax.el.ListELResolver.getValue(ListELResolver.java:199)
      at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)

        Activity

        Hide
        kchung added a comment -

        The JSP spec defines the order that the ELResolvers must be applied. In
        particular, ListELResolver must be applied before BeanELResolver. See JSP.2.9.
        Therefore when encountering the expression "clTestingAreas.map", ListELResolver
        is applied.

        Once in ListELResolver, the property parameter is coerced to a number. The
        javadocs for it says:

        • @param property The index of the value to be returned. Will be coerced
        • into an integer.

        It might makes more sense that BeanELResolver should be used to resolve this,
        but unfortunately this not what the spec says today.

        You can probably get around this issue by calling the access method directly:

        #

        {employeeBean.clTestingAreas.getMap()[employee.teaTeaId].name}

        Show
        kchung added a comment - The JSP spec defines the order that the ELResolvers must be applied. In particular, ListELResolver must be applied before BeanELResolver. See JSP.2.9. Therefore when encountering the expression "clTestingAreas.map", ListELResolver is applied. Once in ListELResolver, the property parameter is coerced to a number. The javadocs for it says: @param property The index of the value to be returned. Will be coerced into an integer. It might makes more sense that BeanELResolver should be used to resolve this, but unfortunately this not what the spec says today. You can probably get around this issue by calling the access method directly: # {employeeBean.clTestingAreas.getMap()[employee.teaTeaId].name}
        Hide
        arkadi added a comment -

        Such interpretation of spec is:
        1. Too narrow: the specification defines resolvers order, but not how list
        resolver must behave when property is not a number.

        2. Wrong: from CompositeELResolver "If it could not handle the given pair, it
        must leave this property alone". EL coercion rules does not force list resolver
        to throw an exception, but defines such situation as coercion "error". "Error"
        means "cannot handle", IMO.
        Taking this further: 1.18.3 Coerce A to Number type N of Expression Language
        Speci�cation Version 2.1 defines coercion rules, but ListELResolver.toInteger()
        is not compliant, for example "If A is Boolean, then error".

        3. Doesn't help in real world situation: it is possible to unambiguously
        resolve the "map" but you choose not to, instead bailing out with number format
        exception (bad diagnostics, BTW).

        Can you handle #

        {list.234}

        ? No? Why not? But why you're trying to handle #

        {list.attr}

        then?
        Amending list resolver to check if passed property consists of digits only (or
        whatever 1.18.3 prescribes) and only then raising an error (if index is out of
        bounds) would not be a titan's work.

        Show
        arkadi added a comment - Such interpretation of spec is: 1. Too narrow: the specification defines resolvers order, but not how list resolver must behave when property is not a number. 2. Wrong: from CompositeELResolver "If it could not handle the given pair, it must leave this property alone". EL coercion rules does not force list resolver to throw an exception, but defines such situation as coercion "error". "Error" means "cannot handle", IMO. Taking this further: 1.18.3 Coerce A to Number type N of Expression Language Speci�cation Version 2.1 defines coercion rules, but ListELResolver.toInteger() is not compliant, for example "If A is Boolean, then error". 3. Doesn't help in real world situation: it is possible to unambiguously resolve the "map" but you choose not to, instead bailing out with number format exception (bad diagnostics, BTW). Can you handle # {list.234} ? No? Why not? But why you're trying to handle # {list.attr} then? Amending list resolver to check if passed property consists of digits only (or whatever 1.18.3 prescribes) and only then raising an error (if index is out of bounds) would not be a titan's work.
        Hide
        kchung added a comment -

        The spec is clear that the parameter "property" of ListELResolve.getValue()
        should be taken as an index, and should be converted to a integer. It is proper
        to raise an error if it not an number, since doing anything else would hide the
        source of error from the user.

        The ELResolvers were designed to resolve expressions based on the type of the
        base object. ListELResolver is meant to handle only indexed List object.

        The only way to do what you want is to place ListELResolver after the
        BeanELResolver in the search list. This is however, disallowed by the JSP spec.

        Show
        kchung added a comment - The spec is clear that the parameter "property" of ListELResolve.getValue() should be taken as an index, and should be converted to a integer. It is proper to raise an error if it not an number, since doing anything else would hide the source of error from the user. The ELResolvers were designed to resolve expressions based on the type of the base object. ListELResolver is meant to handle only indexed List object. The only way to do what you want is to place ListELResolver after the BeanELResolver in the search list. This is however, disallowed by the JSP spec.

          People

          • Assignee:
            uel-issues
            Reporter:
            arkadi
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: