Frage

Wir haben numerische Werte in unserer Datenbank, die einen Zwei-Wert-Zustandes. Natürlich wäre dies perfekt ein boolean passen, aber Orakel hat keinen solchen Datentyp. Die NUMBER (1,0) von der Datenbank wird in Java zu einem java.lang.Short Typ abgestimmt (manchmal benutzten sie einen NUMBER (*, 0) booleans darzustellen, die java.math.BigDecimal abgestimmt sind).

Da es irgendwie offensichtlich ist, möchte ich Angebot Eis: selectBooleanCheckbox in der Ansicht als Wertdarstellung und UIComponent an den Benutzer. (Ich benutze IceFaces als JSF-Implementierung)

Da einige Leute, die JSF angegeben denke, es liegt auf der Hand, den Wert eines Eis immer übereinstimmen: selectBooleanCheckbox oder in JSF h: selectBooleanCheckbox zu einem boolean im Modell, so dass der Renderer der Komponente nie Konverter aufruft, auch wenn Sie geben Sie eine: Ausgabe disscused bei java.net

Deshalb habe ich versucht, die folgenden:

habe ich einen Konverter in der UIComponent angeben:

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

Der Konverter funktioniert gut für die Phase machen (die getAsString-Methode korrekt genannt), aber die getAsObject-Methode (Ignorieren Sie, dass es im Moment nicht richtig ist, weil es sowieso nicht genannt wird, so wird es repariert werden, wenn sie aufgerufen werden !, weil in den Renderer der UIComponent) niemals ein Konverter nicht vorhergesehenen genannt wird, ist, wie man hier sehen kann (schnippeln von 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);
 }

So Dies führt zu einem Illegal, da in der UpdateModelValues ??Phase versucht wird, einen Booleschen auf einen numerischen Wert anzuwenden (bitte BigDecimal / Short Verwirrung ignorieren ... es ist nur eine numerische Art in jedem Fall!).

So habe ich versucht, den Renderer mit einem neuen so zu überschreiben:

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

und registriert es wie folgt in 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>

ich denke, dies sollte korrekt sein, aber die überschriebene Methode „getConvertedValue“ wird nie genannt, noch ist die getAsObject () - Methode, also denke ich, ich habe einen Fehler gemacht die benutzerdefinierten Renderer in der Registrierung, aber ich kann nicht finden mehr Dokumentation oder Hinweise, wie diese richtig zu machen und vor allem, wie die richtige Komponente-Familie zu finden (ich die eine nachgeschlagen ich in icefaces.taglib.xml verwenden) und den korrekten Renderer-Typ ist.

Ich will nicht das komplette Modell zu bearbeiten, weil dieser. Für Hinweise, wie diese gelöst werden können?

War es hilfreich?

Lösung

Wir können das Problem beheben und richtig unsere eigenen Renderer registrieren.

Das Problem bestand darin, die richtigen Eigenschaften für den vorgesehenen Renderer zu finden. Unsere Versuche waren falsch, da ich herausgefunden, wie die entsprechenden Informationen zu erhalten. Es ist ein bisschen Arbeit und Suche, aber es hat schließlich den Trick.

Sie Ihre Container im Debug-Modus starten und einen Haltepunkt auf Klassenebene in der abgeleiteten Klasse der benutzerdefinierten Renderer basiert auf ist (in meinem Fall com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer) hinzuzufügen.

Während Container Inbetriebnahme dieser Haltepunkt erreicht wird und in der stacktrace erhalten Sie einen Anruf von der Methode FacesConfigurator.configureRenderKits finden ().

Dieses Objekt enthält eine Arraylist von registrierten Renderer. Ich suchte die Liste für den Renderer ich gemocht hätte überschrieben werden und die Informationen Ich brauche finden konnten, zu meinen benutzerdefinierten Renderer zu registrieren. In meinem Fall ist dies der richtige Eintrag in 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>

Nun ist die getAsObject () - Methode in dem Konverter wird durch die benutzerdefinierten Renderer genannt. Seien Sie sicher, dass das Verfahren korrekt außer Kraft zu setzen, können Sie, falls Sie nicht einen Konverter auf jedem SelectBooleanCheckbox Objekt wollen:

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

Ansonsten erhalten Sie eine Nullpointer erhalten.

PS: Es ist sicherlich ein intelligenter Weg, um diese Informationen zu erhalten, aber ich bin nicht klug genug. ; -)

Andere Tipps

Sie müssen nicht sagen, ob Sie den Ruhezustand verwenden, aber ich nehme an, dass Sie sein müssen, damit dies ein Problem sein. Haben Sie versucht, die Behandlung der numerischen als boolean in Ihrem Mapping?

Sehen Sie diesen Thread aus dem Hibernate-Foren

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top