You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Erlend Hamnaberg <er...@underdusken.no> on 2007/07/10 18:45:44 UTC

JSF and converters, possible bug in myfaces and RI

Hello.

Last time i posted i didnt get much response from this question.

I have even changed to the JSF RI and the same error occurs.

Some background:

I have provided a converter for a class Alternative.
The class Alternative is a Serializable object generated by JaxB.

The generated class:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {

})
@XmlRootElement(name = "alternative", namespace = "http://evatest.org/xml")
public class Alternative
    implements Serializable
{

    private final static long serialVersionUID = 123L;
    @XmlElement(namespace = "http://evatest.org/xml")
    protected ResourceType resource;
    @XmlElement(namespace = "http://evatest.org/xml", required = true)
    protected String text;
    @XmlAttribute
    protected Integer certainty;
    @XmlAttribute(required = true)
    protected int id;
    @XmlAttribute
    protected Double points;
    @XmlAttribute
    protected Integer weight;

    /**
     * Gets the value of the resource property.
     *
     * @return
     *     possible object is
     *     {@link ResourceType }
     *    
     */
    public ResourceType getResource() {
        return resource;
    }

    /**
     * Sets the value of the resource property.
     *
     * @param value
     *     allowed object is
     *     {@link ResourceType }
     *    
     */
    public void setResource(ResourceType value) {
        this.resource = value;
    }

    /**
     * Gets the value of the text property.
     *
     * @return
     *     possible object is
     *     {@link String }
     *    
     */
    public String getText() {
        return text;
    }

    /**
     * Sets the value of the text property.
     *
     * @param value
     *     allowed object is
     *     {@link String }
     *    
     */
    public void setText(String value) {
        this.text = value;
    }

    /**
     * Gets the value of the certainty property.
     *
     * @return
     *     possible object is
     *     {@link Integer }
     *    
     */
    public int getCertainty() {
        if (certainty == null) {
            return  0;
        } else {
            return certainty;
        }
    }

    /**
     * Sets the value of the certainty property.
     *
     * @param value
     *     allowed object is
     *     {@link Integer }
     *    
     */
    public void setCertainty(Integer value) {
        this.certainty = value;
    }

    /**
     * Gets the value of the id property.
     *
     */
    public int getId() {
        return id;
    }

    /**
     * Sets the value of the id property.
     *
     */
    public void setId(int value) {
        this.id = value;
    }

    /**
     * Gets the value of the points property.
     *
     * @return
     *     possible object is
     *     {@link Double }
     *    
     */
    public double getPoints() {
        if (points == null) {
            return  0.0D;
        } else {
            return points;
        }
    }

    /**
     * Sets the value of the points property.
     *
     * @param value
     *     allowed object is
     *     {@link Double }
     *    
     */
    public void setPoints(Double value) {
        this.points = value;
    }

    /**
     * Gets the value of the weight property.
     *
     * @return
     *     possible object is
     *     {@link Integer }
     *    
     */
    public int getWeight() {
        if (weight == null) {
            return  0;
        } else {
            return weight;
        }
    }

    /**
     * Sets the value of the weight property.
     *
     * @param value
     *     allowed object is
     *     {@link Integer }
     *    
     */
    public void setWeight(Integer value) {
        this.weight = value;
    }

}


this is like this:


public class AlternativeConverter implements Converter {
    private Log log = LogFactory.getLog(getClass());

    public Object getAsObject(FacesContext facesContext, UIComponent 
uiComponent, String string) throws ConverterException {
        if (string == null) return null;
        Alternative a = new Alternative();
        log.debug(string);
        String[] splitted = string.split(";");
        a.setId(Integer.parseInt(splitted[0]));         // id
        a.setText(splitted[1]);                         // text
        a.setWeight(Integer.parseInt(splitted[2]));     // weight
        a.setCertainty(Integer.parseInt(splitted[3]));  // certainty
        log.debug(a.getId() + " " + a.getText() + " " + 
a.getWeight());                                   // resource ?
        return a;
    }

    public String getAsString(FacesContext facesContext, UIComponent 
uiComponent, Object object) throws ConverterException {
        if (object == null || !(object instanceof Alternative)) return null;

        Alternative a = (Alternative) object;
        return String.valueOf(a.getId()) + ";" + a.getText() + ";" + 
a.getWeight() + ";" + a.getCertainty();
    }
}

The converter is registered within faces-context as converter-for-class
I have then created a very basic unit test that verifies that values get 
converted.

Provided here:


public class TestAlternativeConverter extends TestCase {

    private AlternativeConverter alternativeConverter = new 
AlternativeConverter();

   
    public TestAlternativeConverter(String string) {
        super(string);
    }

    @Test
    public void testGetAsObject(){
        String alt = "1;Green;0;100";
        Alternative a = (Alternative) 
alternativeConverter.getAsObject(null, null, alt);
        assertEquals(a.getId(), 1);
    }

    @Test
    public void testGetAsString(){
          Alternative a = new Alternative();
          a.setId(1);
          a.setPoints(2.0);
          a.setCertainty(100);
          a.setText("Green");
          String res = alternativeConverter.getAsString(null, null, a);
          assertEquals("1;Green;0;100", res);
    }
}

I then populate a very simple backing bean with this:

public class TheTestBean {
    private Alternative alternative = new Alternative();
    private Log log = LogFactory.getLog(getClass());

    public Alternative getAlternative() {
        return alternative;
    }



    public void setAlternative(Alternative alternative) {
        this.alternative = alternative;
    }

    public List<SelectItem> getAlternatives() {
        List<SelectItem> list = new LinkedList<SelectItem>();
        for (int i = 1; i < 11; i++) {
            Alternative a = new Alternative();
            a.setId(i);
            a.setText("Text " + i);
            list.add(new SelectItem(a,a.getText()));
        }
        return list;
    }

    public String doSubmit() {
        log.debug(alternative);
        return "ok";
    }
}


  <h:form>
        <h:selectOneRadio id="radiobuttonlist"
                          layout="pageDirection"
                          value="#{theTestBean.alternative}">



            <f:selectItems value="#{theTestBean.alternatives}"/>
        </h:selectOneRadio>
        <t:commandButton value="Submit" action="#{theTestBean.doSubmit}"/>
        </h:form>


The following happens.... Nothing. Validation fails, and there are none 
validators assosiated with the component.

Debug output, from sun ri, the same happens with myfaces, however i 
found that the debug from ri was more helpful.

2007-07-10 18:29:43,910 [btpool0-4] DEBUG 
com.sun.faces.application.StateManagerImpl - Begin creating serialized 
view for /test.xhtml
2007-07-10 18:29:43,910 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@1a6a3c3
2007-07-10 18:29:43,910 [btpool0-4] DEBUG 
com.sun.faces.application.StateManagerImpl - End creating serialized 
view /test.xhtml
2007-07-10 18:29:43,910 [btpool0-4] DEBUG 
com.sun.faces.renderkit.ResponseStateManagerImpl - Compressing state 
before saving..
2007-07-10 18:29:43,927 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RenderResponsePhase - Exiting RenderResponsePhase
2007-07-10 18:29:43,928 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@1a6a3c3
2007-07-10 18:29:47,147 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.LifecycleImpl - 
execute(com.sun.faces.context.FacesContextImpl@139ca7e)
2007-07-10 18:29:47,147 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RestoreViewPhase - Entering RestoreViewPhase
2007-07-10 18:29:47,147 [btpool0-4] DEBUG 
com.sun.faces.application.ViewHandlerImpl - URL pattern of the 
FacesServlet executing the current request .html
2007-07-10 18:29:47,147 [btpool0-4] DEBUG 
com.sun.faces.application.ViewHandlerImpl - viewId after appending the 
context suffix /test.xhtml
2007-07-10 18:29:47,148 [btpool0-4] DEBUG 
com.sun.faces.application.StateManagerImpl - Begin restoring view from 
response /test.xhtml
2007-07-10 18:29:47,150 [btpool0-4] DEBUG 
com.sun.faces.renderkit.ResponseStateManagerImpl - Deflating state 
before restoring..
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.application.StateManagerImpl - End restoring view from 
response /test.xhtml
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RestoreViewPhase - Postback: Restored view for 
/test.html
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RestoreViewPhase - Exiting RestoreViewPhase
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.application.ApplicationImpl - Couldn't find a factory for 
ajaxContext
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:null
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.ApplyRequestValuesPhase - Entering 
ApplyRequestValuesPhase
2007-07-10 18:29:47,161 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,162 [btpool0-4] DEBUG 
com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer - Set 
submitted value 4;Text 4;0;0 on component
2007-07-10 18:29:47,162 [btpool0-4] DEBUG 
com.sun.faces.renderkit.html_basic.ButtonRenderer - This command 
resulted in form submission  ActionEvent queued 
javax.faces.event.ActionEvent[source=org.apache.myfaces.component.html.ext.HtmlCommandButton@1718057]
2007-07-10 18:29:47,162 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.ApplyRequestValuesPhase - Exiting 
ApplyRequestValuesPhase
2007-07-10 18:29:47,162 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,162 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.ProcessValidationsPhase - Entering 
ProcessValidationsPhase
2007-07-10 18:29:47,162 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
com.sun.faces.application.ApplicationImpl - Created bean theTestBean 
successfully
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.evatest.web.beans.TheTestBean@a0eb2a
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer - Created 
converter org.evatest.web.converter.AlternativeConverter@af2a50of type 
class org.evatest.xml.Alternative while decoding component radiobuttonlist
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
org.evatest.web.converter.AlternativeConverter - 4;Text 4;0;0
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
org.evatest.web.converter.AlternativeConverter - 4 Text 4 0
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.evatest.web.beans.TheTestBean@a0eb2a
2007-07-10 18:29:47,163 [btpool0-4] DEBUG 
com.sun.faces.context.FacesContextImpl - Adding 
Message[sourceId=_id35:radiobuttonlist,summary=Validation Error: Value 
is not valid)
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.ProcessValidationsPhase - Exiting 
ProcessValidationsPhase
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.LifecycleImpl - 
render(com.sun.faces.context.FacesContextImpl@139ca7e)
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RenderResponsePhase - Entering RenderResponsePhase
2007-07-10 18:29:47,164 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,169 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RenderResponsePhase - About to render view 
/test.xhtml
2007-07-10 18:29:47,169 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,169 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,169 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,169 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,173 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,175 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,175 [btpool0-4] DEBUG 
com.sun.faces.application.ViewHandlerImpl - URL pattern of the 
FacesServlet executing the current request .html
2007-07-10 18:29:47,179 [btpool0-4] DEBUG 
com.sun.faces.application.ApplicationImpl - Couldn't find a factory for 
visit
2007-07-10 18:29:47,179 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:null
2007-07-10 18:29:47,179 [btpool0-4] DEBUG 
com.sun.faces.application.ApplicationImpl - Couldn't find a factory for 
visit
2007-07-10 18:29:47,179 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:null
2007-07-10 18:29:47,179 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,179 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,180 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,180 [btpool0-4] DEBUG 
com.sun.faces.application.ViewHandlerImpl - URL pattern of the 
FacesServlet executing the current request .html
2007-07-10 18:29:47,180 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.evatest.web.beans.TheTestBean@a0eb2a
2007-07-10 18:29:47,183 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,183 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,184 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,184 [btpool0-4] DEBUG 
com.sun.faces.application.StateManagerImpl - Begin creating serialized 
view for /test.xhtml
2007-07-10 18:29:47,184 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
2007-07-10 18:29:47,184 [btpool0-4] DEBUG 
com.sun.faces.application.StateManagerImpl - End creating serialized 
view /test.xhtml
2007-07-10 18:29:47,184 [btpool0-4] DEBUG 
com.sun.faces.renderkit.ResponseStateManagerImpl - Compressing state 
before saving..
2007-07-10 18:29:47,192 [btpool0-4] DEBUG 
com.sun.faces.lifecycle.RenderResponsePhase - Exiting RenderResponsePhase
2007-07-10 18:29:47,192 [btpool0-4] DEBUG 
com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved 
variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d



The funny thing is, when i change the converter to using any of my JPA 
model objects the conversion works, and the validation errors does not 
occur.

Any idea why this is happening? Can it be because of Jaxb ? in that 
case, how.


Regards

Erlend Hamnaberg
Lead Developer Evatest


Re: JSF and converters, possible bug in myfaces and RI

Posted by Erlend Hamnaberg <er...@underdusken.no>.
David Delbecq wrote:
> Hello,
>
> Logs from JSF -RI clearly show that converter was used to convert
> submitted string to an Alternative object. The error state that this
> converted value is not equal to any of the available SeletItem Value.
> This is obviously caused by your Alternative class not properly
> implements the equals() method. As such, it falls back to
> Object.equals() which only compare instances identifiers. And because
> the result of your converter and the result of your getAlternative()
> both return new items, equals() between them returns false.
> The reason it works if your cange model is maybe that the model used
> implement properly equals() or the backing framework you use (i don't
> know JaxB) ensure there is only 1 instance of a given Alternative with a
> give Id.
>
> So, solution
> implement the equals method.
>
> reference:
> javax.faces.component._SelectItemsUtil, method public static boolean
> matchValue(Object value, Iterator selectItemsIter)
>
> while (selectItemsIter.hasNext())
>         {
>             SelectItem item = (SelectItem) selectItemsIter.next();
>             if (item instanceof SelectItemGroup)
>             {
>                 /..../
>             }
>             else
>             {
>                 Object itemValue = item.getValue();
>                 if (value==itemValue || (itemValue.equals(value)))
>                 {
>                     return true;
>                 }
>             }
> En l'instant précis du 10/07/07 21:40, Erlend Hamnaberg s'exprimait en
> ces termes:
>   
>> Matthias Wessendorf wrote:
>>     
>>> are you sure
>>>
>>> for-class register "Alternative" is same than JaxB ?
>>>
>>> full qualified class name ?
>>>       
>> Of course fully qualified.
>> The classname in question is org.evatest.xml.Alternative.
>>
>> The behavior doesn't change weather i use this method or explicitly
>> define a converter-id.
>>     
>>> On 7/10/07, Erlend Hamnaberg <er...@underdusken.no> wrote:
>>>       
>>>> Hello.
>>>>
>>>> Last time i posted i didnt get much response from this questi
>>>>         
>
>
>   

Ah, obviously.

Incredible that I missed that...
Sorry for my lame questions.

-- 
Erlend Hamnaberg



Re: JSF and converters, possible bug in myfaces and RI

Posted by David Delbecq <de...@oma.be>.
Hello,

Logs from JSF -RI clearly show that converter was used to convert
submitted string to an Alternative object. The error state that this
converted value is not equal to any of the available SeletItem Value.
This is obviously caused by your Alternative class not properly
implements the equals() method. As such, it falls back to
Object.equals() which only compare instances identifiers. And because
the result of your converter and the result of your getAlternative()
both return new items, equals() between them returns false.
The reason it works if your cange model is maybe that the model used
implement properly equals() or the backing framework you use (i don't
know JaxB) ensure there is only 1 instance of a given Alternative with a
give Id.

So, solution
implement the equals method.

reference:
javax.faces.component._SelectItemsUtil, method public static boolean
matchValue(Object value, Iterator selectItemsIter)

while (selectItemsIter.hasNext())
        {
            SelectItem item = (SelectItem) selectItemsIter.next();
            if (item instanceof SelectItemGroup)
            {
                /..../
            }
            else
            {
                Object itemValue = item.getValue();
                if (value==itemValue || (itemValue.equals(value)))
                {
                    return true;
                }
            }
En l'instant précis du 10/07/07 21:40, Erlend Hamnaberg s'exprimait en
ces termes:
> Matthias Wessendorf wrote:
>> are you sure
>>
>> for-class register "Alternative" is same than JaxB ?
>>
>> full qualified class name ?
> Of course fully qualified.
> The classname in question is org.evatest.xml.Alternative.
>
> The behavior doesn't change weather i use this method or explicitly
> define a converter-id.
>>
>> On 7/10/07, Erlend Hamnaberg <er...@underdusken.no> wrote:
>>> Hello.
>>>
>>> Last time i posted i didnt get much response from this questi
>>


Re: JSF and converters, possible bug in myfaces and RI

Posted by Erlend Hamnaberg <er...@underdusken.no>.
Matthias Wessendorf wrote:
> are you sure
>
> for-class register "Alternative" is same than JaxB ?
>
> full qualified class name ?
Of course fully qualified.
The classname in question is org.evatest.xml.Alternative.

The behavior doesn't change weather i use this method or explicitly 
define a converter-id.
>
> On 7/10/07, Erlend Hamnaberg <er...@underdusken.no> wrote:
>> Hello.
>>
>> Last time i posted i didnt get much response from this questi
>


Re: JSF and converters, possible bug in myfaces and RI

Posted by Matthias Wessendorf <ma...@apache.org>.
are you sure

for-class register "Alternative" is same than JaxB ?

full qualified class name ?

On 7/10/07, Erlend Hamnaberg <er...@underdusken.no> wrote:
> Hello.
>
> Last time i posted i didnt get much response from this question.
>
> I have even changed to the JSF RI and the same error occurs.
>
> Some background:
>
> I have provided a converter for a class Alternative.
> The class Alternative is a Serializable object generated by JaxB.
>
> The generated class:
>
> @XmlAccessorType(XmlAccessType.FIELD)
> @XmlType(name = "", propOrder = {
>
> })
> @XmlRootElement(name = "alternative", namespace = "http://evatest.org/xml")
> public class Alternative
>     implements Serializable
> {
>
>     private final static long serialVersionUID = 123L;
>     @XmlElement(namespace = "http://evatest.org/xml")
>     protected ResourceType resource;
>     @XmlElement(namespace = "http://evatest.org/xml", required = true)
>     protected String text;
>     @XmlAttribute
>     protected Integer certainty;
>     @XmlAttribute(required = true)
>     protected int id;
>     @XmlAttribute
>     protected Double points;
>     @XmlAttribute
>     protected Integer weight;
>
>     /**
>      * Gets the value of the resource property.
>      *
>      * @return
>      *     possible object is
>      *     {@link ResourceType }
>      *
>      */
>     public ResourceType getResource() {
>         return resource;
>     }
>
>     /**
>      * Sets the value of the resource property.
>      *
>      * @param value
>      *     allowed object is
>      *     {@link ResourceType }
>      *
>      */
>     public void setResource(ResourceType value) {
>         this.resource = value;
>     }
>
>     /**
>      * Gets the value of the text property.
>      *
>      * @return
>      *     possible object is
>      *     {@link String }
>      *
>      */
>     public String getText() {
>         return text;
>     }
>
>     /**
>      * Sets the value of the text property.
>      *
>      * @param value
>      *     allowed object is
>      *     {@link String }
>      *
>      */
>     public void setText(String value) {
>         this.text = value;
>     }
>
>     /**
>      * Gets the value of the certainty property.
>      *
>      * @return
>      *     possible object is
>      *     {@link Integer }
>      *
>      */
>     public int getCertainty() {
>         if (certainty == null) {
>             return  0;
>         } else {
>             return certainty;
>         }
>     }
>
>     /**
>      * Sets the value of the certainty property.
>      *
>      * @param value
>      *     allowed object is
>      *     {@link Integer }
>      *
>      */
>     public void setCertainty(Integer value) {
>         this.certainty = value;
>     }
>
>     /**
>      * Gets the value of the id property.
>      *
>      */
>     public int getId() {
>         return id;
>     }
>
>     /**
>      * Sets the value of the id property.
>      *
>      */
>     public void setId(int value) {
>         this.id = value;
>     }
>
>     /**
>      * Gets the value of the points property.
>      *
>      * @return
>      *     possible object is
>      *     {@link Double }
>      *
>      */
>     public double getPoints() {
>         if (points == null) {
>             return  0.0D;
>         } else {
>             return points;
>         }
>     }
>
>     /**
>      * Sets the value of the points property.
>      *
>      * @param value
>      *     allowed object is
>      *     {@link Double }
>      *
>      */
>     public void setPoints(Double value) {
>         this.points = value;
>     }
>
>     /**
>      * Gets the value of the weight property.
>      *
>      * @return
>      *     possible object is
>      *     {@link Integer }
>      *
>      */
>     public int getWeight() {
>         if (weight == null) {
>             return  0;
>         } else {
>             return weight;
>         }
>     }
>
>     /**
>      * Sets the value of the weight property.
>      *
>      * @param value
>      *     allowed object is
>      *     {@link Integer }
>      *
>      */
>     public void setWeight(Integer value) {
>         this.weight = value;
>     }
>
> }
>
>
> this is like this:
>
>
> public class AlternativeConverter implements Converter {
>     private Log log = LogFactory.getLog(getClass());
>
>     public Object getAsObject(FacesContext facesContext, UIComponent
> uiComponent, String string) throws ConverterException {
>         if (string == null) return null;
>         Alternative a = new Alternative();
>         log.debug(string);
>         String[] splitted = string.split(";");
>         a.setId(Integer.parseInt(splitted[0]));         // id
>         a.setText(splitted[1]);                         // text
>         a.setWeight(Integer.parseInt(splitted[2]));     // weight
>         a.setCertainty(Integer.parseInt(splitted[3]));  // certainty
>         log.debug(a.getId() + " " + a.getText() + " " +
> a.getWeight());                                   // resource ?
>         return a;
>     }
>
>     public String getAsString(FacesContext facesContext, UIComponent
> uiComponent, Object object) throws ConverterException {
>         if (object == null || !(object instanceof Alternative)) return null;
>
>         Alternative a = (Alternative) object;
>         return String.valueOf(a.getId()) + ";" + a.getText() + ";" +
> a.getWeight() + ";" + a.getCertainty();
>     }
> }
>
> The converter is registered within faces-context as converter-for-class
> I have then created a very basic unit test that verifies that values get
> converted.
>
> Provided here:
>
>
> public class TestAlternativeConverter extends TestCase {
>
>     private AlternativeConverter alternativeConverter = new
> AlternativeConverter();
>
>
>     public TestAlternativeConverter(String string) {
>         super(string);
>     }
>
>     @Test
>     public void testGetAsObject(){
>         String alt = "1;Green;0;100";
>         Alternative a = (Alternative)
> alternativeConverter.getAsObject(null, null, alt);
>         assertEquals(a.getId(), 1);
>     }
>
>     @Test
>     public void testGetAsString(){
>           Alternative a = new Alternative();
>           a.setId(1);
>           a.setPoints(2.0);
>           a.setCertainty(100);
>           a.setText("Green");
>           String res = alternativeConverter.getAsString(null, null, a);
>           assertEquals("1;Green;0;100", res);
>     }
> }
>
> I then populate a very simple backing bean with this:
>
> public class TheTestBean {
>     private Alternative alternative = new Alternative();
>     private Log log = LogFactory.getLog(getClass());
>
>     public Alternative getAlternative() {
>         return alternative;
>     }
>
>
>
>     public void setAlternative(Alternative alternative) {
>         this.alternative = alternative;
>     }
>
>     public List<SelectItem> getAlternatives() {
>         List<SelectItem> list = new LinkedList<SelectItem>();
>         for (int i = 1; i < 11; i++) {
>             Alternative a = new Alternative();
>             a.setId(i);
>             a.setText("Text " + i);
>             list.add(new SelectItem(a,a.getText()));
>         }
>         return list;
>     }
>
>     public String doSubmit() {
>         log.debug(alternative);
>         return "ok";
>     }
> }
>
>
>   <h:form>
>         <h:selectOneRadio id="radiobuttonlist"
>                           layout="pageDirection"
>                           value="#{theTestBean.alternative}">
>
>
>
>             <f:selectItems value="#{theTestBean.alternatives}"/>
>         </h:selectOneRadio>
>         <t:commandButton value="Submit" action="#{theTestBean.doSubmit}"/>
>         </h:form>
>
>
> The following happens.... Nothing. Validation fails, and there are none
> validators assosiated with the component.
>
> Debug output, from sun ri, the same happens with myfaces, however i
> found that the debug from ri was more helpful.
>
> 2007-07-10 18:29:43,910 [btpool0-4] DEBUG
> com.sun.faces.application.StateManagerImpl - Begin creating serialized
> view for /test.xhtml
> 2007-07-10 18:29:43,910 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@1a6a3c3
> 2007-07-10 18:29:43,910 [btpool0-4] DEBUG
> com.sun.faces.application.StateManagerImpl - End creating serialized
> view /test.xhtml
> 2007-07-10 18:29:43,910 [btpool0-4] DEBUG
> com.sun.faces.renderkit.ResponseStateManagerImpl - Compressing state
> before saving..
> 2007-07-10 18:29:43,927 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RenderResponsePhase - Exiting RenderResponsePhase
> 2007-07-10 18:29:43,928 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@1a6a3c3
> 2007-07-10 18:29:47,147 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.LifecycleImpl -
> execute(com.sun.faces.context.FacesContextImpl@139ca7e)
> 2007-07-10 18:29:47,147 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RestoreViewPhase - Entering RestoreViewPhase
> 2007-07-10 18:29:47,147 [btpool0-4] DEBUG
> com.sun.faces.application.ViewHandlerImpl - URL pattern of the
> FacesServlet executing the current request .html
> 2007-07-10 18:29:47,147 [btpool0-4] DEBUG
> com.sun.faces.application.ViewHandlerImpl - viewId after appending the
> context suffix /test.xhtml
> 2007-07-10 18:29:47,148 [btpool0-4] DEBUG
> com.sun.faces.application.StateManagerImpl - Begin restoring view from
> response /test.xhtml
> 2007-07-10 18:29:47,150 [btpool0-4] DEBUG
> com.sun.faces.renderkit.ResponseStateManagerImpl - Deflating state
> before restoring..
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.application.StateManagerImpl - End restoring view from
> response /test.xhtml
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RestoreViewPhase - Postback: Restored view for
> /test.html
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RestoreViewPhase - Exiting RestoreViewPhase
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.application.ApplicationImpl - Couldn't find a factory for
> ajaxContext
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:null
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.ApplyRequestValuesPhase - Entering
> ApplyRequestValuesPhase
> 2007-07-10 18:29:47,161 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,162 [btpool0-4] DEBUG
> com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer - Set
> submitted value 4;Text 4;0;0 on component
> 2007-07-10 18:29:47,162 [btpool0-4] DEBUG
> com.sun.faces.renderkit.html_basic.ButtonRenderer - This command
> resulted in form submission  ActionEvent queued
> javax.faces.event.ActionEvent[source=org.apache.myfaces.component.html.ext.HtmlCommandButton@1718057]
> 2007-07-10 18:29:47,162 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.ApplyRequestValuesPhase - Exiting
> ApplyRequestValuesPhase
> 2007-07-10 18:29:47,162 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,162 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.ProcessValidationsPhase - Entering
> ProcessValidationsPhase
> 2007-07-10 18:29:47,162 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> com.sun.faces.application.ApplicationImpl - Created bean theTestBean
> successfully
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.evatest.web.beans.TheTestBean@a0eb2a
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer - Created
> converter org.evatest.web.converter.AlternativeConverter@af2a50of type
> class org.evatest.xml.Alternative while decoding component radiobuttonlist
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> org.evatest.web.converter.AlternativeConverter - 4;Text 4;0;0
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> org.evatest.web.converter.AlternativeConverter - 4 Text 4 0
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.evatest.web.beans.TheTestBean@a0eb2a
> 2007-07-10 18:29:47,163 [btpool0-4] DEBUG
> com.sun.faces.context.FacesContextImpl - Adding
> Message[sourceId=_id35:radiobuttonlist,summary=Validation Error: Value
> is not valid)
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.ProcessValidationsPhase - Exiting
> ProcessValidationsPhase
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.LifecycleImpl -
> render(com.sun.faces.context.FacesContextImpl@139ca7e)
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RenderResponsePhase - Entering RenderResponsePhase
> 2007-07-10 18:29:47,164 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,169 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RenderResponsePhase - About to render view
> /test.xhtml
> 2007-07-10 18:29:47,169 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,169 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,169 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,169 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,173 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,175 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,175 [btpool0-4] DEBUG
> com.sun.faces.application.ViewHandlerImpl - URL pattern of the
> FacesServlet executing the current request .html
> 2007-07-10 18:29:47,179 [btpool0-4] DEBUG
> com.sun.faces.application.ApplicationImpl - Couldn't find a factory for
> visit
> 2007-07-10 18:29:47,179 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:null
> 2007-07-10 18:29:47,179 [btpool0-4] DEBUG
> com.sun.faces.application.ApplicationImpl - Couldn't find a factory for
> visit
> 2007-07-10 18:29:47,179 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:null
> 2007-07-10 18:29:47,179 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,179 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,180 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,180 [btpool0-4] DEBUG
> com.sun.faces.application.ViewHandlerImpl - URL pattern of the
> FacesServlet executing the current request .html
> 2007-07-10 18:29:47,180 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.evatest.web.beans.TheTestBean@a0eb2a
> 2007-07-10 18:29:47,183 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,183 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,184 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,184 [btpool0-4] DEBUG
> com.sun.faces.application.StateManagerImpl - Begin creating serialized
> view for /test.xhtml
> 2007-07-10 18:29:47,184 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
> 2007-07-10 18:29:47,184 [btpool0-4] DEBUG
> com.sun.faces.application.StateManagerImpl - End creating serialized
> view /test.xhtml
> 2007-07-10 18:29:47,184 [btpool0-4] DEBUG
> com.sun.faces.renderkit.ResponseStateManagerImpl - Compressing state
> before saving..
> 2007-07-10 18:29:47,192 [btpool0-4] DEBUG
> com.sun.faces.lifecycle.RenderResponsePhase - Exiting RenderResponsePhase
> 2007-07-10 18:29:47,192 [btpool0-4] DEBUG
> com.sun.faces.el.VariableResolverImpl - resolveVariable: Resolved
> variable:org.ajax4jsf.framework.ajax.AjaxContext@19c123d
>
>
>
> The funny thing is, when i change the converter to using any of my JPA
> model objects the conversion works, and the validation errors does not
> occur.
>
> Any idea why this is happening? Can it be because of Jaxb ? in that
> case, how.
>
>
> Regards
>
> Erlend Hamnaberg
> Lead Developer Evatest
>
>


-- 
Matthias Wessendorf

further stuff:
blog: http://matthiaswessendorf.wordpress.com/
mail: matzew-at-apache-dot-org