Question

Nous avons des valeurs numériques dans notre base de données, ce qui représente une valeur de deux états. Bien sûr, cela correspond parfaitement à un booléen, mais Oracle n'a pas un tel type de données. Le NUMÉRO Type (1,0) à partir de la base de données est adaptée à un type java.lang.Short en Java (parfois ils ont utilisé un nombre (*, 0) pour représenter les booléens, qui sont adaptés à java.math.BigDecimal).

Comme il est en quelque sorte évident, je veux offrir la glace: selectBooleanCheckbox dans la vue comme une représentation de valeur et UIComponent à l'utilisateur. (J'utilise Icefaces comme la mise en œuvre JSF)

Étant donné que certaines personnes qui ont précisé JSF pensent qu'il est évident pour correspondre toujours la valeur d'une glace: selectBooleanCheckbox ou JSF h: selectBooleanCheckbox à un booléen dans le modèle, de sorte que le moteur de rendu du composant appelle jamais convertisseur, même si vous spécifiez un: Problème disscused à java.net

J'ai donc essayé les éléments suivants:

Je créé un convertisseur pour spécifier dans la 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";
   }
 }

Le convertisseur fonctionne très bien pour la phase de rendu (la getAsString méthode est appelée à juste titre), mais la getAsObject méthode (ignorer que ce n'est pas correct pour le moment, parce que ce ne l'appelle pas de toute façon, il sera fixé si elle est appelée !) est jamais appelé, parce que dans le moteur de rendu du UIComponent un convertisseur n'est pas prévu, comme vous pouvez le voir ici (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);
 }

Il en résulte une IllegalArgumentException, puisque dans la phase de UpdateModelValues ??il est tenté d'appliquer une valeur booléenne à une valeur numérique (s'il vous plaît ignorer la confusion BigDecimal / court ... il est juste un type numérique en tout cas!).

J'ai donc essayé d'écraser le moteur de rendu par un nouveau comme celui-ci:

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

et enregistré comme celui-ci dans les 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>

Je suppose que cela doit être correct, mais la méthode surchargée « getConvertedValue » est jamais appelée, ni la getAsObject () - méthode, donc je suppose que je fait une erreur dans l'enregistrement du moteur de rendu personnalisé, mais je ne trouve pas plus de la documentation ou des conseils comment faire cela correctement et surtout comment trouver la bonne composante familiale (j'ai regardé celui que j'utilise dans icefaces.taglib.xml) et le moteur de rendu de type correct.

Je ne veux pas modifier le modèle complet à cause de cela. Tous les conseils, comment cela peut être résolu?

Était-ce utile?

La solution

Nous pourrions résoudre le problème et correctement enregistrer notre moteur de rendu personnalisé.

Le problème était de trouver les bonnes propriétés pour le moteur de rendu prévu. Nos essais ont eu tort, car j'ai découvert comment obtenir les informations appropriées. Il est un peu de travail et de recherche, mais il a finalement fait l'affaire.

Il suffit de démarrer le conteneur en mode débogage et ajouter un point d'arrêt au niveau de la classe dans la classe dérivée personnalisée du moteur de rendu est basé sur (dans mon cas com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer).

Lors du démarrage contenant ce point d'arrêt sera atteint et dans le stacktrace, vous trouverez un appel de la méthode FacesConfigurator.configureRenderKits ().

Cet objet contient un ArrayList de équarrisseurs enregistrés. Je cherchai la liste pour le moteur de rendu que je l'aurais aimé remplacer et trouver les informations pouvais-je enregistrer mon renderer personnalisé. Dans mon cas, c'est l'entrée correcte dans les 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>

Maintenant, le getAsObject () - méthode dans le convertisseur est appelé par le moteur de rendu personnalisé. Assurez-vous de remplacer correctement la méthode, si vous ne voulez pas un convertisseur sur chaque objet 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);
}

Sinon, vous obtiendrez un NullPointerException.

PS: Il y a sûrement un moyen plus intelligent pour obtenir ces informations, mais je ne suis pas assez intelligent. ; -)

Autres conseils

Vous ne dites pas si vous utilisez Hibernate, mais je suppose que vous devez être pour que cela soit un problème. Avez-vous essayé le traitement de la numérique comme un booléen dans votre mapping?

Voir ce fil des forums Hibernate

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top