Struttura del backing bean JSF (best practice)


118

Spero che in questo post posso ottenere le opinioni delle persone sulle migliori pratiche per l'interfaccia tra le pagine JSF e i backing bean.

Una cosa su cui non riesco mai a stabilirmi è la struttura dei miei fagioli di sostegno. Inoltre, non ho mai trovato un buon articolo sull'argomento.

Quali proprietà appartengono a quali fagioli di supporto? Quando è appropriato aggiungere più proprietà a un dato bean invece di creare un nuovo bean e aggiungervi le proprietà? Per applicazioni semplici, ha senso avere un solo backing bean per l'intera pagina, considerata la complessità legata all'iniezione di un bean in un altro? Il backing bean dovrebbe contenere una logica di business effettiva o contenere rigorosamente dati?

Sentiti libero di rispondere a queste e ad altre domande che potrebbero sorgere.


Per quanto riguarda la riduzione dell'accoppiamento tra la pagina JSF e il backing bean, non permetto mai alla pagina JSF di accedere alle proprietà del backing bean. Ad esempio, non permetto mai qualcosa come:

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

Ho sempre bisogno di qualcosa come:

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

con un valore del fagiolo di supporto di:

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

Quando eseguo il ciclo su una raccolta, utilizzo una classe wrapper per evitare di eseguire il drill-down in un oggetto in una tabella di dati, ad esempio.

In generale, questo approccio mi sembra "giusto". Evita qualsiasi accoppiamento tra la vista e i dati. Per favore correggimi se sbaglio.


Puoi fornire un esempio per: Quando eseguo il ciclo su una raccolta, utilizzo una classe wrapper per evitare di eseguire il drill down in un oggetto in una tabella di dati, ad esempio.
Koray Tugay

2
Per ulteriori informazioni, vedere la risposta di BalusC a stackoverflow.com/questions/7223055/...
Zack Marrapese

Risposte:


146

Potresti voler controllare questo: fare distinzioni tra diversi tipi di bean gestiti JSF .

Ecco una descrizione dei diversi tipi di fagioli, come definiti nell'articolo di Neil Griffin sopra:

  • Model Managed-Bean : normalmente ambito di sessione. Questo tipo di bean gestito partecipa alla preoccupazione "Modello" del modello di progettazione MVC. Quando vedi la parola "modello", pensa a DATA. Un model-bean JSF dovrebbe essere un POJO che segue il design pattern JavaBean con proprietà di incapsulamento getter / setter. Il caso d'uso più comune per un bean modello è quello di essere un'entità di database o semplicemente rappresentare un insieme di righe dal set di risultati di una query di database.
  • Backing Managed-Bean : Normalmente richiedere l'ambito. Questo tipo di bean gestito partecipa alla preoccupazione "Visualizza" del modello di progettazione MVC. Lo scopo di un backing-bean è supportare la logica dell'interfaccia utente e ha una relazione 1 :: 1 con una vista JSF o un modulo JSF in una composizione Facelet. Sebbene in genere abbia proprietà in stile JavaBean con getter / setter associati, queste sono proprietà della vista, non del modello dati dell'applicazione sottostante. I backing-bean JSF possono anche avere i metodi actionListener e valueChangeListener JSF.
  • Controller Managed-Bean : normalmente richiede l'ambito. Questo tipo di bean gestito partecipa alla preoccupazione "Controller" del modello di progettazione MVC. Lo scopo di un bean controller è eseguire un qualche tipo di logica aziendale e restituire un risultato di navigazione al gestore di navigazione JSF. I bean controller JSF in genere hanno metodi di azione JSF (e non metodi actionListener).
  • Support Managed-Bean : normalmente ambito di sessione o applicazione. Questo tipo di bean "supporta" una o più viste nell'ambito della "Visualizzazione" del modello di progettazione MVC. Il caso d'uso tipico è fornire un ArrayList a JSF h: elenchi a discesa selectOneMenu che appaiono in più di una vista JSF. Se i dati negli elenchi a discesa sono specifici per l'utente, il bean verrà mantenuto nell'ambito della sessione. Tuttavia, se i dati si applicano a tutti gli utenti (come un elenco a discesa di province), il bean verrà mantenuto nell'ambito dell'applicazione, in modo che possa essere memorizzato nella cache per tutti gli utenti.
  • Utility Managed-Bean : normalmente ambito dell'applicazione. Questo tipo di bean fornisce un qualche tipo di funzione "utilità" a una o più viste JSF. Un buon esempio di ciò potrebbe essere un bean FileUpload che può essere riutilizzato in più applicazioni web.

8
Questo è un grande articolo. Non l'ho mai visto prima e sono decisamente contento che tu l'abbia postato. Chiunque abbia votato per questo è pazzo. Non è specifico per IceFaces.
Zack Marrapese

2
Il collegamento all'articolo effettivo sembra essere andato.
Bill Rosmus

Una copia può essere trovata qui
ChrLipp

10
Tuttavia, non riesco a capire che questa risposta è attualmente a 71 voti positivi. Chiunque abbia implementato la propria applicazione JSF secondo quelle regole deve indubbiamente in seguito lamentarsi sul fatto che JSF è un framework terribilmente opaco e le loro applicazioni JSF sono un grande pasticcio di codice e tutti incolpano JSF stesso invece del proprio cattivo approccio basato sulle lezioni sbagliate e il cosiddetto "buone pratiche" apprese.
BalusC

la logica di questi bean viene eseguita nel browser invece che nel server?
eskalera

14

Ottima domanda. Ho sofferto molto con lo stesso dilemma quando sono passato a JSF. Dipende davvero dalla tua applicazione. Vengo dal mondo Java EE, quindi consiglierei di avere il minor numero possibile di logica aziendale nei tuoi backing bean. Se la logica è puramente correlata alla presentazione della tua pagina, allora va bene averla nel backing bean.

Credo che uno dei (molti) punti di forza di JSF sia in realtà il fatto che puoi esporre gli oggetti di dominio direttamente sui bean gestiti. Raccomando quindi vivamente l' <:outputText value="#{myBean.anObject.anObjectProperty}" />approccio, altrimenti finisci per lavorare troppo per te stesso nell'esporre manualmente ogni proprietà. Inoltre sarebbe un po 'un pasticcio durante l'inserimento o l'aggiornamento dei dati se si incapsulassero tutte le proprietà. Esistono situazioni in cui un singolo oggetto di dominio potrebbe non essere sufficiente. In questi casi preparo un ValueObject prima di esporlo sul bean.

EDIT: In realtà, se hai intenzione di incapsulare ogni proprietà dell'oggetto che desideri esporre, ti consiglio di associare i componenti dell'interfaccia utente al bean di supporto e quindi iniettare il contenuto direttamente nel valore del componente.

In termini di struttura dei bean, il punto di svolta per me è stato quando ho ignorato con la forza tutto ciò che sapevo sulla creazione di applicazioni web e ho iniziato a trattarlo invece come un'applicazione GUI. JSF imita molto Swing e quindi le migliori pratiche per lo sviluppo di applicazioni Swing si applicherebbero principalmente anche alla creazione di applicazioni JSF.


Grazie per la tua intuizione. Non ho mai fatto molto in termini di applicazioni swing (a parte i progetti accademici molto tempo fa). Quali sono alcuni buoni principi per le applicazioni swing? Inoltre, perché è un disastro durante l'inserimento e l'aggiornamento dei valori? a me sembra lo stesso?
Zack Marrapese

5

Penso che la cosa più importante con i tuoi backing bean sia separare le loro logiche. Se hai una prima pagina per un sistema CMS, vedrei come una cattiva pratica mettere ogni pezzo di codice in un bean perché:

  1. Alla fine il fagiolo diventerebbe molto grande
  2. È più facile per altre persone trovare ciò che stanno cercando se stanno risolvendo i problemi con la pagina di accesso, se poi possono facilmente cercare il file loginBean.java.
  3. A volte hai piccole funzionalità che sono chiaramente distinte dal resto del tuo codice, separando questo immagino che renderesti più facile per te stesso riqualificare / espandere questo codice in qualcosa di più grande, quando hai già un bel fagiolo con del bene struttura.
  4. Avere 1 big bean, per fare tutto, lo renderà più dipendente dalla memoria se / quando devi fare dichiarazioni come questa MyBigBean bigBean = new MyBigBean (); invece di utilizzare la funksjonality di cui hai effettivamente bisogno facendo LoginBean loginBean = new LoginBean (); (Correggimi se sbaglio qui ???)
  5. Secondo me, separare i tuoi fagioli è come separare i tuoi metodi. Non vuoi un grande metodo che funzioni su centinaia di righe, ma piuttosto dividerlo con nuovi metodi che gestiscono il loro compito specifico.
  6. Ricorda, molto probabilmente qualcun altro oltre a te dovrà lavorare anche sui tuoi progetti JSF.


Per quanto riguarda l'accoppiamento, non vedo come un problema fastidioso consentire alle tue pagine JSF di accedere anche alle proprietà negli oggetti nel tuo backingbean. Questo è il supporto integrato in JSF e semplifica la lettura e la creazione di imo. Stai già separando rigorosamente la logica MVC. In questo modo risparmierai tonnellate di linee con getter e setter nel tuo backingbean. Ad esempio, ho un oggetto davvero enorme che mi è stato dato dai servizi web, dove ho bisogno di utilizzare alcune proprietà nella mia presentazione. Se dovessi creare un getter / setter per ogni proprietà, il mio bean si espanderebbe con almeno altre 100 righe di variabili e metodi per ottenere le proprietà. Utilizzando la funzionalità JSF integrata, il mio tempo e preziose linee di codice vengono risparmiati.

Solo i miei 2 centesimi riguardo a questo anche con la domanda già contrassegnata come risposta.


1
tuttavia, se hai un oggetto enorme che si trova nel tuo bean, e hai - diciamo - 15 funzioni EL che scavano in quell'oggetto dalla pagina JSF, ora sei legato non solo al bean, ma a quell'oggetto. Pertanto sarà difficile rimuovere quell'oggetto senza interrompere l'interfaccia utente.
Zack Marrapese

1
Ma il tuo fagiolo di supporto non sarà legato anche a quell'oggetto? E la tua interfaccia utente è legata al backing bean? Quando poi dovrai modificarlo, dovrai cambiare tutti i tuoi getter / setter sia nell'interfaccia utente che nel bean.
Chris Dale,

4

Potrei non rispondere a tutte le tue domande, perché poche sembrano abbastanza dipendenti da caso a caso.

  • Va bene avere una logica di business nel tuo backing bean. Dipende da dove vieni. Se pratichi la progettazione guidata dal dominio, sarai tentato di includere la logica di business nel backing bean o potrebbe essere anche la logica di persistenza. Sostengono che perché così stupido oggetto. L'oggetto non dovrebbe avere solo uno stato ma anche un comportamento. D'altra parte, se consideri il modo tradizionale di fare le cose Java EE, potresti avere la sensazione di avere dati nel tuo backing bean, che può anche essere il tuo entity bean, e altre logiche di business e persistenza in qualche session bean o qualcosa del genere. Anche questo va bene.

  • Va benissimo avere un unico fagiolo di supporto per l'intera pagina. Non vedo alcun problema solo con questo. Potrebbe non sembrare corretto, ma dipende dal caso.

  • La tua altra domanda dipende molto più dal caso che hai in mano. Preferirei passare al dominio guidato qui, potrebbe essere appropriato aggiungere proprietà all'esistente o altrimenti creare un nuovo bean per quello. Che si adatta sempre meglio. Non credo che ci sia un proiettile d'argento per questo.

  • Quali proprietà appartiene a quale fagiolo di supporto. Bene, non dipende dall'oggetto del dominio? O forse la domanda non è così chiara.

Inoltre, nel tuo esempio di codice fornito, non vedo alcun vantaggio enorme.


se, ad esempio, dovessimo passare dall'utilizzo di POJO fatti in casa creati con query JDBC, a entità di Hibernate che hanno nomi di campo leggermente diversi, non dovremmo solo cambiare il backing bean. Dovremmo cambiare anche la pagina JSF. Non così con il mio esempio di codice. Basta cambiare il fagiolo.
Zack Marrapese

In tal caso puoi creare i tuoi fagioli, entità. allora devi solo cambiare le pagine JSF. Oppure dipende perché cambiereste comunque il nome delle proprietà? ciò avrebbe senso solo quando si rinomina il campo in modo che corrisponda al nome della colonna del database. Ma questo è un caso completamente diverso.
Adeel Ansari

4

Non sarebbe necessario mantenere un solo backing bean per pagina. Dipende dalla funzionalità, ma la maggior parte delle volte avevo un bean per pagina poiché principalmente una pagina gestisce una funzionalità. Ad esempio su una pagina ho un link di registrazione (mi collegherò a RegisterBean) e un link al carrello (ShoopingBasketBean).

Uso questo <: outputText value = "# {myBean.anObject.anObjectProperty}" /> poiché normalmente continuo a supportare i bean come action bean che contengono oggetti dati. Non voglio scrivere un wrapper nel mio backing bean per accedere alle proprietà dei miei oggetti dati.


0

Mi piace testare il codice aziendale senza View, quindi considero BackingBeans come interfacce da View a Model code. Non ho mai inserito alcuna regola o processo in un BackingBean. Quel codice entra nei servizi o negli helper, consentendone il riutilizzo.

Se usi validatori, mettili fuori dal tuo BackingBean e riferiscili dal tuo metodo di validazione.

Se accedi a DAO per riempire Selects, Radio, Checkboxes, fallo sempre da un BackingBean.

Credimi!. Puoi iniettare un JavaBean in un BackingBean, ma prova a iniettare un BackingBean in un altro. Sarai presto in un incubo di manutenzione e comprensione del codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.