2016-04-07 16 views
1

Ich bin neu in JSF und habe Probleme damit, Daten an meine Backing-Bean zu übergeben. Ich habe eine Bohne, die Daten zu einer spezifischen Tabelle lesen und speichern sollte. Diese Tabelle hat zwei Spalten "Eigenschaft" und "Val". Die vereinfachte Version dieser Klasse sieht folgendermaßen aus:Bestehe das Initialisierungsargument von der JSF-Ansicht zur verwalteten Bean im Hintergrund

@ManagedBean 
@SessionScoped 
public class GlobalProperties implements Serializable { 

    // private void setKey(param); 
    // private String getKey();  
    // some more attributes and getters/setters 
    private String property; // + getter/setter  

    private void saveProperty() throws SQLException { 
     try { 
      dbHandler = dbConnection.connect(); 
      ps = dbHandler.prepareStatement("UPDATE TABLEXXX SET VAL = '" + getValue() + "' WHERE PROPERTYKEY = '" + getProperty() + "'"); 
      ps.executeQuery(); 
      } catch (SQLException ex) { 
      Logger.getLogger(GlobalProperties.class.getName()).log(Level.SEVERE, null, ex); 
      } finally { 
      if (dbHandler != null) { 
       dbHandler.close(); 
      } 
     }   
    } 

    private void readProperty() throws SQLException { 
     try { 
      dbHandler = dbConnection.connect(); 
      ps = dbHandler.prepareStatement("SELECT VAL FROM TABLEXXX WHERE PROPERTYKEY = '" + getProperty() + "'"); 
      rs = ps.executeQuery(); 
      while (rs.next()) { 
       setValue("VAL"); 
      } 
     } catch (SQLException ex) { 
      Logger.getLogger(GlobalProperties.class.getName()).log(Level.SEVERE, null, ex); 
     } finally { 
      if (dbHandler != null) { 
       dbHandler.close(); 
      } 
     }  
    }   
} 

Diese Klasse wird auf mehreren Seiten verwendet. Auf jeder Seite, die es benutzt, muss es mit einem anderen Wert für das property-Attribut gefüllt werden, da ich verschiedene Schlüssel aus der Tabelle lesen muss. Auf der JSF-Seite gibt es eine Texteingabe, die den Wert anzeigt und ihn einstellt, wenn der Benutzer auf eine Schaltfläche zum Speichern klickt.

Immer wenn eine Instanz dieser Klasse erstellt wird, muss ich der Klasse Informationen darüber geben, welchen Schlüssel sie lesen muss. Aber ich kann keinen geeigneten Mechanismus auf JSF-Seite finden, um dies zu erreichen, da es sehr wichtig ist, dass der Benutzer diesen Wert nicht ändern kann.

Mein letzter Versuch war die "preRenderView" -Event wie folgt zu verwenden:

<f:metadata> 
     <f:event type="preRenderView" listener="#{globalProperties.setKey('SYSTEM_NAME')}" /> 
    </f:metadata> 

Ist das der richtige Weg?

Was ist die beste Vorgehensweise, um eine Eigenschaft in einer ManagedBean im Hintergrund ohne Benutzeraktion und auf sichere Weise festzulegen, damit sie vom Benutzer nicht manipuliert werden kann?

Danke Jungs.

Antwort

2

<f:event type="preRenderView"> wird bei jeder Anfrage aufgerufen. Dies ist möglicherweise für anforderungsbereichsabhängige Beans in Ordnung, ist jedoch für die auf die Sicht/Sitzung beschränkten Beans nicht erforderlich. Siehe auch What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?

Auf der anderen Seite, während die preRenderView Ansatz funktioniert, sollte die JSF-Ansicht deklarativ sein. Das Modell (die Backing-Bean in dieser speziellen Perspektive) sollte die Initialisierung tatsächlich basierend auf der Ansicht durchführen und nicht umgekehrt. Also war deine Intuition richtig, als du Zweifel daran hast.

JSF hat keinen dedizierten Ansatz dafür. Der nächste deklarative Ansatz verwendet <f:attribute> in <f:metadata> ("definieren Sie ein Metadatenattribut für die Ansicht").

<f:metadata> 
    <f:attribute name="key" value="SYSTEM_NAME" /> 
</f:metadata> 

Dies ist durch UIViewRoot#getAttributes() in ao @PostConstruct verfügbar:

String key = (String) context.getViewRoot().getAttributes().get("key"); 

Oder, wenn Sie passieren OmniFaces verwenden:

String key = Faces.getMetadataAttribute("key"); 

Die OmniFaces präsentieren auch diesen Ansatz verwendet Pfade zu erklären Anwendung Dokumentation und Quellcode (siehe zum Beispiel /push/socket.xhtml source von <o:socket> showcase).

Der alternative Ansatz besteht in einer anwendungsweiten Zuordnung von Schlüsseln nach Ansichts-ID und stattdessen auf der Ansichts-ID.

Map<String, String> keysByViewId = new HashMap<>(); 
keysByViewId.put("/foo.xhtml", "SYSTEM_NAME"); 

String key = keysByViewId.get(context.getViewRoot().getViewId()); 
+0

Große Antwort. Geholfen! Vielen Dank. – Caz

+0

Gern geschehen. – BalusC