javaserverfaces-spec-public
  1. javaserverfaces-spec-public
  2. JAVASERVERFACES_SPEC_PUBLIC-1226

Inconsistent handling of null/undeclared attributes, especially with nested components

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.1, 2.2
    • Fix Version/s: None
    • Labels:
      None
    • Environment:

      GF3 + JSF 2.1.26 or GF4 with JSF 2.2.3 with JDK7.0_45

      Description

      The origin is here: https://java.net/jira/browse/JAVASERVERFACES-2614, but it's mainly worth reading the summary further down here.

      The reproducer is on git@github.com:fabmars/JSF2614.git .
      We have an outer component:

      test1.xhtml
      <composite:interface>
      <composite:attribute name="val1" type="java.lang.String"/>
      <composite:attribute name="val2" type="java.lang.String"/>
      <composite:attribute name="val3" type="java.lang.String" default="#{null}"/>
      <composite:attribute name="val4" type="java.lang.String" default="#{null}"/>
      </composite:interface>
      
      <composite:implementation>
      <h:panelGrid>
      <h:outputText value="Outer1: #{cc.attrs.val1 == null ? 'null' : (empty cc.attrs.val1 ? 'empty' : cc.attrs.val1)}" />
      <h:outputText value="Outer2: #{cc.attrs.val2 == null ? 'null' : (empty cc.attrs.val2 ? 'empty' : cc.attrs.val2)}" />
      <h:outputText value="Outer3: #{cc.attrs.val3 == null ? 'null' : (empty cc.attrs.val3 ? 'empty' : cc.attrs.val3)}" />
      <h:outputText value="Outer4: #{cc.attrs.val4 == null ? 'null' : (empty cc.attrs.val4 ? 'empty' : cc.attrs.val4)}" />
      </h:panelGrid>
      <sr:test2 val1="#{cc.attrs.val1}" val2="#{cc.attrs.val2}" val3="#{cc.attrs.val3}" val4="#{cc.attrs.val4}" /> 
      </composite:implementation>
      

      And an inner component:

      test2.xhtml
      <composite:interface>
      	<composite:attribute name="val1" type="java.lang.String"/>
      	<composite:attribute name="val2" type="java.lang.String" default="#{null}"/>
      	<composite:attribute name="val3" type="java.lang.String"/>
      	<composite:attribute name="val4" type="java.lang.String" default="#{null}"/>
      </composite:interface>
      
      <composite:implementation>
      	<h:panelGrid>
      		<h:outputText value="Inner1: #{cc.attrs.val1 == null ? 'null' : (empty cc.attrs.val1 ? 'empty' : cc.attrs.val1)}" />
      		<h:outputText value="Inner2: #{cc.attrs.val2 == null ? 'null' : (empty cc.attrs.val2 ? 'empty' : cc.attrs.val2)}" />
      		<h:outputText value="Inner3: #{cc.attrs.val3 == null ? 'null' : (empty cc.attrs.val3 ? 'empty' : cc.attrs.val3)}" />
      		<h:outputText value="Inner4: #{cc.attrs.val4 == null ? 'null' : (empty cc.attrs.val4 ? 'empty' : cc.attrs.val4)}" />
      	</h:panelGrid>
      </composite:implementation>
      

      And the actual page:

      jsf2614.xhtml
      <sr:test1 val1="AAA" val2="BBB" val3="CCC" val4="DDD"/>
      <sr:test1/>
      <sr:test1 val1="#{null}" val2="#{null}" val3="#{null}" val4="#{null}"/>
      <sr:test2  val1="DDD" val2="EEE" val3="FFF" val4="GGG"/>
      <sr:test2/>
      <sr:test2 val1="#{null}" val2="#{null}" val3="#{null}" val4="#{null}"/>
      

      When running one can notice a couple of odd things:

      1st case:
      On <sr:test1 .../>

      • feed <composite:attribute name="val1" type="java.lang.String"/> with null. Result: null
      • feed <composite:attribute name="val3" type="java.lang.String" default="# {null}"/> with null. Result: ""
        The developer, in the second line expects to get String var3 = null in the end. Instead he gets a real value.
        OK this is due to the mechanics of coertion but this is not consistent and imo should be fixed.


        2nd case:
        - Call the OUTER component dry <sr:test1/>. var1 isn't declared, so will be assumed null. In sr:test1 implementation is a call to <sr:test2 val1="#{cc.attrs.val1}"... The INNER(sr:test2) component is awaiting a String as val1 (<composite:attribute name="val1" type="java.lang.String"/>) and our non-declared attribute becomes "" (again) in the end! (see that lines 9 vs 13 of the output). In other words: feed a null to <composite:attribute name="val1" type="java.lang.String"/> directly, it stays null, feed it from a surrounding component, it becomes ""!


        3rd case:
        Calling directly the inner component <sr:test2/> and <sr:test2 val1="#{null}

        " val2="#

        {null}" val3="#{null}

        " val4="#

        {null}

        "/> produce totally different results (see lines 29-32 vs 33-36 of the output). This is confusing for the developer and I'm not even sure this is a "feature".

        Activity

        fabmars created issue -
        Ed Burns made changes -
        Field Original Value New Value
        Assignee rogerk [ rogerk ]
        Hide
        Ed Burns added a comment -

        Set priority to baseline ahead of JSF 2.3 triage. Priorities will be assigned accurately after this exercise.

        Show
        Ed Burns added a comment - Set priority to baseline ahead of JSF 2.3 triage. Priorities will be assigned accurately after this exercise.
        Ed Burns made changes -
        Priority Major [ 3 ] Trivial [ 5 ]
        Ed Burns made changes -
        Priority Trivial [ 5 ] Minor [ 4 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            fabmars
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: