Come sostituire @ManagedBean / @ViewScope con CDI in JSF 2.0 / 2.1

Attualmente sto valutando Java EE 6 / JSF 2.1 con RichFaces.

Un fagiolo che è dichiarato come

@ManagedBean @ViewScoped 
  1. Ottiene un set ID (per preparare ad esempio un’operazione di cancellazione).
  2. Tramite JSF viene visualizzato un popup di conferma.
  3. Se l’utente conferma, il metodo delete viene richiamato e rimuove la riga per la quale l’ID è stato memorizzato nel passaggio 1.

Poiché i bean CDI non hanno un ViewScope, ho provato a dichiarare il bean come:

 @Named @ConversationScoped 

Ora l’elaborazione non riesce nel passaggio 3. poiché il valore impostato nel passaggio 1 (controllato) non è più disponibile.

Devo utilizzare i metodi Conversation.begin() e Conversation.end() ?

Se sì, dove sarebbe il posto giusto per invocarli?

Se è ansible eseguire l’aggiornamento a JSF 2.2, farlo immediatamente. Offre un’annotazione nativa @ViewScoped per CDI.

 import javax.faces.view.ViewScoped; import javax.inject.Named; @Named @ViewScoped public class Bean implements Serializable { // ... } 

In alternativa, installa OmniFaces che porta il proprio CDI compatibile @ViewScoped , incluso un @PreDestroy funzionante (che è interrotto su JSF @ViewScoped ).

 import javax.inject.Named; import org.omnifaces.cdi.ViewScoped; @Named @ViewScoped public class Bean implements Serializable { // ... } 

Un’altra alternativa è installare MyFaces CODI che @ViewScoped in modo trasparente JSF 2.0 / 2.1 @ViewScoped a CDI. Questo aggiunge solo un parametro di richiesta @ConversationScoped all’URL (come farebbe @ConversationScoped ).

 import javax.faces.bean.ViewScoped; import javax.inject.Named; @Named @ViewScoped public class Bean implements Serializable { // ... } 

Se hai davvero bisogno di usare @ConversationScoped , allora devi effettivamente inizializzarlo e terminarlo. Devi @Inject una Conversation e invocare begin() nella @PostConstruct e end() nell’ultima fase della conversazione, solitamente un metodo di azione che reindirizza a una nuova vista.

 import javax.enterprise.context.Conversation; import javax.enterprise.context.ConversationScoped; import javax.inject.Named; @Named @ConversationScoped public class Bean implements Serializable { @Inject private Conversation conversation; // ... @PostConstruct public void init() { conversation.begin(); } public String submit() { // ... conversation.end(); return "some.xhtml?faces-redirect=true"; } } 

Guarda anche:

  • Come scegliere l’ambito del bean giusto?

Penso che puoi trarre vantaggio dall’estensione CDI per creare il tuo ambito personale in modo da poter implementare il contesto e utilizzare @NormalScope .

  • CDI AfterBeanDiscovery un evento AfterBeanDiscovery dopo ogni chiamata bean
  • È ansible utilizzare l’estensione CDI su @Observes questo evento e aggiungere l’implementazione del contesto
  • Nell’implementazione del tuo ambito puoi:
    1. Usa Contextual per ottenere il tuo bean con il suo nome dalla Map FacesContext ViewRoot e restituirlo dopo ogni chiamata ajax
    2. Usa CreationalContext se non si trova il nome del bean dal primo passaggio per crearlo nella ViewRoot Map ViewRoot

Per una spiegazione più approfondita, raccomando questo link: http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/

Iniettare la conversazione nel bean e nel metodo @PostConstructor avviare la conversazione se la conversazione è transitoria.

E dopo aver eliminato il record, termina la conversazione e vai alla pagina di destinazione. Quando si inizia una conversazione. Ecco un esempio

 public class BaseWebBean implements Serializable { private final static Logger logger = LoggerFactory.getLogger(BaseWebBean.class); @Inject protected Conversation conversation; @PostConstruct protected void initBean(){ } public void continueOrInitConversation() { if (conversation.isTransient()) { conversation.begin(); logger.trace("conversation with id {} has started by {}.", conversation.getId(), getClass().getName()); } } public void endConversationIfContinuing() { if (!conversation.isTransient()) { logger.trace("conversation with id {} has ended by {}.", conversation.getId(), getClass().getName()); conversation.end(); } } 

}

 @ConversationScoped @Named public class yourBean extends BaseWebBean implements Serializable { @PostConstruct public void initBean() { super.initBean(); continueOrInitConversation(); } public String deleteRow(Row row) { /*delete your row here*/ endConversationIfContinuing(); return "yourDestinationPageAfter removal"; } } 

Esiste un progetto che contiene estensioni alle funzionalità di stack EE Java: DeltaSpike . È un consolidamento di Seam 3, Apache CODI. Sopra gli altri, include @ViewScoped in CDI. Questo è un vecchio articolo e ormai ha raggiunto la versione 1.3.0

Puoi usare:

 import javax.annotation.PostConstruct; import javax.faces.view.ViewScoped; import javax.inject.Named; @Named @ViewScoped public class PageController implements Serializable { private String value; public void setValue(String value) { this.value = value; } public String getValue() { return value; } public void execute() { setValue("value"); } @PostConstruct public void init() { System.out.println("postcontructor"); } }