MyFaces Core
  1. MyFaces Core
  2. MYFACES-1670

A dollar-type, 2 level EL expression evaluates to null

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.1-SNAPSHOT
    • Fix Version/s: 1.2.0-SNAPSHOT, 1.2.2
    • Component/s: JSR-252
    • Labels:
      None
    • Environment:
      geronimo-2.0-M6-rc1

      Description

      I have a simple code where dollar-type expression (like ${}) works differently than shrap-type expression (like #{}),
      I put into the http session a managed bean aggregating another bean.
      $

      {parent}

      is calculated, while $

      {parent.child}

      is always null (it is printed as an empty string and equals to null in "when" tag).

      For example the following snip of JSP code:
      <f:view>
      <h:form id="myform" >
      <b>Using sharp-el</b>: <br/>
      *<h:outputText id="cll1" value="#

      {customerDetailsBean}" />*<br/>
      <h:outputText id="cll2" value="#{customerDetailsBean.customer}" /><br/>
      <b>Using dollar-el</b>: <br/>
      *${customerDetailsBean}

      *<br/>
      *$

      {customerDetailsBean.customer}

      *<br/>
      <b>Classical "servlet" style</b>: <br/>
      *<% if (session.getAttribute("customerDetailsBean") != null)

      {%><%= session.getAttribute("customerDetailsBean") %><% }

      %>*<br/>
      *<% if (session.getAttribute("customerDetailsBean") != null)

      {%><%= ((eltest.CustomerDetailsBean)session.getAttribute("customerDetailsBean")).getCustomer() %><% }

      %>*<br/>
      </h:form>
      </f:view>

      – PRODUCES --:

      Using sharp-el:
      CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}
      *Customer

      {frstName: Alex , lastName: Zynevich, id: 1979}

      *
      Using dollar-el:
      CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}
      **
      Classical "servlet" style:
      CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}
      *Customer

      {frstName: Alex , lastName: Zynevich, id: 1979}

      *

      while I would expect:

      Using sharp-el:
      CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}
      *Customer

      {frstName: Alex , lastName: Zynevich, id: 1979}

      *
      Using dollar-el:
      CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}
      *Customer

      {frstName: Alex , lastName: Zynevich, id: 1979}

      *
      Classical "servlet" style:
      CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}
      *Customer

      {frstName: Alex , lastName: Zynevich, id: 1979}

      *

      you may find the maven project at https://issues.apache.org/jira/browse/GERONIMO-3253, war is attached

      1. eltest.war
        6 kB
        Alexander Zynevich
      2. Customer.java
        0.6 kB
        Alexander Zynevich
      3. CustomerDetailsBean.java
        0.8 kB
        Alexander Zynevich
      4. print.jsp
        1 kB
        Alexander Zynevich
      5. faces-config.xml
        1 kB
        Alexander Zynevich
      6. web.xml
        1.0 kB
        Alexander Zynevich
      7. MYFACES-1670.patch
        1 kB
        Bernhard Huemer

        Issue Links

          Activity

          Leonardo Uribe made changes -
          Fix Version/s 1.2.1 [ 12312895 ]
          Fix Version/s 1.2.2 [ 12312932 ]
          Leonardo Uribe made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          Leonardo Uribe made changes -
          Fix Version/s 1.2.1 [ 12312895 ]
          Fix Version/s 1.2.1-SNAPSHOT [ 12312571 ]
          Martin Marinschek made changes -
          Assignee Martin Marinschek [ mmarinschek ]
          Fix Version/s 1.2.1-SNAPSHOT [ 12312571 ]
          Resolution Fixed [ 1 ]
          Status Patch Available [ 10002 ] Resolved [ 5 ]
          Hide
          Martin Marinschek added a comment -

          Sounds reasonable. Thanks Bernhard!

          regards,

          Martin

          Show
          Martin Marinschek added a comment - Sounds reasonable. Thanks Bernhard! regards, Martin
          Bernhard Huemer made changes -
          Status Open [ 1 ] Patch Available [ 10002 ]
          Bernhard Huemer made changes -
          Attachment MYFACES-1670.patch [ 12363632 ]
          Hide
          Bernhard Huemer added a comment -

          The problem is a legacy PropertyResolver being required by the JSF 1.2 specification (org.apache.myfaces.el.DefaultPropertyResolver). This PropertyResolver just has to call "FacesContext.getCurrentInstance().getELContext().setPropertyResolved(false);" (see JSF 1.2 specification, 5.8.2). However, if the container is evaluating an expression, it uses its own ELContext implementation (e.g. org.apache.jasper.el.ELContextImpl).

          At the beginning I've said that the problem is the legacy PropertyResolver, but that's not really the case as its expected behaviour is described in the specification. Actually, the adapter class making it possible to use PropertyResolvers in the ELResolver chain is incorrect. Before delegating the request to the PropertyResolver it assumes that the property will be resolved and therefore calls "context.setPropertyResolved(true);". This behaviour is also according the specification if I haven't got it wrong (5.6.1.6). If the PropertyResolver is not able to fulfill the task it just has to call "context.setPropertyResolved(false);", but remember that a PropertyResolver just knows how to access the FacesELContext.

          Therefore the adapter class has to inform its given context whether the property has been resolved or not according to the FacesELContext. I'll attach a patch.

          Show
          Bernhard Huemer added a comment - The problem is a legacy PropertyResolver being required by the JSF 1.2 specification (org.apache.myfaces.el.DefaultPropertyResolver). This PropertyResolver just has to call "FacesContext.getCurrentInstance().getELContext().setPropertyResolved(false);" (see JSF 1.2 specification, 5.8.2). However, if the container is evaluating an expression, it uses its own ELContext implementation (e.g. org.apache.jasper.el.ELContextImpl). At the beginning I've said that the problem is the legacy PropertyResolver, but that's not really the case as its expected behaviour is described in the specification. Actually, the adapter class making it possible to use PropertyResolvers in the ELResolver chain is incorrect. Before delegating the request to the PropertyResolver it assumes that the property will be resolved and therefore calls "context.setPropertyResolved(true);". This behaviour is also according the specification if I haven't got it wrong (5.6.1.6). If the PropertyResolver is not able to fulfill the task it just has to call "context.setPropertyResolved(false);", but remember that a PropertyResolver just knows how to access the FacesELContext. Therefore the adapter class has to inform its given context whether the property has been resolved or not according to the FacesELContext. I'll attach a patch.
          Matthias Weßendorf made changes -
          Affects Version/s 1.2.1-SNAPSHOT [ 12312571 ]
          Alexander Zynevich made changes -
          Description I have a simple code where dollar-type expression (like ${}) works differently than shrap-type expression (like #{}),
          I put into the http session a managed bean aggregating another bean.
          ${parent} is calculated, while ${parent.child} is always null (it is printed as an empty string and equals to null in "when" tag).

          For example the following snip of JSP code:
             <f:view>
              <h:form id="myform" >
              <b>Using sharp-el</b>: <br/>
              \*<h:outputText id="cll1" value="#{customerDetailsBean}" />\*<br/>
              \*<h:outputText id="cll2" value="#{customerDetailsBean.customer}" />\*<br/>
              <b>Using dollar-el</b>: <br/>
              \*${customerDetailsBean}\*<br/>
              \*${customerDetailsBean.customer}\*<br/>
              <b>Classical "servlet" style</b>: <br/>
              \*<% if (session.getAttribute("customerDetailsBean") != null) {%><%= session.getAttribute("customerDetailsBean") %><% } %>\*<br/>
              \*<% if (session.getAttribute("customerDetailsBean") != null) {%><%= ((eltest.CustomerDetailsBean)session.getAttribute("customerDetailsBean")).getCustomer() %><% } %>\*<br/>
              </h:form>
              </f:view>

          -- PRODUCES --:

              *Using sharp-el:*
              \*CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}\*
              \*Customer {frstName: Alex , lastName: Zynevich, id: 1979}\*
              *Using dollar-el:*
              \*CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}\*
              \*\*
              *Classical "servlet" style:*
              \*CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}\*
              \*Customer {frstName: Alex , lastName: Zynevich, id: 1979}\*

          while I would expect:

              *Using sharp-el:*
              \*CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}\*
              \*Customer {frstName: Alex , lastName: Zynevich, id: 1979}\*
              *Using dollar-el:*
              \*CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}\*
              \*Customer {frstName: Alex , lastName: Zynevich, id: 1979}\*
              *Classical "servlet" style:*
              \*CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}\*
              \*Customer {frstName: Alex , lastName: Zynevich, id: 1979}\*

          you may find the maven project at https://issues.apache.org/jira/browse/GERONIMO-3253, war is attached
          I have a simple code where dollar-type expression (like ${}) works differently than shrap-type expression (like #{}),
          I put into the http session a managed bean aggregating another bean.
          ${parent} is calculated, while ${parent.child} is always null (it is printed as an empty string and equals to null in "when" tag).

          For example the following snip of JSP code:
             <f:view>
              <h:form id="myform" >
              <b>Using sharp-el</b>: <br/>
              *<h:outputText id="cll1" value="#{customerDetailsBean}" />*<br/>
              *<h:outputText id="cll2" value="#{customerDetailsBean.customer}" />*<br/>
              <b>Using dollar-el</b>: <br/>
              *${customerDetailsBean}*<br/>
              *${customerDetailsBean.customer}*<br/>
              <b>Classical "servlet" style</b>: <br/>
              *<% if (session.getAttribute("customerDetailsBean") != null) {%><%= session.getAttribute("customerDetailsBean") %><% } %>*<br/>
              *<% if (session.getAttribute("customerDetailsBean") != null) {%><%= ((eltest.CustomerDetailsBean)session.getAttribute("customerDetailsBean")).getCustomer() %><% } %>*<br/>
              </h:form>
              </f:view>

          -- PRODUCES --:

              Using sharp-el:
              *CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}*
              *Customer {frstName: Alex , lastName: Zynevich, id: 1979}*
              Using dollar-el:
              *CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}*
              **
              Classical "servlet" style:
              *CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}*
              *Customer {frstName: Alex , lastName: Zynevich, id: 1979}*

          while I would expect:

              Using sharp-el:
              *CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}*
              *Customer {frstName: Alex , lastName: Zynevich, id: 1979}*
              Using dollar-el:
              *CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}*
              *Customer {frstName: Alex , lastName: Zynevich, id: 1979}*
              Classical "servlet" style:
              *CustomerDetailsBean: { customer: Customer {frstName: Alex , lastName: Zynevich, id: 1979}}*
              *Customer {frstName: Alex , lastName: Zynevich, id: 1979}*

          you may find the maven project at https://issues.apache.org/jira/browse/GERONIMO-3253, war is attached
          Hide
          Alexander Zynevich added a comment -

          just rechecked this smallest application in Glassfish, it did produce output as expected,
          I also recheck it on Geronimo with different <managed-bean-scope>: application, request, session. Result is always the same and incorrect.

          Show
          Alexander Zynevich added a comment - just rechecked this smallest application in Glassfish, it did produce output as expected, I also recheck it on Geronimo with different <managed-bean-scope>: application, request, session. Result is always the same and incorrect.
          Alexander Zynevich made changes -
          Link This issue is duplicated by GERONIMO-3253 [ GERONIMO-3253 ]
          Alexander Zynevich made changes -
          Attachment faces-config.xml [ 12360420 ]
          Attachment web.xml [ 12360421 ]
          Attachment print.jsp [ 12360419 ]
          Alexander Zynevich made changes -
          Attachment CustomerDetailsBean.java [ 12360418 ]
          Alexander Zynevich made changes -
          Attachment Customer.java [ 12360417 ]
          Alexander Zynevich made changes -
          Attachment Customer.java [ 12360416 ]
          Alexander Zynevich made changes -
          Attachment Customer.java [ 12360416 ]
          Alexander Zynevich made changes -
          Attachment eltest.war [ 12360415 ]
          Alexander Zynevich made changes -
          Attachment eltest.war [ 12360414 ]
          Alexander Zynevich made changes -
          Field Original Value New Value
          Attachment eltest.war [ 12360414 ]
          Alexander Zynevich created issue -

            People

            • Assignee:
              Martin Marinschek
              Reporter:
              Alexander Zynevich
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development