В нашей базе данных есть числовые значения, представляющие собой состояние с двумя значениями. Конечно, это будет идеально соответствовать логическому значению, но у oracle такого типа данных нет. Тип NUMBER (1,0) из базы данных соответствует типу java.lang.Short в Java (иногда они используют NUMBER (*, 0) для представления логических значений, которые соответствуют java.math.BigDecimal).
Поскольку это как-то очевидно, я хочу предложить ice: selectBooleanCheckbox в представлении в качестве представления значения и UIComponent для пользователя. (Я использую IceFaces как реализацию JSF)
Поскольку некоторые люди, которые указали JSF, считают очевидным, что всегда нужно сопоставлять значение ice: selectBooleanCheckbox или в JSF h: selectBooleanCheckbox с логическим значением в модели, поэтому средство визуализации компонента никогда не вызывает какой-либо преобразователь, даже если вы указать один:
Вопрос рассмотрен на java.net
Поэтому я попробовал следующее:
Я создал конвертер, чтобы указать его в UIComponent:
public class BooleanBigDecimalConverter implements Converter {
public Object getAsObject(FacesContext context, UIComponent component, String str) {
if (StringUtils.isEmptyString(str)) {
return new BigDecimal(0);
}
if (str.equals("true")) {
return new BigDecimal(1);
} else {
return new BigDecimal(0);
}
}
public String getAsString(FacesContext context, UIComponent component, Object obj) {
if (obj != null) {
String str = obj.toString();
if (str.equalsIgnoreCase("1")
|| str.equalsIgnoreCase("yes")
|| str.equalsIgnoreCase("true")
|| str.equalsIgnoreCase("on")) {
return "true";
} else {
return "false";
}
}
return "false";
}
}
Конвертер работает нормально для фазы рендеринга (метод getAsString вызывается правильно), но метод getAsObject (не обращайте внимания на то, что в данный момент он некорректен, так как он все равно не вызывается, поэтому он будет исправлен, если он вызывается !) никогда не вызывается, потому что в средстве визуализации UIComponent конвертер не предусмотрен, как вы можете видеть здесь (фрагмент из com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer):
public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue) throws ConverterException
{
if(!(submittedValue instanceof String))
throw new ConverterException("Expecting submittedValue to be String");
else
return Boolean.valueOf((String)submittedValue);
}
Таким образом, это приводит к IllegalArgumentException, поскольку на этапе UpdateModelValues он пытается применить логическое значение к числовому значению (пожалуйста, игнорируйте путаницу BigDecimal / Short ... это просто числовой тип в любом случае!).
Итак, я попытался переписать рендерер новым:
import com.icesoft.faces.component.ext.renderkit.CheckboxRenderer;
public class CustomHtmlSelectBooleanCheckbox extends CheckboxRenderer {
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
Converter converter = ((ValueHolder) component).getConverter();
return converter.getAsObject(context, component, (String) submittedValue);
}
}
и зарегистрировал это следующим образом в face-config.xml:
<render-kit>
<renderer>
<component-family>com.icesoft.faces.HtmlSelectBooleanCheckbox</component-family>
<renderer-type>com.icesoft.faces.Checkbox</renderer-type>
<renderer-class>com.myapp.web.util.CustomHtmlSelectBooleanCheckbox</renderer-class>
</renderer>
</render-kit>
Полагаю, это должно быть правильно, но переопределенный метод "getConvertedValue" никогда не вызывается, как и метод getAsObject (), поэтому, я думаю, я допустил ошибку при регистрации пользовательского средства визуализации, но не могу найти какой-либо дополнительная документация или советы о том, как это сделать правильно, и особенно о том, как найти правильное семейство компонентов (я нашел тот, который я использую в icefaces.taglib.xml) и правильный тип рендерера.
Я не хочу редактировать полную модель из-за этого. Любые намеки, как это можно решить?