#目的
DBにOracleを使用している場合、真偽値に該当する型が存在しないため、Varchar2等を使用し、「0/1」で真偽値を表す必要があります。しかし、h:selectBooleanCheckboxではvalueにStringのプロパティーをバインドした場合、チェック有の場合「true」、無の場合「false」となります。これをチェック有の場合「1」に、無の場合「0」を設定させるのが目的です。
#問題点
単純にコンバーターを使用すれば可能かと思っていたのですが、
なぜかh:selectBooleanCheckboxのレンダラークラス「CheckboxRenderer」では「getAsObject」が実行されないよう実装されています。
なので「getAsObject」が実行されるレンダラークラスを自作し、そのクラスを使用するよう設定する必要があります。
やることは以下
1.CheckboxRendererを継承したクラスを作成。
「getConvertedValue」をオーバーライドし「getAsObject」を使用するよう修正。
2.faces-config.xmlでrender-kitを指定
3.コンバーターを作成
4.h:selectBooleanCheckboxのconverte属性に作成したコンバーターを指定
#実装方法
1.CheckboxRendererを継承したクラスを作成。
package renderer;
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import com.sun.faces.renderkit.html_basic.CheckboxRenderer;
public class CheckboxRendererEx extends CheckboxRenderer {
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) {
Converter converter = ((ValueHolder) component).getConverter();
if (converter instanceof FlagConverter) {
return converter.getAsObject(context, component, submittedValue == null ? null : submittedValue.toString());
} else {
return ((submittedValue instanceof Boolean)
? submittedValue
: Boolean.valueOf(submittedValue.toString()));
}
}
}
2.faces-config.xmlでrender-kitを指定
<?xml version="1.0"?>
<faces-config version="2.3"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd">
<render-kit>
<renderer>
<component-family>javax.faces.SelectBoolean</component-family>
<renderer-type>javax.faces.Checkbox</renderer-type>
<renderer-class>renderer.CheckboxRendererEx</renderer-class>
</renderer>
</render-kit>
</faces-config>
3.コンバーターを作成
package renderer;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
@FacesConverter("FlagConverter")
public class FlagConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
ValueExpression ve = component.getValueExpression("value");
Class<?> clazz = ve.getType(context.getELContext());
if (clazz.equals(String.class)) {
if (value == null) {
return "0";
} else {
return "true".equals(value) ? "1" : "0";
}
} else {
if (value == null) {
return Boolean.FALSE;
} else {
return "true".equals(value);
}
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value instanceof String) {
return "0".equals(value) ? "false" : "true";
} else if (value instanceof Boolean) {
return Boolean.FALSE.equals((Boolean) value) ? "false" : "true";
} else {
return "false";
}
}
}
4.h:selectBooleanCheckboxのconverte属性に作成したコンバーターを指定
<h:selectBooleanCheckbox value="#{checkRendererTest.strval}" converter="FlagConverter">
<f:ajax render="strval" execute="@this" event="change"/>
</h:selectBooleanCheckbox>
<h:outputText id="strval" value="#{checkRendererTest.strval}" />
これでチェック有の場合、strvalに「1」が
チェック無の場合、strvalに「0」が設定されるようになります。