wake-up-neo.net

So ersetzen Sie @ManagedBean/@ViewScope durch CDI in JSF 2.0/2.1

Ich evaluiere derzeit Java EE 6/JSF 2.1 mit RichFaces.

Eine Bohne, die als deklariert ist 

@ManagedBean
@ViewScoped
  1. Ruft einen ID-Satz ab (um beispielsweise einen Löschvorgang vorzubereiten).
  2. Über JSF wird ein Bestätigungs-Popup angezeigt.
  3. Wenn der Benutzer dies bestätigt, wird die Löschmethode aufgerufen und die Zeile entfernt, für die die ID in Schritt 1 gespeichert wurde.

Da CDI-Beans keinen ViewScope haben, habe ich versucht, die Bean als zu deklarieren:

@Named
@ConversationScoped

Nun schlägt die Verarbeitung in Schritt 3 fehl, da der in Schritt 1 festgelegte Wert (geprüft) nicht mehr verfügbar ist. 

Muss ich die Methoden Conversation.begin() und Conversation.end() verwenden?

Wenn ja, wo wäre ein guter Ort, um sie anzurufen?

22
stacker

Wenn Sie ein Upgrade auf JSF 2.2 durchführen können, tun Sie es sofort. Es bietet eine native @ViewScopedAnmerkung für CDI.

import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

Alternativ können Sie/- OmniFaces installieren, das eine eigene CDI-kompatible @ViewScoped enthält, einschließlich eines funktionierenden @PreDestroy (der bei JSF @ViewScoped defekt ist).

import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

Eine andere Alternative ist die Installation von MyFaces CODI , die JSF 2.0/2.1 @ViewScoped transparent mit CDI verbindet. Dadurch wird der URL nur ein automatisch generierter Anforderungsparameter hinzugefügt (wie @ConversationScoped).

import javax.faces.bean.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class Bean implements Serializable {
    // ...
}

Wenn Sie wirklich @ConversationScoped verwenden müssen, müssen Sie tatsächlich anfangen und es beenden. Sie müssen im letzten Schritt der Konversation @Inject eine Conversation und begin() in @PostConstruct und end() aufrufen, normalerweise eine Aktionsmethode, die auf eine neue Ansicht umleitet.

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";
    }

}

Siehe auch:

48
BalusC

Ich denke, Sie können von der CDI-Erweiterung profitieren, um Ihren eigenen Bereich zu erstellen, sodass Sie den Kontext implementieren und den @NormalScope verwenden können.

  • CDI löst nach jedem Bean-Aufruf ein Ereignis AfterBeanDiscovery aus
  • Sie können die CDI-Erweiterung für @Observes dieses Ereignis verwenden und Ihre Kontextimplementierung hinzufügen
  • In Ihrer Implementierung können Sie Folgendes tun:
    1. Verwenden Sie Contextual, um Ihre Bean von FacesContextViewRootMap mit ihrem Namen abzurufen und es zurückzugeben nach jedem Ajax-Aufruf zurück
    2. Verwenden Sie CreationalContext, wenn der Bean-Name aus dem ersten Schritt nicht gefunden wurde, um ihn in der FacesContextViewRootMap zu erstellen. 

Für eine ausführlichere Erklärung empfehle ich diesen Link: http://www.verborgh.be/articles/2010/01/06/porting-the-viewscoped-jsf-annotation-to-cdi/

6
Kurohige

Injizieren Sie die Konversation in Ihre Bean und starten Sie die Konversation in der @PostConstructor-Methode, wenn die Konversation vorübergehend ist.

Beenden Sie nach dem Löschen des Datensatzes Ihr Gespräch und navigieren Sie zu Ihrer Zielseite. Wenn Sie ein Gespräch beginnen. Hier ist ein Beispiel

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";
    }

}
3
cubbuk

Es gibt ein Projekt, das Erweiterungen der Java EE-Stack-Funktionen enthält: DeltaSpike . Es ist eine Konsolidierung von Seam 3, Apache CODI. Es enthält unter anderem @ViewScoped in CDI. Dies ist ein alter Artikel und hat inzwischen die Version 1.3.0 erreicht

0
Endrik