2013-01-09 16 views
7

È necessario utilizzare alcuni dati salvati in un bean con ambito di visualizzazione in un altro bean con ambito di visualizzazione.L'iniezione di un bean con ambito vista in un altro bean con ambito di visualizzazione ne consente la creazione

@ManagedBean 
@ViewScoped 
public class Attivita implements Serializable { 
    // 
} 

e

@ManagedBean 
@ViewScoped 
public class Nota implements Serializable { 

    @ManagedProperty("#{attivita}") 
    private Attivita attivita; 

    // Getter and setter. 
} 

Ora, forse la mia teoria in proposito è ancora piuttosto scarsa, ho notato che quando #{attivita} viene iniettato, il costruttore Attivita viene richiamato e creando così un'altra istanza. È il comportamento giusto? Che dire se voglio fare riferimento alla stessa istanza e non crearne una nuova?

+0

Fare attenzione a contrassegnare le risposte corrette.L'overflow dello stack non riguarda solo le domande, ma anche le risposte. –

risposta

13

Ciò accade se si sta navigando da uno all'altro vista su un postback . Un bean con scope vista non è legato a una richiesta, ma a una vista. Pertanto, quando si passa a una nuova vista, si otterrà una nuova istanza del bean con ambito di visualizzazione. Non riutilizzerà la stessa istanza di bean associata a una vista precedente.

Capisco che il bean attivita venga creato nella vista iniziale e riutilizzato nel postback. Capisco che il bean nota sia associato alla nuova vista alla quale stai navigando. Quando si inietta attivita in esso, otterrà semplicemente un'istanza nuova e distinta anche se c'è un'altra istanza nella stessa richiesta. Tutto ciò è previsto (e, ammettiamolo, un po 'non intuitivo) comportamento.

Non esiste una soluzione JSF standard per questo. CDI risolve questo problema con @ConversationScoped (il bean vive finché glielo dici esplicitamente di vivere) e l'estensione CDI MyFaces CODI va un po 'oltre con @ViewAccessScoped (il bean vive finché la vista navigata lo fa riferimento).

È tuttavia possibile aggirare il problema memorizzando il bean come attributo nell'ambito della richiesta.

@ManagedBean 
@ViewScoped 
public class Attivita implements Serializable { 

    public String submit() { 
     FacesContext.getCurrentInstance().getExternalContext() 
      .getRequestMap().put("attivita", this); 
     return "nota"; 
    } 

} 

e

@ManagedBean 
@ViewScoped 
public class Nota implements Serializable { 

    private Attivita attivita; 

    @PostConstruct 
    public void init() { 
     attivita = (Attivita) FacesContext.getCurrentInstance().getExternalContext() 
      .getRequestMap().get("attivita"); 
    } 

} 

Si noti che questo è piuttosto hacky. Potrebbero esserci soluzioni migliori a seconda del requisito funzionale concreto. Si noti inoltre che nella vista nota fare riferimento all'istanza del bean Attivita desiderata come #{nota.attivita} e non come #{attivita}, perché fornirebbe un'istanza nuova e diversa, per i motivi già illustrati in precedenza.

+0

Questo funziona di sicuro - Ho avuto lo stesso problema. Tuttavia, è molto hacky come hai affermato, ed è ancora UN'ALTRA lacuna di JSF. Elimina le finalità di CDI o Proprietà gestite quando devi aggiungere un PostConstruct e devi estrarre manualmente un bean dal contesto di Faces. Esiste un piano per aggiungere @ViewAccessScoped all'API JSF standard e non solo come parte di Myfaces? – GreenieMeanie

+0

@GreenieMeanie: JSF 2.2 ha aggiunto '@ FlowScoped' per coprire questo problema, ma sfortunatamente richiede ancora un po 'di configurazione XML e parametri di richiesta generati automaticamente, poiché ha anche bisogno di sopravvivere alle richieste GET. È, diciamo, tra '@ ViewAccessScoped' e' @ SessionScoped'. Come probabile "soluzione migliore", puoi pensare di ridirigerla con ID entità come param, o eseguire il rendering condizionale della stessa vista con un'altra inclusione. Vedi anche a.o. http://stackoverflow.com/questions/15521451/how-to-navigate-in-jsf-how-to-make-url-reflect-current-page-and-not-previous-o – BalusC

+0

Stai suggerendo di vedere a.xhtml hanno un "fittizio" incluso in b.xhtml e forse avvolgono tutto il contenuto di b.xhtml in un enorme ui: frammento che in realtà rende qualsiasi cosa solo quando viene reindirizzato a (tramite b.xhtml) e NON quando è incluso come riferimento fittizio da a.xhtml? – GreenieMeanie

1

Il bean attivita è @ViewScoped e ciò non garantisce che l'istanza venga trattenuta in sessione. Hai bisogno di un bean @SessionScoped. Tuttavia, se hai bisogno di attivita per qualche motivo per essere @ViewScoped, puoi passare i parametri attraverso di essi in altri modi, ad es. utilizzando viewParam o utilizzando altro bean @SessionScoped tra di loro.

Pagina Parametri

http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/

JSF 2 Managed Bean Scopes

http://balusc.blogspot.com.es/2011/09/communication-in-jsf-20.html#ManagedBeanScopes

Problemi correlati