1

I try to understand the principle of operation of the omnifaces.converter.ListIndexConverter

@FacesConverter("omnifaces.ListIndexConverter")
public class ListIndexConverter implements Converter {

private static final String ERROR_LIST_INDEX_BOUNDS =
        "Index {0} for value {1} in component {2} is out of bounds.";

private static final String ERROR_VALUE_NOT_IN_LIST =
        "Object {0} in component {1} does not appear to be present in the given list.";

private List<?> list;

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
    int index = Integer.valueOf(value);
    if (index < 0 || index >= list.size()) {
        throw new ConverterException(
            createError(ERROR_LIST_INDEX_BOUNDS, index, value, component.getClientId(context))
        );
    }

    return list.get(index);
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    for (int i = 0; i < list.size(); i++) {
        if (list.get(i).equals(value)) {
            return i + "";
        }
    }

    throw new ConverterException(
        createError(ERROR_VALUE_NOT_IN_LIST, value == null ? "null" : value.toString(), component.getClientId(context))
    );
}

public void setList(List<?> list) {
    this.list = list;
}

}

I've debugged into it, but couldn't figure out everything!

Here are my questions:

1) When and by whom is the list member variable filled?

2) In the documentation

http://omnifaces.org/docs/javadoc/2.0/org/omnifaces/converter/SelectItemsIndexConverter.html

the following point is mentioned:

This converter has the following disadvantage over SelectItemsConverter:

The "Validation Error: value is not valid" will never occur anymore for the case that the available select items has incompatibly changed during the postback due to a developer's mistake. The developer should make absolutely sure that exactly the same list is preserved on postback (e.g. by making it a property of a view scoped or broader scoped bean).

(SelectItemsConverter can be replaced by ListConverter)

Could someone explain that a bit more in detail? As I understood, it would need a @RequestScoped Bean and an editable list like used for DataTable, to provoke this? I would like to do so, for educational reasons and show this to other developers.

Hope my questions are clear! Thanks a lot for any explanation!

bauz
  • 125
  • 1
  • 12

1 Answers1

3

When and by whom is the list member variable filled?

By <o:converter list> attribute, exactly as shown in Usage section at showcase.

<p:pickList value="#{bean.dualListModel}" var="entity" itemValue="#{entity}" itemLabel="#{entity.someProperty}">
    <o:converter converterId="omnifaces.ListIndexConverter" list="#{bean.dualListModel.source}" />
    <!-- ===================================================^^^^ -->
</p:pickList>

The <o:converter> is a special taghandler which allows setting arbitrary properties on the referenced Converter instance as if it are bean properties.


The "Validation Error: value is not valid" will never occur anymore [...]

Could someone explain that a bit more in detail?

Selected items are with omnifaces.XxxIndexConverter not identified by their own identifier anymore, but by their position in the list. If the list changes across postbacks, JSF can this way not validate anymore if the selected item is really part of the list and the enduser really intends to select exactly that item. Imagine that the item's position in the list has changed due to it being removed or a newer item being added before the selected item, then you will end up actually getting the wrong item. See also the answer on Validation Error: Value is not valid for a background explanation.

If this is a security concern, then you'd really best pick the omnifaces.XxxConverter (without Index).

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555