JSF-Backing-Bean-Struktur (Best Practices)

118

Ich hoffe, dass ich in diesem Beitrag die Meinung der Leute zu Best Practices für die Schnittstelle zwischen JSF-Seiten und Backing Beans einholen kann.

Eine Sache, auf die ich mich nie festlegen kann, ist die Struktur meiner Backing Beans. Außerdem habe ich nie einen guten Artikel zu diesem Thema gefunden.

Welche Eigenschaften gehören zu welchen Backing Beans? Wann ist es angebracht, einer bestimmten Bean mehr Eigenschaften hinzuzufügen, als eine neue Bean zu erstellen und die Eigenschaften hinzuzufügen? Ist es für einfache Anwendungen sinnvoll, nur eine einzige Backing Bean für die gesamte Seite zu haben, wenn man bedenkt, wie komplex es ist, eine Bean in eine andere zu injizieren? Sollte die Backing Bean eine tatsächliche Geschäftslogik enthalten oder sollte sie ausschließlich Daten enthalten?

Fühlen Sie sich frei, diese und andere Fragen zu beantworten.


Um die Kopplung zwischen der JSF-Seite und der Backing-Bean zu verringern, erlaube ich der JSF-Seite niemals, auf die Eigenschaften einer Backing-Bean-Eigenschaft zuzugreifen. Zum Beispiel erlaube ich niemals etwas wie:

<h:outputText value="#{myBean.anObject.anObjectProperty}" />

Ich brauche immer so etwas wie:

<h:outputText value="#{myBean.theObjectProperty}" />

mit einem Backing Bean-Wert von:

public String getTheObjectProperty()
{
    return anObject.getAnObjectProperty();
}

Wenn ich eine Sammlung durchlaufe, verwende ich eine Wrapper-Klasse, um beispielsweise einen Drilldown in ein Objekt in einer Datentabelle zu vermeiden.

Im Allgemeinen fühlt sich dieser Ansatz für mich "richtig" an. Es wird jegliche Kopplung zwischen der Ansicht und den Daten vermieden. Bitte korrigieren Sie mich, wenn ich falsch liege.

Zack Marrapese
quelle
Können Sie ein Beispiel geben für: Wenn ich eine Sammlung durchlaufe, verwende ich eine Wrapper-Klasse, um beispielsweise einen Drilldown in ein Objekt in einer Datentabelle zu vermeiden.
Koray Tugay
2
Weitere Informationen finden Sie in der Antwort von BalusC
Zack Marrapese

Antworten:

146

Vielleicht möchten Sie dies überprüfen: Unterscheiden zwischen verschiedenen Arten von JSF-verwalteten Beans .

Hier ist eine Beschreibung der verschiedenen Bohnensorten, wie im obigen Artikel von Neil Griffin definiert:

  • Model Managed-Bean : Normalerweise Sitzungsumfang. Diese Art von Managed-Bean nimmt am "Modell" -Anliegen des MVC-Entwurfsmusters teil. Wenn Sie das Wort "Modell" sehen, denken Sie an DATEN. Eine JSF-Modell-Bean sollte ein POJO sein, das dem JavaBean-Entwurfsmuster folgt und Getter / Setter enthält, die Eigenschaften kapseln. Der häufigste Anwendungsfall für eine Modell-Bean besteht darin, eine Datenbankentität zu sein oder einfach eine Reihe von Zeilen aus der Ergebnismenge einer Datenbankabfrage darzustellen.
  • Backing Managed-Bean : Normalerweise Umfang anfordern. Diese Art von Managed-Bean nimmt am "View" -Anliegen des MVC-Entwurfsmusters teil. Der Zweck einer Backing-Bean ist die Unterstützung der UI-Logik und hat eine 1: 1-Beziehung zu einer JSF-Ansicht oder einem JSF-Formular in einer Facelet-Komposition. Obwohl es normalerweise Eigenschaften im JavaBean-Stil mit zugehörigen Gettern / Setzern hat, sind dies Eigenschaften der Ansicht - nicht des zugrunde liegenden Anwendungsdatenmodells. JSF-Backing-Beans können auch die Methoden JSF actionListener und valueChangeListener enthalten.
  • Controller Managed-Bean : Normalerweise Umfang anfordern. Diese Art von Managed-Bean nimmt am "Controller" -Anliegen des MVC-Entwurfsmusters teil. Der Zweck einer Controller-Bean besteht darin, eine Art Geschäftslogik auszuführen und ein Navigationsergebnis an den JSF-Navigationshandler zurückzugeben. JSF-Controller-Beans verfügen normalerweise über JSF-Aktionsmethoden (und nicht über actionListener-Methoden).
  • Support Managed-Bean : Normalerweise Sitzungs- oder Anwendungsbereich. Diese Art von Bean "unterstützt" eine oder mehrere Ansichten im "View" -Anliegen des MVC-Entwurfsmusters. Der typische Anwendungsfall ist die Bereitstellung einer ArrayList für JSF h: selectOneMenu-Dropdown-Listen, die in mehr als einer JSF-Ansicht angezeigt werden. Wenn die Daten in den Dropdown-Listen spezifisch für den Benutzer sind, wird die Bean im Sitzungsbereich beibehalten. Wenn die Daten jedoch für alle Benutzer gelten (z. B. eine Dropdown-Liste der Provinzen), wird die Bean im Anwendungsbereich beibehalten, sodass sie für alle Benutzer zwischengespeichert werden kann.
  • Utility Managed-Bean : Normalerweise Anwendungsbereich. Diese Art von Bean bietet einer oder mehreren JSF-Ansichten eine Art "Dienstprogramm" -Funktion. Ein gutes Beispiel hierfür ist möglicherweise eine FileUpload-Bean, die in mehreren Webanwendungen wiederverwendet werden kann.
Cecemel
quelle
8
Dies ist ein großartiger Artikel. Ich habe es noch nie gesehen und bin auf jeden Fall froh, dass Sie es gepostet haben. Wer das abgelehnt hat, ist verrückt. Es ist nicht iceFaces-spezifisch.
Zack Marrapese
2
Der Link zum eigentlichen Artikel scheint verschwunden zu sein.
Bill Rosmus
Eine Kopie finden Sie hier
ChrLipp
10
Trotzdem kann ich nicht sagen, dass diese Antwort derzeit 71 positive Stimmen hat. Wer auch immer seine JSF-Anwendung nach diesen Regeln implementiert hat, muss sich danach zweifellos darauf verlassen, dass JSF ein schrecklich undurchsichtiges Framework ist und dass seine JSF-Anwendungen ein großes Code-Chaos darstellen, und alle geben JSF selbst die Schuld, anstatt ihren eigenen schlechten Ansatz, der auf den falschen Lehren und dem sogenannten basiert "Best Practices" gelernt.
BalusC
Wird eine der Logik dieser Beans im Browser anstatt auf dem Server ausgeführt?
Eskalera
14

Gute Frage. Ich hatte viel mit dem gleichen Dilemma zu kämpfen, als ich zu JSF wechselte. Es hängt wirklich von Ihrer Anwendung ab. Ich komme aus der Java EE-Welt, daher würde ich empfehlen, so wenig Geschäftslogik wie möglich in Ihren Backing Beans zu haben. Wenn sich die Logik ausschließlich auf die Präsentation Ihrer Seite bezieht, ist es in Ordnung, sie in der Backing Bean zu haben.

Ich glaube, eine der (vielen) Stärken von JSF ist tatsächlich die Tatsache, dass Sie Domänenobjekte direkt auf den verwalteten Beans verfügbar machen können. Ich würde den <:outputText value="#{myBean.anObject.anObjectProperty}" />Ansatz daher dringend empfehlen , da Sie sonst zu viel Arbeit für sich selbst aufwenden müssen, um jede Eigenschaft manuell freizulegen. Darüber hinaus wäre es beim Einfügen oder Aktualisieren von Daten ein bisschen chaotisch, wenn Sie alle Eigenschaften gekapselt hätten. Es gibt Situationen, in denen ein einzelnes Domänenobjekt möglicherweise nicht ausreicht. In diesen Fällen bereite ich ein ValueObject vor, bevor ich es auf der Bean verfügbar mache.

BEARBEITEN: Wenn Sie jede Objekteigenschaft kapseln möchten, die Sie verfügbar machen möchten, würde ich empfehlen, stattdessen UI-Komponenten an die Backing Bean zu binden und den Inhalt dann direkt in den Wert der Komponente einzufügen.

In Bezug auf die Bean-Struktur war der Wendepunkt für mich, als ich alles, was ich über das Erstellen von Webanwendungen wusste, mit Nachdruck ignorierte und stattdessen begann, es als GUI-Anwendung zu behandeln. JSF ahmt Swing stark nach, und daher gelten die Best Practices für die Entwicklung von Swing-Anwendungen meist auch für die Erstellung von JSF-Anwendungen.

Allan Lykke Christensen
quelle
Vielen Dank für Ihren Einblick. Ich habe nie wirklich viel in Bezug auf Swing-Anwendungen gemacht (außer bei akademischen Projekten vor langer Zeit). Was sind einige gute Prinzipien für Swing-Anwendungen? Warum ist es auch ein Chaos beim Einfügen und Aktualisieren von Werten? scheint mir das gleiche?
Zack Marrapese
5

Ich denke, das Wichtigste bei Ihren Backing Beans ist, ihre Logik zu trennen. Wenn Sie eine Startseite für ein CMS-System haben, würde ich es als schlechte Praxis ansehen, jeden Code in eine Bean zu packen, weil:

  1. Die Bohne würde irgendwann sehr groß werden
  2. Für andere Personen ist es einfacher zu finden, wonach sie suchen, wenn sie Fehler auf der Anmeldeseite beheben. Wenn sie dann einfach die Datei loginBean.java nachschlagen können.
  3. Manchmal haben Sie kleine Funktionen, die sich deutlich vom Rest Ihres Codes unterscheiden. Wenn Sie diese trennen, würde ich mir vorstellen, dass Sie es sich leichter machen würden, diesen Code in etwas Größeres umzuentwickeln / zu erweitern, wenn Sie bereits eine schöne Bohne mit gutem haben Struktur.
  4. Wenn Sie 1 große Bean haben, wird alles speicherabhängiger, wenn Sie Deklarationen wie diese ausführen müssen. MyBigBean bigBean = new MyBigBean (); anstatt die Funkjonalität zu verwenden, die Sie tatsächlich benötigen, indem Sie LoginBean ausführen loginBean = new LoginBean (); (Korrigiere mich, wenn ich hier falsch liege ???)
  5. Meiner Meinung nach ist das Trennen Ihrer Bohnen wie das Trennen Ihrer Methoden. Sie möchten nicht eine große Methode, die mehr als 100 Zeilen umfasst, sondern sie mit neuen Methoden aufteilen, die ihre spezifische Aufgabe erfüllen.
  6. Denken Sie daran, dass höchstwahrscheinlich auch eine andere Person als Sie an Ihren JSF-Projekten arbeiten muss.


Was die Kopplung betrifft, sehe ich es nicht als problematisch an, Ihren JSF-Seiten zu erlauben, auch auf die Eigenschaften von Objekten in Ihrer Backingbean zuzugreifen. Dies ist eine Unterstützung, die in JSF integriert ist und das Lesen und Erstellen von Imo wirklich erleichtert. Sie haben die MVC-Logik bereits strikt getrennt. Auf diese Weise sparen Sie sich Tonnen von Zeilen mit Gettern und Setzern in Ihrer Backingbean. Zum Beispiel habe ich ein wirklich großes Objekt, das mir von den Webdiensten zur Verfügung gestellt wird, wo ich einige Eigenschaften in meiner Präsentation verwenden muss. Wenn ich für jede Eigenschaft einen Getter / Setter erstellen würde, würde meine Bean mit mindestens 100 weiteren Zeilen von Variablen und Methoden zum Abrufen der Eigenschaften erweitert. Durch die Verwendung der integrierten JSF-Funktionalität werden meine Zeit und wertvolle Codezeilen geschont.

Nur meine 2 Cent dazu, auch wenn die Frage bereits als beantwortet markiert ist.

Chris Dale
quelle
1
Wenn Sie jedoch ein riesiges Objekt in Ihrer Bean haben und beispielsweise 15 EL-Funktionen haben, die von der JSF-Seite in dieses Objekt eingegraben werden, sind Sie jetzt nicht nur an die Bean, sondern auch an dieses Objekt gebunden. Daher ist es schwierig, dieses Objekt zu entfernen, ohne die Benutzeroberfläche zu beschädigen.
Zack Marrapese
1
Aber wird Ihre Backing Bean nicht auch an dieses Objekt gebunden sein? Und Ihre Benutzeroberfläche ist an die Backing Bean gebunden? Wenn Sie es dann ändern müssen, müssen Sie alle Ihre Getter / Setter sowohl in der Benutzeroberfläche als auch in der Bean ändern.
Chris Dale
4

Ich beantworte möglicherweise nicht jede Ihrer Fragen, da nur wenige von Fall zu Fall abhängig zu sein scheinen.

  • Dies ist in Ordnung, um eine Geschäftslogik in Ihrer Backing Bean zu haben. Es kommt darauf an, woher du kommst. Wenn Sie domänengesteuertes Design praktizieren, werden Sie versucht sein, die Geschäftslogik in die Backing Bean aufzunehmen, oder es kann sich auch um eine Persistenzlogik handeln. Sie argumentieren, warum so dummes Objekt. Das Objekt sollte nicht nur den Zustand, sondern auch das Verhalten enthalten. Wenn Sie jedoch die traditionelle Java EE-Methode in Betracht ziehen, haben Sie möglicherweise das Gefühl, Daten in Ihrer Backing Bean zu haben, die auch Ihre Entity Bean sein kann, und andere Geschäfts- und Persistenzlogiken in einer Session Bean oder so. Das ist auch gut so.

  • Es ist vollkommen in Ordnung, eine einzelne Backing Bean für die ganze Seite zu haben. Ich sehe allein damit kein Problem. Das sieht vielleicht nicht richtig aus, aber das hängt vom Fall ab.

  • Ihre andere Frage hängt viel mehr von dem Fall ab, den Sie in der Hand haben. Ich würde es vorziehen, hier domänengesteuert zu sein. Es könnte angebracht sein, Eigenschaften zu den vorhandenen hinzuzufügen oder auf andere Weise eine neue Bean dafür zu erstellen. Was immer besser passt. Ich glaube nicht, dass es dafür eine Silberkugel gibt.

  • Welche Eigenschaften zu welcher Backing Bean gehören. Nun, hängt es nicht vom Domain-Objekt ab? Oder vielleicht ist die Frage nicht so klar.

Darüber hinaus sehe ich in Ihrem angegebenen Codebeispiel keinen großen Vorteil.

Adeel Ansari
quelle
Wenn wir beispielsweise von selbst gebrauten POJOs, die mit JDBC-Abfragen erstellt wurden, zu Hibernate-Entitäten mit leicht unterschiedlichen Feldnamen wechseln würden, müssten wir nicht nur die Backing Bean ändern. Wir müssten auch die JSF-Seite ändern. Nicht so bei meinem Codebeispiel. Wechseln Sie einfach die Bohne.
Zack Marrapese
In diesem Fall können Sie Ihre Backing Beans und Entitäten erstellen. Dann müssen Sie nur noch die JSF-Seiten ändern. Oder hängt es davon ab, warum Sie den Namen der Eigenschaften überhaupt ändern würden? Dies ist nur dann sinnvoll, wenn Sie das Feld so umbenennen, dass es Ihrem Datenbankspaltennamen entspricht. Aber das ist insgesamt ein anderer Fall.
Adeel Ansari
4

Ich würde nicht unbedingt nur eine Backing Bean pro Seite behalten. Es hängt von der Funktionalität ab, aber die meiste Zeit hatte ich eine Bean pro Seite, da meistens eine Seite eine Funktionalität handhabt. Zum Beispiel habe ich auf einer Seite einen Registerlink (ich werde mit RegisterBean verknüpfen) und einen Warenkorblink (ShoopingBasketBean).

Ich verwende diesen <: outputText value = "# {myBean.anObject.anObjectProperty}" />, da ich normalerweise Backing Beans als Action Beans halte, die Datenobjekte enthalten. Ich möchte keinen Wrapper in meine Backing Bean schreiben, um auf die Eigenschaften meiner Datenobjekte zuzugreifen.

Bhushan Bhangale
quelle
0

Ich teste gerne Geschäftscode ohne Ansichten, daher betrachte ich BackingBeans als Schnittstellen von Ansicht zu Modellcode. Ich habe niemals eine Regel oder einen Prozess in eine BackingBean eingefügt. Dieser Code geht in Dienste oder Helfer und ermöglicht die Wiederverwendung.

Wenn Sie Validatoren verwenden, löschen Sie diese aus Ihrer BackingBean und verweisen Sie auf sie aus Ihrer Validierungsmethode.

Wenn Sie auf DAOs zugreifen, um Selects, Radios, Checkboxes zu füllen, tun Sie dies immer aus einer BackingBean heraus.

Glaube mir!. Sie können eine JavaBean in eine BackingBean einfügen, aber versuchen, eine BackingBean in eine andere einzufügen. Sie werden bald in einem Nigntraum der Wartung und des Verständnisses von Code sein.

jjruiz
quelle