1

I still have problem with selectManyCheckBox..

selectManyCheckBox:

 <p:selectManyCheckbox converter="genericEnumConverter" value="#{aView.newObject.aValue}">                                           
        <f:selectItems value="#{enumBean.aValueValues}" var="s" itemValue="#{s}" itemLabel = "#{s.name}"/>
 </p:selectManyCheckbox> 

Converter for this selectManyCheckBox is the same as described here: Use enum in h:selectManyCheckbox

@FacesConverter("genericEnumConverter")
public class GenericEnumConverter implements Converter {

    private static final String ATTRIBUTE_ENUM_TYPE = "GenericEnumConverter.enumType";

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        System.out.println("getAsString 1: ");
        if (value instanceof Enum) {
            System.out.println("getAsString 2: ");
            component.getAttributes().put(ATTRIBUTE_ENUM_TYPE, value.getClass());
            System.out.println("getAsString 3: ");
            return ((Enum<?>) value).name();
        } else {
            System.out.println("getAsString 4: ");
            throw new ConverterException(new FacesMessage("Value is not an enum: " + value.getClass()));
        }        
    }

    @Override
    @SuppressWarnings({"rawtypes", "unchecked"})
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        System.out.println("getAsObject 1: ");
        Class<Enum> enumType = (Class<Enum>) component.getAttributes().get(ATTRIBUTE_ENUM_TYPE);
        System.out.println("getAsObject 2: ");
        try {
            System.out.println("getAsObject 3: ");
            return Enum.valueOf(enumType, value);
        } catch (IllegalArgumentException e) {
            System.out.println("getAsObject 4: ");
            throw new ConverterException(new FacesMessage("Value is not an enum of type: " + enumType));
        }
    }

The enum is:

public enum aValue {

        1Value,
        2Value,
        3Value,
        4Value;
        private final String name;

        private aValue() {
            System.out.println("aValue 1");
            this.name = null;
            System.out.println("aValue 2");
        }

        public String getName() {
            System.out.println("getName 1 " + name());
            return ResourceBundleUtil.getLabelFromRb("aValue." + name());
        }
    }

    public aValue[] getAValueValues() {
        return AValue.values();
    }

Tomcat Logs are:

aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
aValue 1
aValue 2
getName 1Value
getName 2Value
getName 3Value
getName 4Value
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getName 1Value
getName 2Value
getName 3Value
getName 4Value
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 
getAsString 1: 
getAsString 2: 
getAsString 3: 

When I press save button, nothing happens and nothing is saved into database. It looks like it is not going into getAsObject method. I don't know why. When I change the component into a SelectOneMenu there is no problem. But this selectManyCheckBox thing is not working. Does anyone have any idea?

Community
  • 1
  • 1
lamostreta
  • 2,359
  • 7
  • 44
  • 61
  • If you are using `p:commandButton` add attribute `ajax="false"` and check event is firing or not. – UdayKiran Pulipati Apr 16 '14 at 08:36
  • 1
    My approch for thoses situations is to put a breakpoint on processDecodes(FacesContext context) and getConvertedValue(context, submittedValue) of javax.faces.component.UIinput and to look for the request parameters – Nassim MOUALEK Apr 20 '14 at 16:14

1 Answers1

2

Your problem is here:

<p:selectManyCheckbox ... value="#{aView.newObject.aValue}">

You're binding the value attribute of an input component which can get/set multiple values to a property which represents a single value. This isn't going to work. You need to bind the value attribute to a collection (e.g. List<aValue>) or array (e.g. aValue[]) property instead of a single property aValue.

For example:

public class NewObject {

    private List<aValue> aValues;

    // ...
}

with

<p:selectManyCheckbox ... value="#{aView.newObject.aValues}">

Or, alternatively:

public class NewObject {

    private aValue[] aValues;

    // ...
}

with

<p:selectManyCheckbox value="#{aView.newObject.aValues}">

Note that when you use arrays, the whole converter is not needed. See also omnifaces.GenericEnumConverter showcase page.


Unrelated to the concrete problem, according to Java Naming Conventions, enum class names should start with uppercase, like as with regular classes and interfaces, so aValue as enum class name is really a bad choice. Hungarian notations are also discouraged in Java, by the way.


Update: to prove its working, here's an SSCCE.

The enum:

public enum Value {

    ONE, TWO, THREE;

    public String getName() {
        return name().toLowerCase();
    }

}

The entity:

public class Entity {

    private Value[] values;

    public Value[] getValues() {
        return values;
    }

    public void setValues(Value[] values) {
        this.values = values;
    }

}

The managed bean:

@ManagedBean
@RequestScoped // Note: @ViewScoped works as well on this SSCCE.
public class Bean {

    private Entity entity;

    @PostConstruct
    public void init() {
        entity = new Entity();
    }

    public void submit() {
        System.out.println(Arrays.toString(entity.getValues()));
    }

    public Entity getEntity() {
        return entity;
    }

    public Value[] getAvailableValues() {
        return Value.values();
    }

}

The view (without any converter!):

<h:form>
    <p:selectManyCheckbox value="#{bean.entity.values}">
        <f:selectItems value="#{bean.availableValues}" var="value"
            itemValue="#{value}" itemLabel="#{value.name}" />
    </p:selectManyCheckbox> 
    <p:commandButton value="Submit" action="#{bean.submit}" /> 
</h:form>

It works just fine for me (Mojarra 2.1.28 + PrimeFaces 4.0, but should work on all older versions as well as this construct isn't previously known to have any bugs).

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • thanks for the detailed answer. I tried using arrays, but didn't work. The output is: http://codeshare.io/tTJDY I changed the code like this: http://codeshare.io/O7eNb – lamostreta Apr 18 '14 at 13:25
  • Well, apparently `#{aView.newObject}` is `null`, or the input is simply not covered by ajax process. Hard to tell without seeing a true SSCCE. – BalusC Apr 18 '14 at 13:29
  • Note: In the original code I obeyed the Java Naming Conventions. But when I transfer the code here, I made a mistake. Thanks anyway:) – lamostreta Apr 18 '14 at 13:30
  • I was not setting the value in the bean. When did it, it worked. Thanks! – lamostreta Apr 24 '14 at 07:45