I agree this does not fix the case where equals() has been implemented
incorrectly, nor should it. But it reduces the likelihood of an exception
for EJB's. The default equals() calls isIdentical(), which gets the
exception, at least in the JBoss 4.0.1 and 4.0.4 implementations. But thanks
for the fix.

Mike Kienenberger wrote:
> 
> Yes, I finally figured that out.
> 
> Unfortunately, it does mean the equality method on the object is
> incorrect since equals() requires symmetric-ness.
> 
> http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#equals(java.lang.Object)
> ==================
> It is symmetric: for any non-null reference values x and y,
> x.equals(y)  should return true if and only if y.equals(x) returns
> true.
> ==================
> 
> Even if I committed this change, it still wouldn't work in all cases.
>  As soon as two different  classes with broken equals()
> implementations were involved, you'd get the same error.   All it's
> doing is counting on the fact that String.equals() is written
> correctly and that you're only mixing MyObject classes and String
> classes.
> 
> On 4/4/07, fastbob <[EMAIL PROTECTED]> wrote:
>>
>> Sorry I wasn't clear. The null check is incidental, and can be eliminated
>> if
>> any of the itemValues can never be null. The key change is the object
>> order
>> of the second clause, relying on equality being symmetric. Originally it
>> was
>> "value.equals(itemValue)"; now it is "itemValue.equals(value)". So when
>> itemValue is the empty string, String equals() will be invoked, rather
>> than
>> EJB equals. The String equals() will return false, not an exception.
>>
>> Mike Kienenberger wrote:
>> >
>> > I'm not seeing how this will fix the problem.   In the test case you
>> > posted, the value is not null -- it's empty string.  So checking
>> > against null won't change the behavior.   The ClassCastException will
>> > still occur.
>> >
>> >
>> > On 4/3/07, fastbob <[EMAIL PROTECTED]> wrote:
>> >>
>> >> After doing a bit of research, I'm convinced the problem only 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:
>> >> Iin _SelectItemsUtil.matchValue() change the lines above to:
>> >>
>> >>                 [item is class SelectItem]
>> >>                 Object itemValue = item.getValue();
>> >>                 if (value==itemValue || ( itemValue != null &&
>> >> itemValue.equals(value)))
>> >>
>> >>
>> >>
>> >>
>> >> fastbob wrote:
>> >> >
>> >> > Usually the selectItem values are EJB's, but in a couple of
>> instances
>> >> they
>> >> > strings that just happen to be the serialized form of the EJB. The
>> >> > prototypical code looks like:
>> >> >
>> >> >          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() ) );
>> >> >          }
>> >> >
>> >> > What this means is when we get to the following lines in
>> >> _SelectItemsUtil,
>> >> > the equals() method of the EJB is called with the empty ("") string
>> (in
>> >> > 1.1.5):
>> >> >
>> >> >                  [item is class SelectItem]
>> >> >                  Object itemValue = item.getValue();
>> >> >                  if (value==itemValue || value.equals(itemValue))
>> >> >
>> >> > It appears that the 1.1.3 code handled the case of any String being
>> >> > passed. Since our converters look for an empty string, this results
>> in
>> >> the
>> >> > EJB equals() being passed null:
>> >> >
>> >> >                 Object itemValue = item.getValue();
>> >> >                 if(converter != null && itemValue instanceof String)
>> >> >                 {
>> >> >                     itemValue = converter.getConvertedValue(context,
>> >> > (String)itemValue);
>> >> >                 }
>> >> >                 if (value==itemValue || value.equals(itemValue))
>> >> >
>> >> > But I guess this circles back to non-standard conversion that was
>> taken
>> >> > out.
>> >> >
>> >> > I'm pretty ignorant of all the JSF lifecycle semantics, but since
>> this
>> >> > practice is always used with required="true", would an earlier check
>> >> for a
>> >> > non-null, non-empty string fix this?
>> >> >
>> >> > I'm open to suggestions.
>> >> >
>> >> >
>> >> > Mike Kienenberger wrote:
>> >> >>
>> >> >> Yes, I think you're right.  It's not the form String -> Object
>> that's
>> >> >> causing the issue.
>> >> >> It looks like it's the contents of the selectItem values.  What are
>> >> >> you initializing the selectItem value fields with?
>> >> >>
>> >> >> What's the contents of selectItem.value when it's of type String?
>> >> >>
>> >> >>
>> >> >
>> >> >
>> >>
>> >> --
>> >> View this message in context:
>> >>
>> http://www.nabble.com/ERROR%3A-Value-is-not-a-valid-option-tf3270984.html#a9826625
>> >> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>> >>
>> >>
>> >
>> >
>>
>> --
>> View this message in context:
>> http://www.nabble.com/ERROR%3A-Value-is-not-a-valid-option-tf3270984.html#a9841526
>> Sent from the MyFaces - Users mailing list archive at Nabble.com.
>>
>>
> 
> 

-- 
View this message in context: 
http://www.nabble.com/ERROR%3A-Value-is-not-a-valid-option-tf3270984.html#a9843207
Sent from the MyFaces - Users mailing list archive at Nabble.com.

Reply via email to