Problem with two nested selectOneMenu

1

I'm trying to make two nested selectOneMenu, one contains the provinces and the second the cities of those provinces. I miss an error, when selecting the province, and I can not find out what I did wrong.

The error:

SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-22) javax.faces.component.UpdateModelException: java.lang.IllegalArgumentException: 
  

Can not convert 2 of type class java.lang.Integer to class   ar.com.kompass.model.Province

at javax.faces.component.UIInput.updateModel(UIInput.java:866)
at javax.faces.component.UIInput.processUpdates(UIInput.java:749)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:577)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)

If I do not understand correctly, the message "Can not convert 2 of ...." refers to the value selected, in this case the value 2 of provinces, and that fails to "convert" it to a province object. How do I solve this?

The code snippet in the view that generates the error:

    <p:row>
                    <p:column>
                        <p:outputLabel value="Provincia " />
                        <p:selectOneMenu id="cboProvincia"
                            value="#{cuentaBean.cuenta.provincia}" required="true"
                            requiredMessage="Debe seleccionar una provincia"
                            converter="omnifaces.SelectItemsConverter">
                            <f:selectItem itemLabel="--Seleccione--" itemValue="#{null}"
                                noSelectionOption="true" />
                            <f:selectItems value="#{cuentaBean.lstProvincias}" var="prov"
                                itemLabel="#{prov.nombre}" itemValue="#{prov.id}" />
                            <f:ajax event="change"
                                listener="#{cuentaBean.listarLocalidades()}"
                                execute="cboProvincia" render="cboLocalidad" />
                        </p:selectOneMenu>
                    </p:column>

                    <p:column>
                        <p:outputLabel value="Localidad " />
                        <p:selectOneMenu id="cboLocalidad"
                            value="#{cuentaBean.cuenta.localidad}" required="true"
                            requiredMessage="Debe seleccionar una Localidad"
                            converter="omnifaces.SelectItemsConverter">
                            <f:selectItem itemLabel="--Seleccione--" itemValue="#{null}"
                                noSelectionOption="true" />
                            <f:selectItems value="#{cuentaBean.lstLocalidades}" var="loca"
                                itemLabel="#{loca.nombre}" itemValue="#{loca}" />
                        </p:selectOneMenu>
                    </p:column>
                </p:row>

This is the Bean:

@Named
@ViewScoped public class CuentaBean implements Serializable {

@Inject
private ICuentaService cuentaService;

@Inject
private Cuenta cuenta;
@Inject
private IProvinciaService provinciaService;
@Inject
private ILocalidadService localidadService;


private List<Cuenta> lstCuentas;
private List<Provincia> lstProvincias;
private List<Localidad> lstLocalidades;
private int codigoProvincia;

public int getCodigoProvincia() {
    return codigoProvincia;
}

public void setCodigoProvincia(int codigoProvincia) {
    this.codigoProvincia = codigoProvincia;
}

public Cuenta getCuenta() {
    return cuenta;
}

public void setCuenta(Cuenta cuenta) {
    this.cuenta = cuenta;
}


@PostConstruct
public void init(){     
    lstCuentas = new ArrayList<>();
    lstProvincias = new ArrayList<>();
    lstLocalidades = new ArrayList<>();
    this.listarProvincias();
}


public List<Cuenta> getLstCuentas() {
    return lstCuentas;
}

public void setLstCuentas(List<Cuenta> lstCuentas) {
    this.lstCuentas = lstCuentas;
}


public List<Provincia> getLstProvincias() {
    return lstProvincias;
}


public void setLstProvincias(List<Provincia> lstProvincias) {
    this.lstProvincias = lstProvincias;
}

public List<Localidad> getLstLocalidades() {
    return lstLocalidades;
}


public void setLstLocalidades(List<Localidad> lstLocalidades) {
    this.lstLocalidades = lstLocalidades;
}

public void listarProvincias() {
    try {
        //lstCuentas = cuentaService.listar();
        lstProvincias= provinciaService.listar();
        //lstLocalidades= localidadService.listar(idProv);      
    } catch (Exception e) {

    }
}

public void listarLocalidades() {
    try {
        System.out.print(this.codigoProvincia);
        lstLocalidades= localidadService.listar(this.codigoProvincia);          
    } catch (Exception e) {

    }
}


}

And finally the Model accounts , which could be the reason for the error:

@Entity @Table(name = "cuenta") public class Cuenta  implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "nombre", length = 30, nullable = false)
private String nombre;
@Column(name = "domicilio", length = 30, nullable = false)
private String domicilio;
private short altura;

@OneToOne
@JoinColumn(name="idprov" , nullable = false)
private Provincia provincia;

@OneToOne
@JoinColumn(name="idloca" , nullable = false)
private Localidad localidad;

public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getNombre() {
    return nombre;
}
public void setNombre(String nombre) {
    this.nombre = nombre;
}
public String getDomicilio() {
    return domicilio;
}
public void setDomicilio(String domicilio) {
    this.domicilio = domicilio;
}
public short getAltura() {
    return altura;
}
public void setAltura(short altura) {
    this.altura = altura;
}


public Localidad getLocalidad() {
    return localidad;
}
public void setLocalidad(Localidad localidad) {
    this.localidad = localidad;
}

public Provincia getProvincia() {
    return provincia;
}
public void setProvincia(Provincia provincia) {
    this.provincia = provincia;
}


@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Cuenta other = (Cuenta) obj;
    if (id != other.id)
        return false;
    return true;
}
}
    
asked by Fernando 27.09.2017 в 17:17
source

1 answer

0

The problem is in the inconsistency between the types of value of selectOneMenu and of itemValue of selectItems

The value of selectOneMenu should be able to be mapped to one of the itemValue of the possible items, however, in your code ( quito parts that are not related to the problem ) :

<p:selectOneMenu id="cboProvincia"
     value="#{cuentaBean.cuenta.provincia}"
     converter="omnifaces.SelectItemsConverter">
     <f:selectItems value="#{cuentaBean.lstProvincias}" var="prov"
     itemLabel="#{prov.nombre}" itemValue="#{prov.id}" />

 </p:selectOneMenu>
  • the value of selectOneMenu is an object of type Provincia
  • the itemValue of the selectItems is prov.id , that is, a Integer .

So the converter ( omnifaces.SelectItemsConverter ), when updating the model with the selected value, tries to convert from Integer to Provincia and the exception occurs:

  

Can not convert 2 of type class java.lang.Integer to class   ar.com.kompass.model.Province

The correct thing would be one of these two options, depending on your design:

  • Let value of selectOneMenu be #{cuentaBean.cuenta.provincia.id} and keep selectItems as they are
  •   <p:selectOneMenu id="cboProvincia"
                     value="#{cuentaBean.cuenta.provincia.id}"
                     converter="omnifaces.SelectItemsConverter">
                     <f:selectItems value="#{cuentaBean.lstProvincias}" var="prov"
                     itemLabel="#{prov.nombre}" itemValue="#{prov.id}" />
        </p:selectOneMenu>
    
  • Let itemValue of selectItems be #{prov} and keep value of selectOneMenu as it is defined.
  •  <p:selectOneMenu id="cboProvincia"
             value="#{cuentaBean.cuenta.provincia}"
             converter="omnifaces.SelectItemsConverter">
             <f:selectItems value="#{cuentaBean.lstProvincias}" var="prov"
             itemLabel="#{prov.nombre}" itemValue="#{prov}" />
         </p:selectOneMenu>
    
        
    answered by 07.10.2017 в 00:32