2

I am about developing a small jsf project and I arrived to a state that I have to store a value in an enumeration type but couldn't figure out how to deal with

so I post here a small description of my problem:

here is the enumeration type:

 package com.enumeration;

 import java.io.Serializable;


 public enum Gender implements Serializable{

    Male('M'), Female('F');

    private char description;

   private Gender(char description) {
     this.description = description;
   }

   public char getDescription() {
     return description;
   }

}

the xhtml page:

    <h:panelGrid columns="2">
                <h:outputLabel value="Nom:" for="nom" />
                <h:inputText id="nom" value="#{employee.newEmployee.nom}" title="Nom" />

                <h:outputLabel value="Gender:" for="gender" />
                <h:selectOneMenu value="#{employeeBean.newEmployee.gender}" id="gender">
                     <f:selectItem itemLabel="Male" itemValue="Male" />
                    <f:selectItem itemLabel="Female" itemValue="Female"/>
                </h:selectOneMenu>

            </h:panelGrid>
            <h:commandButton value="ajouter" action="index.xhtml" actionListener="#{employeeBean.ajouter}" />
        </h:form>

the problem is that when I try to add a new row to the database, and error is thrown by jsf: j_idt7:gender: 'Male' must be convertible to an enum.

I did some search on the net but couldn't understand the solutions please help thanks

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
user1540625
  • 35
  • 1
  • 1
  • 5

2 Answers2

9

Your problem is that your <f:selectItem> specify strings, while in the <h:selectItem value="#{employeeBean.newEmployee.gender}"> seems to return one of the two Gender enums.

Enums are AFAIK directly convertible without converter as long as you stick the same values into both.

Here's the/a pattern:

<h:selectOneMenu value="#{employeeBean.newEmployee.gender}" id="gender">
    <f:selectItems value="#{enumValuesProvider.genders}"
                   var="gender"
                   itemValue="#{gender}"
                   itemLabel="#{gender.name()}" />
</h:selectOneMenu>

Note, I'm using <f:selectItems> here. The problem is, you can't simply get the values from a JSF page directly. You will need a dedicated bean to do the job:

@Named      // or @ManagedBean if you're not using CDI
@ViewScoped // or @RequestScoped
public EnumValuesProvider implements Serializable
{
    public Gender[] getGenders()
    {
        return Gender.values();
    }
}

This is just written down without any testing. No warranties.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
Kawu
  • 13,647
  • 34
  • 123
  • 195
0

In my entity:

@Entity

public class MyClass {
@Column
@Convert(converter = MyEnumConverter.class)
@Enumerated(EnumType.ORDINAL)
private MyEnumType myEnumType;
//....getter and setter    }

In my enum:

public enum MyEnumType {
    AAAA,
    BBBB;
public String getLabel() {
    switch (this) {
        case AAAA:
            return "aaaa";
        case BBBB:
            return "bbbb";

    }
    return "NONE";
}
@Override
public String toString() {
    return getLabel();
}
}

another enum:

public enum AnotherEnum {
      ...
}

In my convertor:(It is not one FacesConvertor).

@Converter
public class MyEnumConvertor implements AttributeConverter<MyEnumType, Byte> {
    @Override
    public Byte convertToDatabaseColumn(MyEnumType attribute) {
        switch (attribute) {
            case AAAA:
                return 0;
            case BBBB:
                return 1;
            default:
                throw new IllegalArgumentException("Unknown" + attribute);
        }
    }
    @Override
    public MyEnumType convertToEntityAttribute(Byte dbData) {
        switch (dbData) {
            case 0 :
                return EstatePossessionType.AAAA;
            case 1:
                return EstatePossessionType.BBBB;

            default:
                throw new IllegalArgumentException("Unknown" + dbData);
        }
    }
  }

In my util class:

public class MyUtilClass {
    public <T extends Enum> SelectItem[]     createSelectItemByEnumClass(Class<T> clazz) throws Exception {
        SelectItem[] selectItem = null;
        int i = 0;
        try {
          Object[] enumConstants = clazz.getEnumConstants();
            if (enumConstants != null) {
                selectItem = new SelectItem[enumConstants.length];
                for (Object object : enumConstants) {
                    selectItem[i++] = new SelectItem(object,     object.toString());
              }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return selectItem;
    }
}

In my CDI-bean class:

public class MyCdiClass {
    MyEnumType selectByUser = null;
    public Class getSelectItemClass(){
        return MyEnumType.class;//<<--I'll tell jsf, I want create SelectItem from this class.Maybe I have more than one enum:).
    }
    public MyEnumType getSelectByUser() {
        return selectByUser;
    }
    public void setSelectByUser(MyEnumType selectByUser) {
        this.selectByUser = selectByUser;
    }
}

In my jsf page:

<h:selectOneMenu value="#{handleEstateActionInEstate.selectByUser}">
    <f:selectItems value="#{myUtility.createSelectItemByEnumClass(myCdiBean.selectItemClass)}"/>
 </h:selectOneMenu>

I hope these snippet be useful.

M.Namjo
  • 374
  • 2
  • 13