Pregunta

Tenemos valores numéricos en nuestra base de datos, lo que representa un estado de dos valores. Por supuesto, esto sería perfectamente coincidir un valor lógico, pero Oracle no tiene tal tipo de datos. El tipo de número (1,0) de la base de datos está adaptada a un tipo java.lang.Short en Java (a veces se utilizan un número (*, 0) para representar booleanos, que se hacen coincidir con java.math.BigDecimal).

Dado que de alguna manera es obvio, quiero ofrecer hielo: selectBooleanCheckbox en la vista como una representación de valor y UIComponent al usuario. (Yo uso IceFaces como la implementación JSF)

Dado que algunas personas que se especifican JSF piensan que es obvio para coincidir siempre con el valor de un hielo: selectBooleanCheckbox o en JSF h: selectBooleanCheckbox a un valor lógico en el modelo, por lo que el procesador del componente nunca llama a cualquier convertidor, incluso si especifique uno: disscused en java.net

Por lo tanto he intentado lo siguiente:

He creado un convertidor para especificar que en el 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";
   }
 }

El convertidor funciona bien para la fase de render (el getAsString-método se llama correctamente), pero el getAsObject-método (Ignorar que no es correcta en el momento, porque no se le llama de todos modos, por lo que se fijará si se llama !), nunca se llama, porque en el procesador de la UIComponent un convertidor no está previsto, como se puede ver aquí (SNIP de 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);
 }

Así que esto resulta en una IllegalArgumentException, ya que en la fase UpdateModelValues ??se pretende aplicar un booleano a un valor numérico (por favor, ignora la confusión BigDecimal / corto ... es sólo un tipo numérico en cualquier caso!).

Así que traté de sobrescribir el procesador por uno nuevo como esto:

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);  
   }
 }

y registrado como este en faces-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>

Creo que esto debe ser correcta, pero el método reemplazado "getConvertedValue" nunca es llamado, ni es la getAsObject () - Método, así que supongo que he cometido un error al registrar el intérprete personalizado, pero no puedo encontrar ningún más documentación o consejos de cómo hacer esto correctamente y, especialmente, cómo encontrar la correcta componente familiar (miré el que yo uso en icefaces.taglib.xml) y el correcto tipo de render.

Yo no quiero editar el modelo completo debido a esto. ¿Alguna pista, cómo esto se puede resolver?

¿Fue útil?

Solución

Podríamos solucionar el problema y correctamente registrar nuestro intérprete personalizado.

El problema era encontrar las propiedades correctas para el renderizador previsto. Nuestros intentos estaban equivocados, ya que me enteré de cómo obtener la información apropiada. Es un poco de trabajo y búsqueda, pero finalmente lo hizo el truco.

Simplemente comienza su contenedor en modo de depuración y añadir un punto de interrupción en el nivel de clase en la clase derivada del intérprete personalizado se basa en (en mi caso com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer).

Durante recipiente de puesta en marcha este punto de interrupción se alcanzará y en el StackTrace encontrará una llamada de los FacesConfigurator.configureRenderKits método ().

Este objeto contiene un ArrayList de extracción de grasas registrados. He buscado en la lista para el procesador Me hubiera gustado para sobrescribir y no pude encontrar las informaciones que necesito para registrar mi intérprete personalizado. En mi caso esto es la entrada correcta en el faces-config.xml:

<render-kit>
    <description>The ICEsoft Renderers.</description>
    <render-kit-id>ICEfacesRenderKit</render-kit-id>
    <render-kit-class>com.icesoft.faces.renderkit.D2DRenderKit</render-kit-class>
    <renderer>
            <component-family>javax.faces.SelectBoolean</component-family>
            <renderer-type>com.icesoft.faces.Checkbox</renderer-type>
            <renderer-class>com.myapp.web.util.CustomHtmlSelectBooleanCheckbox</renderer-class>
    </renderer>
 </render-kit>

Ahora el getAsObject () - Método en el convertidor es llamado por el intérprete personalizado. Asegúrese de reemplazar el método correctamente, en caso de que no quieren un convertidor en cada objeto SelectBooleanCheckbox:

public Object getConvertedValue(FacesContext context,
        UIComponent component, Object submittedValue)
        throws ConverterException {
    Converter converter = ((ValueHolder) component).getConverter();
    if (converter == null) {
        if(!(submittedValue instanceof String))
            throw new ConverterException("Expecting submittedValue to be String");
        else
            return Boolean.valueOf((String)submittedValue);
    }
    return converter.getAsObject(context, component,
            (String) submittedValue);
}

De lo contrario obtendrá una NullPointerException.

PS: Hay sin duda es una forma más inteligente para conseguir esta información, pero no soy lo suficientemente inteligente. ; -)

Otros consejos

Usted no dijo si usted está usando Hibernate pero supongo que debe ser para que esto sea un problema. ¿Ha intentado tratar el numérico como un valor lógico en su asignación?

hilo de los foros de Hibernate

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top