JSF验证错误:值无效[重复]

时间:2020-12-30 20:03:02

This question already has an answer here:

这个问题在这里已有答案:

I know this seems to be a common one, but I'm lost with it. Occurs on clicking the Add button in assessment.jsf. Anyway, I've attached what I think are the relevant sections.

我知道这似乎是一个普通的,但我迷失了它。单击assessment.jsf中的“添加”按钮时发生。无论如何,我已经附上了我认为相关的部分。

FWIW, AssessmentType.equals() isn't triggered when I debug.

我调试时没有触发FWIW,AssessmentType.equals()。

Thanks in advance.

提前致谢。

j_idt38:j_idt47:j_idt48: Validation Error: Value is not valid

assessment.xhtml:

assessment.xhtml:

        <h:form>
            <h:selectOneMenu value="#{assessmentBean.assessmentField}">
                <f:selectItems value="#{assessmentBean.assessment.type.fields}" />
            </h:selectOneMenu>

            <h:commandButton value="Add" action="#{assessmentBean.doAddField}">
                <f:param name="assessmentId"
                    value="#{assessmentBean.assessment.id}" />
            </h:commandButton>
        </h:form>

assessment.jsf:

assessment.jsf:

<form id="j_idt38:j_idt47" name="j_idt38:j_idt47" method="post" action="/jsf-web/edit/assessment.jsf" enctype="application/x-www-form-urlencoded"> 
<input type="hidden" name="j_idt38:j_idt47" value="j_idt38:j_idt47" /> 
<select name="j_idt38:j_idt47:j_idt48" size="1">    <option value="1">Presenting Condition</option> 
    <option value="2">Problem Duration</option> 
</select> 
<script type="text/javascript" src="/jsf-web/javax.faces.resource/jsf.js.jsf?ln=javax.faces"></script>
<input type="submit" name="j_idt38:j_idt47:j_idt50" value="Add" onclick="mojarra.jsfcljs(document.getElementById('j_idt38:j_idt47'),{'j_idt38:j_idt47:j_idt50':'j_idt38:j_idt47:j_idt50','assessmentId':'1'},'');return false" /><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="3431661972220941645:6952134510589038883" autocomplete="off" /> 
</form> 

AssessmentType.java:

AssessmentType.java:

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.validation.constraints.NotNull;

import lombok.Data;

import org.hibernate.envers.Audited;

@Audited
@Data
@Entity
public class AssessmentType implements Comparable<AssessmentType> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    private String name;

    @OneToMany( fetch=FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity=AssessmentField.class )
    private List<AssessmentField> fields;

    @Override
    public int compareTo(final AssessmentType o) {
        return getId().compareTo(o.getId());
    }

    @Override
    public String toString() {
        return getName();
    }
}

AssessmentFieldConverter.java

AssessmentFieldConverter.java

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.htu.fizio.api.AssessmentFieldManager;
import com.htu.fizio.domain.AssessmentField;

@FacesConverter(forClass = AssessmentField.class)
public class AssessmentFieldConverter implements Converter {

    AssessmentFieldManager<AssessmentField> assessmentFieldManager;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public Object getAsObject(FacesContext ctx, UIComponent component, String value) {
        try {
            final InitialContext ic = new InitialContext();

            assessmentFieldManager = (AssessmentFieldManager) ic.lookup("fizio/AssessmentFieldManagerImpl/local");

            return assessmentFieldManager.find(Long.valueOf(value));
        } catch (NamingException e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    public String getAsString(FacesContext ctx, UIComponent component, Object value) {
        return String.valueOf(((AssessmentField) value).getId());
    }
}

AssessmentBean.java

AssessmentBean.java

    import java.util.List;

    import javax.annotation.PostConstruct;
    import javax.ejb.EJB;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ManagedProperty;
    import javax.faces.bean.SessionScoped;

    import lombok.Getter;
    import lombok.Setter;

    import com.htu.fizio.api.AssessmentManager;
    import com.htu.fizio.domain.Assessment;
    import com.htu.fizio.domain.AssessmentField;
    import com.htu.fizio.domain.AssessmentFieldValue;
    import com.htu.fizio.jsf.faces.FacesUtil;

...    

@PostConstruct
public void init() {
    if (FacesUtil.containsKey("assessmentId")) {
        final Long id = Long.parseLong(FacesUtil.get("assessmentId"));

        assessment = assessmentManager.find(id);
    } else {
        assessment = new Assessment();
    }
}

    public String doAddField() {
        final AssessmentFieldValue value = new AssessmentFieldValue();

        value.setField(assessmentField);
        value.setValue("");

        assessment.getFieldValues().add(value);

        assessmentManager.save(assessment);

        return "/edit/assessment";
    }

Edit:

编辑:

Just noticed this when debugging, is it a likely suspect?:

在调试时注意到这一点,是否可能是可疑的?:

Daemon Thread [HandshakeCompletedNotify-Thread] (Suspended (exception ConcurrentModificationException)) 
    HashMap$EntryIterator(HashMap$HashIterator<E>).nextEntry() line: 793    
    HashMap$EntryIterator.next() line: 834  
    HashMap$EntryIterator.next() line: 832  
    SSLSocketImpl$NotifyHandshakeThread.run() line: 2214    

3 个解决方案

#1


15  

Validation Error: Value is not valid

验证错误:值无效

To the point, this error means that the selected item does not match any of the items available in the list. I.e. the object represented by the selected item value has never returned true on its equals() call with any of the available select items.

到目前为止,此错误表示所选项目与列表中的任何可用项目都不匹配。即所选项目值表示的对象在其equals()调用中从未返回true,并且具有任何可用的选择项。

There are only two causes for this problem:

导致此问题的原因只有两个:

  1. The equals() method of the object type in question is broken.
  2. 有问题的对象类型的equals()方法被破坏。
  3. The contents of the list of items is different during the validations phase of the form submit request than as it was during the render response phase of the initial request to display the form.
  4. 在表单提交请求的验证阶段,项目列表的内容与在显示表单的初始请求的呈现响应阶段期间的内容不同。

Since the first seems to be properly implemented -as per the comments-, the only cause left is the second. Assuming that you're nowhere doing business logic in a getter method, an easy test is to put the #{assessmentBean} in the session scope. If it works, then the data (pre)loading logic of the list of select items is definitely wrong.

由于第一个似乎是正确实施的 - 按照评论 - ,唯一的原因是第二个。假设您在getter方法中没有进行业务逻辑,一个简单的测试就是将#{assessmentBean}放在会话范围内。如果它工作,那么选择项列表的数据(预)加载逻辑肯定是错误的。

#2


5  

The validation is failing because after your converter converts the String representation of AssessmentType back to an object, JSF iterates over the existing values (assessmentBean.assessment.type.fields) and compares this recently converted object with all those existing ones.

验证失败,因为在转换器将AssessmentType的String表示形式转换回对象后,JSF会迭代现有值(assessmentBean.assessment.type.fields)并将此最近转换的对象与所有现有对象进行比较。

Since you did not implement Object#equals for AssessmentType, it will default to an object identity comparison (roughly spoken, the memory address of your object) , which will of course fail.

由于您没有为AssessmentType实现Object#equals,因此它将默认为对象标识比较(粗略地说,您的对象的内存地址),这当然会失败。

The solution is thus to either implement Object#equals, or let the converter get the object from assessmentBean.assessment.type.fields instead of from AssessmentTypeManager.

因此,解决方案是实现Object#equals,或者让转换器从assessmentBean.assessment.type.fields而不是从AssessmentTypeManager获取对象。

#3


2  

I think I've resolved this, at least, I've moved on to the next error!

我想我已经解决了这个问题,至少,我已经转向了下一个错误!

Despite posting reams of code I'd not posted the full xhtml in which there were multiple and nested form tags. Just the one form seems to allow passing the assessmentId parameter which in turn allows the AssessmentBean to then populate the List of AssessmentFields for the assessment type correctly.

尽管发布了大量的代码,我还没有发布完整的xhtml,其中有多个嵌套的表单标签。只有一个表单似乎允许传递assessmentId参数,而参数允许EvaluBean然后正确填充评估类型的AssessmentFields列表。

Thanks for all the help.

谢谢你的帮助。

#1


15  

Validation Error: Value is not valid

验证错误:值无效

To the point, this error means that the selected item does not match any of the items available in the list. I.e. the object represented by the selected item value has never returned true on its equals() call with any of the available select items.

到目前为止,此错误表示所选项目与列表中的任何可用项目都不匹配。即所选项目值表示的对象在其equals()调用中从未返回true,并且具有任何可用的选择项。

There are only two causes for this problem:

导致此问题的原因只有两个:

  1. The equals() method of the object type in question is broken.
  2. 有问题的对象类型的equals()方法被破坏。
  3. The contents of the list of items is different during the validations phase of the form submit request than as it was during the render response phase of the initial request to display the form.
  4. 在表单提交请求的验证阶段,项目列表的内容与在显示表单的初始请求的呈现响应阶段期间的内容不同。

Since the first seems to be properly implemented -as per the comments-, the only cause left is the second. Assuming that you're nowhere doing business logic in a getter method, an easy test is to put the #{assessmentBean} in the session scope. If it works, then the data (pre)loading logic of the list of select items is definitely wrong.

由于第一个似乎是正确实施的 - 按照评论 - ,唯一的原因是第二个。假设您在getter方法中没有进行业务逻辑,一个简单的测试就是将#{assessmentBean}放在会话范围内。如果它工作,那么选择项列表的数据(预)加载逻辑肯定是错误的。

#2


5  

The validation is failing because after your converter converts the String representation of AssessmentType back to an object, JSF iterates over the existing values (assessmentBean.assessment.type.fields) and compares this recently converted object with all those existing ones.

验证失败,因为在转换器将AssessmentType的String表示形式转换回对象后,JSF会迭代现有值(assessmentBean.assessment.type.fields)并将此最近转换的对象与所有现有对象进行比较。

Since you did not implement Object#equals for AssessmentType, it will default to an object identity comparison (roughly spoken, the memory address of your object) , which will of course fail.

由于您没有为AssessmentType实现Object#equals,因此它将默认为对象标识比较(粗略地说,您的对象的内存地址),这当然会失败。

The solution is thus to either implement Object#equals, or let the converter get the object from assessmentBean.assessment.type.fields instead of from AssessmentTypeManager.

因此,解决方案是实现Object#equals,或者让转换器从assessmentBean.assessment.type.fields而不是从AssessmentTypeManager获取对象。

#3


2  

I think I've resolved this, at least, I've moved on to the next error!

我想我已经解决了这个问题,至少,我已经转向了下一个错误!

Despite posting reams of code I'd not posted the full xhtml in which there were multiple and nested form tags. Just the one form seems to allow passing the assessmentId parameter which in turn allows the AssessmentBean to then populate the List of AssessmentFields for the assessment type correctly.

尽管发布了大量的代码,我还没有发布完整的xhtml,其中有多个嵌套的表单标签。只有一个表单似乎允许传递assessmentId参数,而参数允许EvaluBean然后正确填充评估类型的AssessmentFields列表。

Thanks for all the help.

谢谢你的帮助。