2

I know this has been discussed a lot, and I also tried most of resolution, but I still got this error:

    sourceId=comboNewTaskParent[severity=(ERROR 2), summary=(comboNewTaskParent: Validation Error: Value is not valid), detail=(comboNewTaskParent: Validation Error: Value is not valid)]

Here is the code for HTML:

    <h:outputLabel value="Parent task" for="comboNewTaskParent" />
                            <div class="formRight">
                                <h:selectOneMenu id="comboNewTaskParent" value="#{taskController.parentTask}" converter="#{taskConverter}"
                                    <f:selectItems value="#{comboTaskByProject}" var="task" itemValue="#{task}" itemLabel="#{task.taskName}" />
                                </h:selectOneMenu>
                            </div>

Here is the code of my entity bean:

    package com.projectportal.entity;

import java.io.Serializable;
import javax.persistence.*;
import java.util.Date;
import java.util.List;


/**
 * The persistent class for the Task database table.
 * 
 */
@Entity
@Table(name="Task")
public class Task implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@Column(unique=true, nullable=false, length=36)
private String taskId;

@Column(length=1000)
private String taskDesc;

@Column(nullable=false)
private int taskDurationHour;

@Temporal(TemporalType.TIMESTAMP)
@Column(nullable=false)
private Date taskEstimated;

@Column(nullable=false, length=200)
private String taskName;

@Column(nullable=false)
private float taskPercentComplete;

@Temporal(TemporalType.TIMESTAMP)
@Column(nullable=false)
private Date taskStartDate;

//bi-directional many-to-one association to Priority
@ManyToOne
@JoinColumn(name="priorityId", nullable=false)
private Priority priority;

//bi-directional many-to-one association to Project
@ManyToOne
@JoinColumn(name="projectId")
private Project project;

//bi-directional many-to-one association to Status
@ManyToOne
@JoinColumn(name="statusId", nullable=false)
private Status status;

//bi-directional many-to-one association to Task
@ManyToOne
@JoinColumn(name="parentTaskId")
private Task parentTask;

//bi-directional many-to-one association to Task
@OneToMany(mappedBy="parentTask")
private List<Task> childTasks;

//bi-directional many-to-one association to Task
@ManyToOne
@JoinColumn(name="preTaskId")
private Task preTask;

//bi-directional many-to-one association to Task
@OneToMany(mappedBy="preTask")
private List<Task> dependentTasks;

//bi-directional many-to-one association to UserXTask
@OneToMany(mappedBy="task")
private List<UserXTask> userXtasks;

public Task() {
}

public String getTaskId() {
    return this.taskId;
}

public void setTaskId(String taskId) {
    this.taskId = taskId;
}

public String getTaskDesc() {
    return this.taskDesc;
}

public void setTaskDesc(String taskDesc) {
    this.taskDesc = taskDesc;
}

public int getTaskDurationHour() {
    return this.taskDurationHour;
}

public void setTaskDurationHour(int taskDurationHour) {
    this.taskDurationHour = taskDurationHour;
}

public Date getTaskEstimated() {
    return this.taskEstimated;
}

public void setTaskEstimated(Date taskEstimated) {
    this.taskEstimated = taskEstimated;
}

public String getTaskName() {
    return this.taskName;
}

public void setTaskName(String taskName) {
    this.taskName = taskName;
}

public float getTaskPercentComplete() {
    return this.taskPercentComplete;
}

public void setTaskPercentComplete(float taskPercentComplete) {
    this.taskPercentComplete = taskPercentComplete;
}

public Date getTaskStartDate() {
    return this.taskStartDate;
}

public void setTaskStartDate(Date taskStartDate) {
    this.taskStartDate = taskStartDate;
}

public Priority getPriority() {
    return this.priority;
}

public void setPriority(Priority priority) {
    this.priority = priority;
}

public Project getProject() {
    return this.project;
}

public void setProject(Project project) {
    this.project = project;
}

public Status getStatus() {
    return this.status;
}

public void setStatus(Status status) {
    this.status = status;
}

public Task getParentTask() {
    return this.parentTask;
}

public void setParentTask(Task parentTask) {
    this.parentTask = parentTask;
}

public List<Task> getChildTasks() {
    return this.childTasks;
}

public void setChildTasks(List<Task> childTasks) {
    this.childTasks = childTasks;
}

public Task getPreTask() {
    return this.preTask;
}

public void setPreTask(Task preTask) {
    this.preTask = preTask;
}

public List<Task> getDependentTasks() {
    return this.dependentTasks;
}

public void setDependentTasks(List<Task> dependentTasks) {
    this.dependentTasks = dependentTasks;
}

public List<UserXTask> getUserXtasks() {
    return this.userXtasks;
}

public void setUserXtasks(List<UserXTask> userXtasks) {
    this.userXtasks = userXtasks;
}

}

The controller:

    public @Model class TaskController {

@Inject private EntityManager em;
@Inject Identity identity;
@Inject Logger log;
@Inject Event<Task> taskEventSrc;

@Named
@Produces
private List<Task> requestTaskList;

private Task parentTask;

private Task newTask;

@Produces
@Named
public Task getNewTask(){
    return this.newTask;
}
/**
 * 
 */
public TaskController() {
    // TODO Auto-generated constructor stub
}

@PostConstruct
public void loadSelfTasks(){

    // Init
    newTask = new Task();

    // Get user from DB.
    User user = em.find(User.class, identity.getUser().getId());
    requestTaskList = new ArrayList<Task>();

    // Loop user's tasks.
    for(UserXTask userTask : user.getUserXtasks()){
        requestTaskList.add(userTask.getTask());
    }

    log.info("Tasks for user: " + user.getFirstname() + " loaded.");
}

/**
 * Create task.
 * @throws Exception
 */
public void createTask() throws Exception{
    log.info("Persistencing task: " + newTask.getParentTask().getTaskId());
    em.persist(newTask);
    taskEventSrc.fire(newTask);

    newTask = new Task();
}
/**
 * @return the parentTask
 */
public Task getParentTask() {
    return parentTask;
}
/**
 * @param parentTask the parentTask to set
 */
public void setParentTask(Task parentTask) {
    this.parentTask = parentTask;
}

}

And of course the converter:

    @Named
/**
 * @author lastcow
 *
 */

public class TaskConverter implements Converter {

@Inject EntityManager em;
@Inject Logger log;

/* (non-Javadoc)
 * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
 */
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value)     {
    log.info("=========== Convert to Object " + value);
    if(value.equals("0")){
        return null;
    }
    Task t =  em.find(Task.class, value);
    log.info("======== Got : " + t.getTaskName());
    return t;
}

/* (non-Javadoc)
 * @see javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.Object)
 */
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    log.info("=========== Convert to String " + value);
    return ((Task)value).getTaskId();
}

}

from what logged, the convert are working as it, but when I try to submit the form, always throw 'Validation Error: Value is not valid' ERROR, I have struck here for almost 2 days.

Anyone please give some suggestions.

BTW, I tried put equals and hashCode in Task.java, doesn't working either. Thanks in advance.

lastcow
  • 137
  • 1
  • 4
  • 13

2 Answers2

11

Validation Error: Value is not valid

This error will be thrown when the equals() method of the selected item hasn't returned true for any of the available items in <f:selectItem(s)>. Thus, this can technically have only 2 causes:

  1. The equals() method of your Task class is missing or broken.
  2. The <f:selectItems value="#{comboTaskByProject}"> has incompatibly changed during the postback request of the form submit as compared to during the initial request of the form display.

To fix cause #1, make sure that you understand how to implement equals() properly. You can find kickoff examples here: Right way to implement equals contract

To fix cause #2, make sure that the #{comboTaskByProject} never canges during postback. Best is to put it in the view scope or broader, or to make sure that request based conditions for populating that list are preserved in the postback request by e.g. using <f:viewParam>.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks, BalusC, the problem solved by implemented correct equals method, but the strange things is that I implemented equals method yesterday still without luck:(. – lastcow Dec 08 '12 at 02:17
  • Really great appreciate your help. ;) you saved my life. ;) – lastcow Dec 08 '12 at 02:18
1

I am not sure which version of JSF you are using. As far as I know, the converter in HTML should be used like this converter="javax.faces.DateTime". Where this part javax.faces.DateTime is converter name defined in faces-config.xml or in converter class with @FacesConverter.

piotrsPL
  • 17
  • 3
  • This is valid usage of a converter. Main reason why a converter is annotated as managed bean is just to be able to use `@EJB` or `@Inject`. See also among others http://stackoverflow.com/questions/13156671/how-can-i-inject-in-facesconverter/13156834#13156834 Even then, if the converter was indeed not recognized for the reasons you assumed, the OP would have received a conversion error, not a validation error. – BalusC Dec 07 '12 at 19:52
  • Both implementation should works. – lastcow Dec 08 '12 at 02:19