[JAVASERVERFACES_SPEC_PUBLIC-1226] Inconsistent handling of null/undeclared attributes, especially with nested components Created: 07/Oct/13  Updated: 13/Aug/14

Status: Open
Project: javaserverfaces-spec-public
Component/s: Components/Renderers, Facelets/VDL
Affects Version/s: 2.1, 2.2
Fix Version/s: None

Type: Improvement Priority: Minor
Reporter: fabmars Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

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

Tags: composite, composite-component, null


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:

<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}"/>

<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)}" />
<sr:test2 val1="#{cc.attrs.val1}" val2="#{cc.attrs.val2}" val3="#{cc.attrs.val3}" val4="#{cc.attrs.val4}" /> 

And an inner component:

	<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}"/>

		<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)}" />

And the actual page:

<sr:test1 val1="AAA" val2="BBB" val3="CCC" val4="DDD"/>
<sr:test1 val1="#{null}" val2="#{null}" val3="#{null}" val4="#{null}"/>
<sr:test2  val1="DDD" val2="EEE" val3="FFF" val4="GGG"/>
<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="#


    "/> 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".

Comment by Ed Burns [ 01/Aug/14 ]

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

Generated at Mon Apr 27 14:03:29 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.