JSF验证错误:值无效



我知道这似乎是一个常见的问题,但我对此感到困惑。在assessment.jsf中单击"添加"按钮时发生。无论如何,我已经附上了我认为相关的部分。

FWIW,当我调试时,AssessmentType.equals()不会被触发。

提前谢谢。

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

评估.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:

<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> 

评估类型.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

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());
    }
}

评估Bean.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";
    }

编辑:

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

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    

验证错误:值不是有效的

就这点而言,此错误意味着所选项目与列表中的任何可用项目都不匹配。即,由所选项目值表示的对象从未在其具有任何可用选择项目的equals()调用中返回true

造成这个问题的原因只有两个:

  1. 所讨论的对象类型的equals()方法已损坏
  2. 在表单提交请求的验证阶段,项目列表的内容与在显示表单的初始请求的呈现响应阶段不同

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

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

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

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

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

尽管我发布了大量的代码,但我并没有发布完整的xhtml,其中有多个嵌套的表单标记。只有一个表单似乎允许传递assessmentId参数,这反过来又允许AssessmentBean正确地填充评估类型的AssessmentFields列表。

谢谢你的帮助。

相关内容

  • 没有找到相关文章

最新更新