You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by "Bob (JIRA)" <de...@myfaces.apache.org> on 2007/04/04 01:55:32 UTC

[jira] Created: (MYFACES-1581) UISelectOne encounters exception in call to equals()

UISelectOne encounters exception in call to equals()
----------------------------------------------------

                 Key: MYFACES-1581
                 URL: https://issues.apache.org/jira/browse/MYFACES-1581
             Project: MyFaces Core
          Issue Type: Bug
          Components: General
    Affects Versions: 1.1.5
         Environment: Any, found using JDK 1.6, JBoss 4.0.1, Windows XP SP2
            Reporter: Bob


After doing a bit of research, I'm convinced a problem occurs when SelectItem.itemValue is an EJB. Given that 1.1.3 and the RI (1.2_04) do not have this problem, I suggest the current implementation be changed. If I'm wrong, please help me understand. Otherwise, I'll submit a change request. 

JSP contents: 
         <h:selectOneMenu id="client" value="#{myPage.projectType}" required="true"> 
             <f:converter converterId="x.y.ProjectTypeConverter"/> 
             <f:selectItem itemValue="" itemLabel="--- Select Project Type---"/> 
             <f:selectItems value="#{myPage.projectTypeList}"/> 
         </h:selectOneMenu> 

Where ProjectTypeConverter returns null for "" on input and myPage.projectTypeList is a list of SelectItem created in the following manner: 

         ArrayList projectTypes = new ArrayList( projectTypeHome.findAll() ); 
         for( int i = 0; i < projectTypes.size(); i++ ) 
         { 
            ProjectTypeLocal projectType = (ProjectTypeLocal)projectTypes.get( i ); 
            m_projectTypes.add( new SelectItem( projectType, projectType.getName() ) ); 
         } 

Note that the SelectItem.itemValue is an EJB. 

The intent is to force the user to select a value from the list. If no action is taken by the user, generate an error. This is directly analogous to a Tomahawk example, except the values are EJB's. 

The problem: 
This worked fine under MyFaces 1.1.3 and appears that it would work under RI 1.2_04. Under release 1.1.5, however, a ClassCastException occurs during the validation phase, but only if a list item is selected and the item is an EJB. 

Analysis (based on 1.1.5 release): 
During the validation phase, UISelectOne.validateValue is invoked with the selected EJB. This causes the following lines in _SelectItemsUtil.matchValue() to be invoked: 

                [item is class SelectItem] 
                Object itemValue = item.getValue(); 
                if (value==itemValue || value.equals(itemValue)) 

This is fine for the SelectItem values that are EJB's, but not for "". Since EJB equality requires identity, the EJB equals() method calls isIdentical() and immediately encounters an exception casting to EJBLocalObject (code here from JBoss 4.0.4GA LocalProxy): 

   Boolean isIdentical(final Object a, final Object b) 
   { 
      final EJBLocalObject ejb = (EJBLocalObject)a; 
      Boolean isIdentical = Boolean.FALSE; 
      if( ejb != null ) 
      { 
         isIdentical = new Boolean(ejb.toString().equals(b)); 
      } 
      return isIdentical; 
   } 

Possible solution: 
In _SelectItemsUtil.matchValue() change the lines above to: 

                [item is class SelectItem] 
                Object itemValue = item.getValue(); 
                if (value==itemValue || ( itemValue != null && itemValue.equals(value))) 

Note: The attached test files attempt to recreate the exception with a POJO rather than an EJB.



-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MYFACES-1581) UISelectOne encounters exception in call to equals()

Posted by "Mike Kienenberger (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-1581?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12486718 ] 

Mike Kienenberger commented on MYFACES-1581:
--------------------------------------------

Ok.  The null equality test is a red-herring and unnecessary part of this patch.
Both itemValue and value are guaranteed to be non-null at this point.

What the patch actually does is swap value and itemValue so that itemValue is doing the comparision.   This assumes that a generic Object (typically String) is more likely to have a correct equals implementation that can handle mismatched classes whereas the converted object will not.

Unfortunately, this does point to a flawed equals() implementation in your converted objects.   There's probably no harm in swapping the arguments, but it won't fix the problem -- only hide it for the case where only one broken class is involved.

I'll go ahead and do this, but I'd strongly recommend fixing your code because this won't be the only place you'll run into this problem.


> UISelectOne encounters exception in call to equals()
> ----------------------------------------------------
>
>                 Key: MYFACES-1581
>                 URL: https://issues.apache.org/jira/browse/MYFACES-1581
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: General
>    Affects Versions: 1.1.5
>         Environment: Any, found using JDK 1.6, JBoss 4.0.1, Windows XP SP2
>            Reporter: Bob
>         Attachments: _SelectItemsUtil.java.diff, faces-config.xml, MyValue.java, TestMyValues.java, testValues.jsp
>
>
> After doing a bit of research, I'm convinced a problem occurs when SelectItem.itemValue is an EJB. Given that 1.1.3 and the RI (1.2_04) do not have this problem, I suggest the current implementation be changed. If I'm wrong, please help me understand. Otherwise, I'll submit a change request. 
> JSP contents: 
>          <h:selectOneMenu id="client" value="#{myPage.projectType}" required="true"> 
>              <f:converter converterId="x.y.ProjectTypeConverter"/> 
>              <f:selectItem itemValue="" itemLabel="--- Select Project Type---"/> 
>              <f:selectItems value="#{myPage.projectTypeList}"/> 
>          </h:selectOneMenu> 
> Where ProjectTypeConverter returns null for "" on input and myPage.projectTypeList is a list of SelectItem created in the following manner: 
>          ArrayList projectTypes = new ArrayList( projectTypeHome.findAll() ); 
>          for( int i = 0; i < projectTypes.size(); i++ ) 
>          { 
>             ProjectTypeLocal projectType = (ProjectTypeLocal)projectTypes.get( i ); 
>             m_projectTypes.add( new SelectItem( projectType, projectType.getName() ) ); 
>          } 
> Note that the SelectItem.itemValue is an EJB. 
> The intent is to force the user to select a value from the list. If no action is taken by the user, generate an error. This is directly analogous to a Tomahawk example, except the values are EJB's. 
> The problem: 
> This worked fine under MyFaces 1.1.3 and appears that it would work under RI 1.2_04. Under release 1.1.5, however, a ClassCastException occurs during the validation phase, but only if a list item is selected and the item is an EJB. 
> Analysis (based on 1.1.5 release): 
> During the validation phase, UISelectOne.validateValue is invoked with the selected EJB. This causes the following lines in _SelectItemsUtil.matchValue() to be invoked: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || value.equals(itemValue)) 
> This is fine for the SelectItem values that are EJB's, but not for "". Since EJB equality requires identity, the EJB equals() method calls isIdentical() and immediately encounters an exception casting to EJBLocalObject (code here from JBoss 4.0.4GA LocalProxy): 
>    Boolean isIdentical(final Object a, final Object b) 
>    { 
>       final EJBLocalObject ejb = (EJBLocalObject)a; 
>       Boolean isIdentical = Boolean.FALSE; 
>       if( ejb != null ) 
>       { 
>          isIdentical = new Boolean(ejb.toString().equals(b)); 
>       } 
>       return isIdentical; 
>    } 
> Possible solution: 
> In _SelectItemsUtil.matchValue() change the lines above to: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || ( itemValue != null && itemValue.equals(value))) 
> Note: The attached test files attempt to recreate the exception with a POJO rather than an EJB.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Commented: (MYFACES-1581) UISelectOne encounters exception in call to equals()

Posted by "Bob (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-1581?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12486739 ] 

Bob commented on MYFACES-1581:
------------------------------

Thanks. Just for the record, the EJB in question does not override equals() (which in itself may be a mistake). The default equals() calls isIdentical(), which gets the exception, at least in the JBoss 4.0.1 and 4.0.4 implementations. So it's something others could run into.

> UISelectOne encounters exception in call to equals()
> ----------------------------------------------------
>
>                 Key: MYFACES-1581
>                 URL: https://issues.apache.org/jira/browse/MYFACES-1581
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: General
>    Affects Versions: 1.1.5
>         Environment: Any, found using JDK 1.6, JBoss 4.0.1, Windows XP SP2
>            Reporter: Bob
>             Fix For:  1.1.6-SNAPSHOT
>
>         Attachments: _SelectItemsUtil.java.diff, faces-config.xml, MyValue.java, TestMyValues.java, testValues.jsp
>
>
> After doing a bit of research, I'm convinced a problem occurs when SelectItem.itemValue is an EJB. Given that 1.1.3 and the RI (1.2_04) do not have this problem, I suggest the current implementation be changed. If I'm wrong, please help me understand. Otherwise, I'll submit a change request. 
> JSP contents: 
>          <h:selectOneMenu id="client" value="#{myPage.projectType}" required="true"> 
>              <f:converter converterId="x.y.ProjectTypeConverter"/> 
>              <f:selectItem itemValue="" itemLabel="--- Select Project Type---"/> 
>              <f:selectItems value="#{myPage.projectTypeList}"/> 
>          </h:selectOneMenu> 
> Where ProjectTypeConverter returns null for "" on input and myPage.projectTypeList is a list of SelectItem created in the following manner: 
>          ArrayList projectTypes = new ArrayList( projectTypeHome.findAll() ); 
>          for( int i = 0; i < projectTypes.size(); i++ ) 
>          { 
>             ProjectTypeLocal projectType = (ProjectTypeLocal)projectTypes.get( i ); 
>             m_projectTypes.add( new SelectItem( projectType, projectType.getName() ) ); 
>          } 
> Note that the SelectItem.itemValue is an EJB. 
> The intent is to force the user to select a value from the list. If no action is taken by the user, generate an error. This is directly analogous to a Tomahawk example, except the values are EJB's. 
> The problem: 
> This worked fine under MyFaces 1.1.3 and appears that it would work under RI 1.2_04. Under release 1.1.5, however, a ClassCastException occurs during the validation phase, but only if a list item is selected and the item is an EJB. 
> Analysis (based on 1.1.5 release): 
> During the validation phase, UISelectOne.validateValue is invoked with the selected EJB. This causes the following lines in _SelectItemsUtil.matchValue() to be invoked: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || value.equals(itemValue)) 
> This is fine for the SelectItem values that are EJB's, but not for "". Since EJB equality requires identity, the EJB equals() method calls isIdentical() and immediately encounters an exception casting to EJBLocalObject (code here from JBoss 4.0.4GA LocalProxy): 
>    Boolean isIdentical(final Object a, final Object b) 
>    { 
>       final EJBLocalObject ejb = (EJBLocalObject)a; 
>       Boolean isIdentical = Boolean.FALSE; 
>       if( ejb != null ) 
>       { 
>          isIdentical = new Boolean(ejb.toString().equals(b)); 
>       } 
>       return isIdentical; 
>    } 
> Possible solution: 
> In _SelectItemsUtil.matchValue() change the lines above to: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || ( itemValue != null && itemValue.equals(value))) 
> Note: The attached test files attempt to recreate the exception with a POJO rather than an EJB.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (MYFACES-1581) UISelectOne encounters exception in call to equals()

Posted by "Mike Kienenberger (JIRA)" <de...@myfaces.apache.org>.
     [ https://issues.apache.org/jira/browse/MYFACES-1581?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Mike Kienenberger updated MYFACES-1581:
---------------------------------------

       Resolution: Fixed
    Fix Version/s:  1.1.6-SNAPSHOT
           Status: Resolved  (was: Patch Available)

Changed, but not really fixed.

> UISelectOne encounters exception in call to equals()
> ----------------------------------------------------
>
>                 Key: MYFACES-1581
>                 URL: https://issues.apache.org/jira/browse/MYFACES-1581
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: General
>    Affects Versions: 1.1.5
>         Environment: Any, found using JDK 1.6, JBoss 4.0.1, Windows XP SP2
>            Reporter: Bob
>             Fix For:  1.1.6-SNAPSHOT
>
>         Attachments: _SelectItemsUtil.java.diff, faces-config.xml, MyValue.java, TestMyValues.java, testValues.jsp
>
>
> After doing a bit of research, I'm convinced a problem occurs when SelectItem.itemValue is an EJB. Given that 1.1.3 and the RI (1.2_04) do not have this problem, I suggest the current implementation be changed. If I'm wrong, please help me understand. Otherwise, I'll submit a change request. 
> JSP contents: 
>          <h:selectOneMenu id="client" value="#{myPage.projectType}" required="true"> 
>              <f:converter converterId="x.y.ProjectTypeConverter"/> 
>              <f:selectItem itemValue="" itemLabel="--- Select Project Type---"/> 
>              <f:selectItems value="#{myPage.projectTypeList}"/> 
>          </h:selectOneMenu> 
> Where ProjectTypeConverter returns null for "" on input and myPage.projectTypeList is a list of SelectItem created in the following manner: 
>          ArrayList projectTypes = new ArrayList( projectTypeHome.findAll() ); 
>          for( int i = 0; i < projectTypes.size(); i++ ) 
>          { 
>             ProjectTypeLocal projectType = (ProjectTypeLocal)projectTypes.get( i ); 
>             m_projectTypes.add( new SelectItem( projectType, projectType.getName() ) ); 
>          } 
> Note that the SelectItem.itemValue is an EJB. 
> The intent is to force the user to select a value from the list. If no action is taken by the user, generate an error. This is directly analogous to a Tomahawk example, except the values are EJB's. 
> The problem: 
> This worked fine under MyFaces 1.1.3 and appears that it would work under RI 1.2_04. Under release 1.1.5, however, a ClassCastException occurs during the validation phase, but only if a list item is selected and the item is an EJB. 
> Analysis (based on 1.1.5 release): 
> During the validation phase, UISelectOne.validateValue is invoked with the selected EJB. This causes the following lines in _SelectItemsUtil.matchValue() to be invoked: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || value.equals(itemValue)) 
> This is fine for the SelectItem values that are EJB's, but not for "". Since EJB equality requires identity, the EJB equals() method calls isIdentical() and immediately encounters an exception casting to EJBLocalObject (code here from JBoss 4.0.4GA LocalProxy): 
>    Boolean isIdentical(final Object a, final Object b) 
>    { 
>       final EJBLocalObject ejb = (EJBLocalObject)a; 
>       Boolean isIdentical = Boolean.FALSE; 
>       if( ejb != null ) 
>       { 
>          isIdentical = new Boolean(ejb.toString().equals(b)); 
>       } 
>       return isIdentical; 
>    } 
> Possible solution: 
> In _SelectItemsUtil.matchValue() change the lines above to: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || ( itemValue != null && itemValue.equals(value))) 
> Note: The attached test files attempt to recreate the exception with a POJO rather than an EJB.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


[jira] Updated: (MYFACES-1581) UISelectOne encounters exception in call to equals()

Posted by "Bob (JIRA)" <de...@myfaces.apache.org>.
     [ https://issues.apache.org/jira/browse/MYFACES-1581?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Bob updated MYFACES-1581:
-------------------------

    Status: Patch Available  (was: Open)

> UISelectOne encounters exception in call to equals()
> ----------------------------------------------------
>
>                 Key: MYFACES-1581
>                 URL: https://issues.apache.org/jira/browse/MYFACES-1581
>             Project: MyFaces Core
>          Issue Type: Bug
>          Components: General
>    Affects Versions: 1.1.5
>         Environment: Any, found using JDK 1.6, JBoss 4.0.1, Windows XP SP2
>            Reporter: Bob
>         Attachments: faces-config.xml, MyValue.java, TestMyValues.java, testValues.jsp
>
>
> After doing a bit of research, I'm convinced a problem occurs when SelectItem.itemValue is an EJB. Given that 1.1.3 and the RI (1.2_04) do not have this problem, I suggest the current implementation be changed. If I'm wrong, please help me understand. Otherwise, I'll submit a change request. 
> JSP contents: 
>          <h:selectOneMenu id="client" value="#{myPage.projectType}" required="true"> 
>              <f:converter converterId="x.y.ProjectTypeConverter"/> 
>              <f:selectItem itemValue="" itemLabel="--- Select Project Type---"/> 
>              <f:selectItems value="#{myPage.projectTypeList}"/> 
>          </h:selectOneMenu> 
> Where ProjectTypeConverter returns null for "" on input and myPage.projectTypeList is a list of SelectItem created in the following manner: 
>          ArrayList projectTypes = new ArrayList( projectTypeHome.findAll() ); 
>          for( int i = 0; i < projectTypes.size(); i++ ) 
>          { 
>             ProjectTypeLocal projectType = (ProjectTypeLocal)projectTypes.get( i ); 
>             m_projectTypes.add( new SelectItem( projectType, projectType.getName() ) ); 
>          } 
> Note that the SelectItem.itemValue is an EJB. 
> The intent is to force the user to select a value from the list. If no action is taken by the user, generate an error. This is directly analogous to a Tomahawk example, except the values are EJB's. 
> The problem: 
> This worked fine under MyFaces 1.1.3 and appears that it would work under RI 1.2_04. Under release 1.1.5, however, a ClassCastException occurs during the validation phase, but only if a list item is selected and the item is an EJB. 
> Analysis (based on 1.1.5 release): 
> During the validation phase, UISelectOne.validateValue is invoked with the selected EJB. This causes the following lines in _SelectItemsUtil.matchValue() to be invoked: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || value.equals(itemValue)) 
> This is fine for the SelectItem values that are EJB's, but not for "". Since EJB equality requires identity, the EJB equals() method calls isIdentical() and immediately encounters an exception casting to EJBLocalObject (code here from JBoss 4.0.4GA LocalProxy): 
>    Boolean isIdentical(final Object a, final Object b) 
>    { 
>       final EJBLocalObject ejb = (EJBLocalObject)a; 
>       Boolean isIdentical = Boolean.FALSE; 
>       if( ejb != null ) 
>       { 
>          isIdentical = new Boolean(ejb.toString().equals(b)); 
>       } 
>       return isIdentical; 
>    } 
> Possible solution: 
> In _SelectItemsUtil.matchValue() change the lines above to: 
>                 [item is class SelectItem] 
>                 Object itemValue = item.getValue(); 
>                 if (value==itemValue || ( itemValue != null && itemValue.equals(value))) 
> Note: The attached test files attempt to recreate the exception with a POJO rather than an EJB.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.