4 Replies Latest reply on Apr 1, 2008 4:21 PM by Ernesto Cullen

    selectOneMenu and JPA ManyToOne

    Ken Clark Newbie

      I have a lookup table and corresponding JPA component, and a table with a foreign key to that lookup table.  The JPA component for this looks like:

      @Table(name = "custom_data_configuration")
      public class CustomDataConfiguration implements Serializable
          @Column(name = "custom_data_key")
          private String customDataKey;
          @JoinColumn(name = "custom_data_type_code")
          private CustomDataType customDataType;
      // ...

      I have a web page which allows editing of the customDataConfiguration component.  In order to allow entry of the customDataType field, I figure the easiest thing to do is make it an h:selectOneMenu, and build the SelectItem array like this:

              customDataTypes = new ArrayList<SelectItem>();
              List<CustomDataType> cdts = em.createQuery("SELECT cdt FROM CustomDataType cdt").
              for (CustomDataType cdt : cdts)
                  customDataTypes.add(new SelectItem(cdt, cdt.getCustomDataTypeDesc()));

      Note, the customDataTypes field is set up as:

          @Out(required = false,scope=ScopeType.SESSION)
          private List<SelectItem> customDataTypes;

      I wasn't really sure if this would work and, so far, it doesn't.  I get the following error:

      sourceId=selectBranchForm:typeSelection[severity=(ERROR 2), summary=(/admin/editcdconfig.xhtml @23,1
      07 value="#{customDataConfiguration.customDataType}": java.lang.IllegalArgumentException: argument t
      ype mismatch), detail=(/admin/editcdconfig.xhtml @23,107 value="#{customDataConfiguration.customData
      Type}": java.lang.IllegalArgumentException: argument type mismatch)]

      Is this just the wrong way to go about this or do I just have a minor error somewhere.  If there is a better solution, how does that work?

      ken clark

        • 1. Re: selectOneMenu and JPA ManyToOne
          Marcell Newbie

          I don't know what the errors is, but what I do is to return the List returned by the entityManager directly and use a @Factory to cache the returned value.

          Can you post your facelets page?

          • 2. Re: selectOneMenu and JPA ManyToOne
            Ken Clark Newbie

            Here is the whole thing:

            <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
            <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                <ui:define name="body">
                    <ice:form id="selectBranchForm">
                        <h:messages globalOnly="true" styleClass="message"/>
                        <ice:panelGrid id="homePanelGrid" columns="1" columnClasses="leftMenu,leftMenu">
                            <ice:panelGrid columns="2" columnClasses="rightMenu,leftMenu">
                                <h:outputLabel for="keyid" value="Key Id: " />
                                <h:inputText id="keyid" value="#{customDataConfiguration.customDataKey}"/>
                                <h:outputLabel for="typeSelection" value="User Entry Field Type: " />
                                <h:selectOneMenu id="typeSelection" value="#{customDataConfiguration.customDataType}">
                                    <f:selectItems value="#{customDataTypes}"/>
                                <h:outputLabel for="required" value="Required Entry?: " />
                                <h:selectBooleanCheckbox id="required" value="#{customDataConfiguration.required}" />                    
                                <h:outputLabel for="labelentry" value="Label: " />
                                <h:inputText id="labelentry" value="#{customDataConfiguration.customDataLabel}"/>
                                <h:outputLabel for="desc" value="Description (hint): " />
                                <h:inputTextarea id="desc" rows="4" cols="80" value="#{customDataConfiguration.customDataDesc}"/>
                            <ice:panelGrid columns="2" columnClasses="leftMenu,leftMenu">
                                <h:commandButton value="Save" action="#{customDataAction.save}" 
                                                 styleClass="button" />
                                <h:commandButton value="Cancel" action="#{customDataAction.cancel}" 
                                                 styleClass="button" />

            I don't believe I can just convert customDataTypes to be a List of CustomDataType objects with the f:selectItems as it is now.  How would I have to change this?

            I forgot to mention that before, the screen did display correctly -- the problem was with save.


            • 3. Re: selectOneMenu and JPA ManyToOne
              Sylvain Leroux Newbie

              I'm not sure, but I think you need one of the following:

              • a custom converter to convert from String to CustomDataType

              • a setCustomDataType(String s) method that accept a String and convert it, then store the value to your customDataType field (possibly annotating this method with @In)

              Hope this helps a little...


              • 4. Re: selectOneMenu and JPA ManyToOne
                Ernesto Cullen Newbie

                I think you need a converter String - CustomDataType, and also you need to use s:selectItems tag if your data is in a List; as I understand it, f:selectItems work with a Map. I have made a page with both cases like this:

                <h:selectOneMenu value="#{alumnoActual.tipoDoc}">
                  <f:selectItems value="#{manager4.getTiposDoc()}" />
                <h:selectOneMenu value="#{alumnoActual.localidad}" 
                  <s:selectItems value="#{localidades}" noSelectionLabel="----"
                    var="loc" label="#{loc.nombre}" />

                baked by EJB session beans:

                public class AlumnosMgr4 implements IAlumnosMgr4 {
                  public Map<String,String> getTiposDoc()
                    HashMap<String,String> tiposDoc = new 
                    for (TiposDoc t : TiposDoc.values())
                    return tiposDoc;
                public class LocalidadesList implements ILocalidadesList {
                  private List<Localidad> localidades;
                  EntityManager em;
                  public void cargarLocalidades() {
                    localidades = em.createQuery("select l from Localidad l")
                  public Converter getConverter() {
                    return new LocalidadConverter(localidades);
                  public void destroy() {
                  public List<Localidad> getLocalidades() {
                    return localidades;

                the converter:

                public class LocalidadConverter implements Converter {
                  private List<Localidad> localidades;
                  public LocalidadConverter(List<Localidad> lista)
                    localidades = lista;
                  public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
                    if (arg2==null || arg2.length()==0)
                      return null;
                    long id = Long.valueOf(arg2).longValue();
                    System.out.println("valor de id: "+arg2);
                    if (id<0) return null;
                    Localidad lRet = null;
                    for (Localidad l : localidades)
                      if (l.getIdlocalidad()==id)
                        lRet = l;
                    return lRet;    
                  public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
                    if (arg2==null) return "-1";
                    Localidad l = (Localidad)arg2;
                    System.out.println("Localidad: "+l.getNombre());
                    return String.valueOf(l.getIdlocalidad());

                hope this helps

                Ernesto Cullen