Pourquoi @PostConstruct callback tire-t-il à chaque fois que bean est @ViewScoped? JSF

j'utilise datatable on page et j'utilise l'attribut binding pour le lier à mon support. C'est mon code: -

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
            <h:form prependId="false">

                <h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
                    <h:column>
                        <h:outputText value="#{item}"/>
                    </h:column>
                    <h:column>
                        <h:commandButton value="Click" actionListener="#{testBean.action}"/>
                    </h:column>
                </h:dataTable>

            </h:form>

    </h:body>
</html>

C'est mon haricot: -

package managedBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;

@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {

    private List<String> stringCollection;

    public List<String> getStringCollection() {
        return stringCollection;
    }

    public void setStringCollection(List<String> stringCollection) {
        this.stringCollection = stringCollection;
    }

    private HtmlDataTable dataTable;

    public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!!");
        stringCollection = new ArrayList<String>();
        stringCollection.add("a");
        stringCollection.add("b");
        stringCollection.add("c");

    }

    public void action(){
        System.out.println("Clicked!!");

    }
}

s'il vous plaît dites-moi pourquoi le @PostConstruct tire chaque fois que je clique sur le bouton? Il ne devrait tirer qu'une fois aussi longtemps que je suis sur la même page beacause my bean is @ViewScoped. En outre, si je supprime l'attribut de liaison alors tout fonctionne bien et @PostConstruct callback déclenche qu'une seule fois. Alors pourquoi à chaque fois que j'utilise l'attribut liant? J'ai besoin d'attribut de liaison et je veux effectuer des tâches d'initialisation comme récupérer des données à partir de webservice, etc qu'une seule fois. Que dois-je faire? Où dois-je écrire ma tâche d'initialisation?

31
demandé sur BalusC 2010-05-09 13:45:10

5 réponses

intéressant, quand vous utilisez la fixation d'un composant sur une fève vue scoped, le champ de vision se casse.

Je ne suis pas sûr que ce soit un bug dans JSF2, je devrais d'abord lire toute la spécification JSF2. Jusqu'à présent, le mieux est de laisser tomber la liaison du composant pour le moment et de passer l'élément sélectionné via la nouvelle syntaxe d'argument de la méthode EL 2.2:

<h:dataTable var="item" value="#{testBean.stringCollection}">
    <h:column>
        <h:outputText value="#{item}"/>
    </h:column>
    <h:column>
        <h:commandButton value="Click" action="#{testBean.action(item)}"/>
    </h:column>
</h:dataTable>

voir aussi:


mise à jour (Décembre 2012): il s'agit en effet d'un bug dans JSF2. C'est un poulet-oeuf question. La vue scoped haricots sont stockés dans le JSF l'état d'affichage. Ainsi, les fèves scoped view ne sont disponibles qu'après la phase de restauration. Cependant, l'attribut binding s'exécute pendant la phase de restauration de la vue, alors que les fèves scoped view ne sont pas encore disponibles. Cela provoque la création d'une toute nouvelle vue scoped Bean instance, qui est ensuite remplacé par la vue réelle scoped bean qui a été stocké dans l'état de vue JSF restauré.

C'est signalée comme JSF question 1492 et JSF spec isssue 787 qui sera fixé pour JSF 2.2. D'ici là, votre meilleur pari est d'utiliser binding sur demande haricots scoped exclusivement, ou de chercher d'autres moyens pour l'exigence fonctionnelle particulière.


mise à jour (mars 2015): le correctif JSF 2.2 a été rétroporté à Mojarra 2.1.18. Donc, si vous utilisez encore JSF 2.0/2.1, vous feriez mieux de passer à au moins cette version. Voir aussi a. O. Qu'est-ce que component liant dans le JSF? Quand il est préféré pour être utilisé? et JSTL dans JSF2 Facelets... du sens?

32
répondu BalusC 2017-05-23 12:17:28

comme d'autres l'ont dit, je dirais que la meilleure chose à faire est de laisser tomber la fixation des composants (vous n'en avez pas besoin ici).

mais je voudrais ajouter que vous pouvez obtenir la même chose que vous essayez de faire d'une manière plus orientée objet en utilisant des paramètres d'action, comme ceci:

<h:commandButton value="Click" action="#{testBean.action(item)}"/>

... et dans votre code java:

  public void action(Item item){
    System.out.println("Clicked!!" + item);
}
4
répondu ymajoros 2011-03-16 15:10:16

si vous avez un bean viewscoped et si vous voulez conserver les valeurs qui ont été entrées sur le formulaire ou si vous ne voulez pas que postconstruct soit lancé, vous devez retourner null de votre méthode d'action.

si vous retournez un résultat (par exemple invalide) et pointez le résultat invalide sur la même page en utilisant faces-config.xml, puis le bean viewscoped est recréé et ainsi il provoque postconstruct à tirer à nouveau.

0
répondu Pramod Kankure 2013-03-26 17:39:20

autre solution:

  • liant le Htmldatable dans une requête objet.
  • injecter cette demande scope bean dans la vue scope bean.

JBoss Seam utiliser cette solution pour lier JSF componentes à un élément conversation scope.

0
répondu Juan Miguel Bernal González 2013-05-16 15:50:49

la réponse de balusc m'a beaucoup aidé, je voudrais dire que j'ai eu ce bug avec mojarra Version 2.1.7, je suis actuellement en train d'utiliser 2.1.29-01 publié en janvier-2015 et ce bug est corrigé, mon problème était de lier un tabview à un haricot viewscoped. Avec cette version, je n'ai pas ce bug et reliure et postconstruct fonctionne très bien. J'utilise Jboss 5.2 et je dois utiliser mojarra 2.1.x j'espère donc que cette réponse aidera d'autres personnes dans la même situation.

http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01 http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01

0
répondu Luis Vidal 2015-03-20 12:54:40