這的確是「設計」,並在JSF規範也許有點疏忽。您理論上可以通過從UIComponent
參數中提取項目並與其進行比較來完全避免它。這是一個工作。我的同事阿爾揚Tijms寫了博客這個問題:Automatic to-Object conversion in JSF selectOneMenu & Co.
下面是相關的提取物;以下是基本轉換器,你就需要去繼承:
public abstract class SelectItemsBaseConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return SelectItemsUtils.findValueByStringConversion(context, component, value, this);
}
}
這裏的SelectItemsUtils
類這部分是從鑽嘴魚科的源代碼複製:
public final class SelectItemsUtils {
private SelectItemsUtils() {}
public static Object findValueByStringConversion(FacesContext context, UIComponent component, String value, Converter converter) {
return findValueByStringConversion(context, component, new SelectItemsIterator(context, component), value, converter);
}
private static Object findValueByStringConversion(FacesContext context, UIComponent component, Iterator<SelectItem> items, String value, Converter converter) {
while (items.hasNext()) {
SelectItem item = items.next();
if (item instanceof SelectItemGroup) {
SelectItem subitems[] = ((SelectItemGroup) item).getSelectItems();
if (!isEmpty(subitems)) {
Object object = findValueByStringConversion(context, component, new ArrayIterator(subitems), value, converter);
if (object != null) {
return object;
}
}
} else if (!item.isNoSelectionOption() && value.equals(converter.getAsString(context, component, item.getValue()))) {
return item.getValue();
}
}
return null;
}
public static boolean isEmpty(Object[] array) {
return array == null || array.length == 0;
}
/**
* This class is based on Mojarra version
*/
static class ArrayIterator implements Iterator<SelectItem> {
public ArrayIterator(SelectItem items[]) {
this.items = items;
}
private SelectItem items[];
private int index = 0;
public boolean hasNext() {
return (index < items.length);
}
public SelectItem next() {
try {
return (items[index++]);
}
catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
下面是你應該如何使用它自己的轉換器,你只需要執行getAsString()
(該getAsObject()
已處理):
@FacesConverter("someEntitySelectItemsConverter")
public class SomeEntitySelectItemsConverter extends SelectItemsBaseConverter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return ((SomeEntity) value).getId().toString();
}
}
更新上述概念已經結束了在JSF工具庫OmniFaces下面的轉換器的味道:
@BalusC:感謝您的想法和對不起,我對此很晚迴應。我需要爲primefaces'AutoComplete'組件實現這個(http://www.primefaces.org/showcase-labs/ui/autoCompletePojo.jsf),你能告訴我如何在這種情況下應用你的sol?謝謝。 – 2012-02-09 20:12:51
爲什麼是SomeEntity而不是實體?實例在哪裏發起? – Thufir 2012-04-17 03:10:30
斷開鏈接(第一個) – 2017-06-12 09:43:36