Lets say I ahve this on xhtml page:
                    <h:selectOneMenu value="#{repairManagerBean.manufacturerName}"
                        id="manufacturer_selection">
                        <f:ajax listener="#{repairManagerBean.changeDevice}" 
                            render="device_selection" />
                        <f:selectItems value="#{repairManagerBean.manufacturers}" 
                            var="manufacturer" itemValue="#{manufacturer.name}"/>
                    </h:selectOneMenu>
                    <h:message for="manufacturer_selection" style="color: red"/>
                    <h:selectOneMenu value="#{repairManagerBean.deviceName}" 
                        id="device_selection">
                        <f:selectItems value="#{repairManagerBean.devices}" 
                            var="device" itemValue="#{device.name}"/>
                    </h:selectOneMenu>
                    <h:message for="device_selection" style="color: red"/>
        <p><h:commandButton value="Submit" action="#{repairManagerBean.storeRepairInfo}" /></p>
In database there are 2 manufacturers: "Apple"(id=1), "myPhone"(id=2); and also 4 devices: "iPhone 4"(id=4), "iPad mini 4"(id=3), "SmartView 7"(id=2), "Pocket 2"(id=1).
When choose manufacturer, ajax updates devices. If I choose Apple, I can select any of 2 devices, hit Submit, and alls well and saved to db. If however I choose myPhone, no matter which device I select, I get:
j_id_4:device_selection: Value is not valid option
and storeRepairInfo method doesnt gets called.
This is my backing RepairManagerBean class:
@ManagedBean(name = "repairManagerBean")
@ViewScoped
public class RepairManager implements Serializable {
private Repair repair;
private List<Manufacturer> manufacturers;
private String manufacturerName;
private String deviceName;
private List<Device> devices;
/**
 * Creates a new instance of RepairManagerBean
 */
public RepairManager() {
}
// getters and setters for all fields except daos
// Action Methods
public String storeRepairInfo() {
    try {
        Manufacturer m = manufacturerDao.findByName(manufacturerName);
        Device d = deviceDao.findByName(deviceName);
        repair.setDevice(d);
        repair.setManufacturer(m);
        saveRepair();
        return "success";
    } catch(Exception e) {
        System.err.println("write fail");
        return "error";
    }
}
public void changeDevice(AjaxBehaviorEvent event) {
    for(Manufacturer m : manufacturers) {
        if(m.getName().equals(manufacturerName)) {
            devices = deviceDao.findByManufacturerId(m.getId());
            break;
        }
    }
}
@PostConstruct
public void init() {
    repair = new Repair();
    manufacturers = new ArrayList<>();
    manufacturerName = "";
    devices = new ArrayList<>();
    deviceName = "";
    try {
        readManufacturersDevices();
    } catch(Exception e) { System.err.println("manufacturers read fail");}
}
public void saveRepair() throws Exception {
    // save repair object to db
}
public void readManufacturersDevices() throws Exception {
    // normally ofc its read from db, but result is same here so you can compile it
    Manufacturer apple = new Manufacturer(1l, "Apple");
    Manufacturer myphone = new Manufacturer(2l, "myPhone");
    manufacturers = new ArrayList<>();
    manufacturers.add(apple);
    manufacturers.add(myphone);
    Device pocket2 = new Device(1l, "Pocket 2");
    Device smartview7 = new Device(2l, "SmartView 7");
    Device ipad4mini = new Device(3l, "iPad 4 mini");
    Device iphone4 = new Device(4l, "iPhone 4");
    devices = new ArrayList<>();
    devices.add(pocket2);
    devices.add(smartview7);
    devices.add(ipad4mini);
    devices.add(iphone4);
}
}
And here is simple Device entity class:
@Entity
@Table(name = "Device")
public class Device extends AbstractEntity {
@Column(name = "name")
private String name;
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "manufacturer_id")
private Manufacturer manufacturer;
public Device() {
}
public Device(String name, Manufacturer manufacturer) {
    this.name = name;
    this.manufacturer = manufacturer;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public Manufacturer getManufacturer() {
    return manufacturer;
}
public void setManufacturer(Manufacturer manufacturer) {
    this.manufacturer = manufacturer;
}
@Override
public String toString() {
    return "Device{" + "id=" + id + "name=" + name + ", manufacturer=" 
            + manufacturer + '}';
}
@Override
public int hashCode() {
    int hash = 7;
    hash = 71 * hash + Objects.hashCode(this.name);
    hash = 71 * hash + Objects.hashCode(this.manufacturer.getName());
    return hash;
}
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Device other = (Device) obj;
    if (!this.name.equals(other.name)) {
        return false;
    }
    if (!this.manufacturer.getName().equals(other.manufacturer.getName())) {
        return false;
    }
    return true;
}
}
And here is simple Manufacturer entity class:
@Entity
@Table(name = "Manufacturer")
public class Manufacturer extends AbstractEntity {
@Column(name = "name")
private String name;
public Manufacturer() {
}
public Manufacturer(String name) {
    this.name = name;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
@Override
public String toString() {
    return "Manufacturer{" + "id=" + id + "name=" + name + '}';
}
@Override
public int hashCode() {
    int hash = 7;
    hash = 29 * hash + Objects.hashCode(this.name);
    return hash;
}
@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Manufacturer other = (Manufacturer) obj;
    if (!Objects.equals(this.name, other.name)) {
        return false;
    }
    return true;
}
}
And simple abstract entity here:
@MappedSuperclass
public abstract class AbstractEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}
}
I have implemented equals and hashcode in Device entity class as you can see. I use @ViewScoped on backing bean class. I read also this and that posts. I dont use any custom converter. Thanks for help.
