Pourquoi @PostConstruct rappel se déclenche chaque fois que, même si le haricot est @ViewScoped? JSF

StackOverflow https://stackoverflow.com/questions/2797231

Question

J'utilise datatable à la page et en utilisant l'attribut de liaison pour la lier à mon grain de soutien. Ceci 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>

Ceci 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 devrait tirer qu'une seule fois aussi longtemps que je suis sur une même page beacause mon haricot est @ViewScoped. De plus, si je supprime l'attribut liant alors tout fonctionne les feux de fin et rappel @PostConstruct qu'une seule fois. Alors pourquoi chaque fois que j'utiliser l'attribut de liaison? J'ai besoin lier attribut et que vous souhaitez effectuer des tâches d'initialisation comme l'extraction de données à partir webservice, etc qu'une seule fois. Que devrais-je faire? Où devrais-je écrire ma tâche d'initialisation?

Était-ce utile?

La solution

Intéressant, lorsque vous utilisez composant de liaison sur une vue SCOPED haricots, les sauts de portée de vue.

Je ne suis pas sûr que ce soit un bogue dans JSF2, je dois d'abord lire la spécification entière JSF2. En ce qui concerne maintenant votre meilleur pari est de laisser tomber lier le composant pour le moment et passer l'élément sélectionné par une nouvelle syntaxe de l'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): ceci est en effet un bogue dans JSF2. Il est une question poulet œuf. La vue des haricots scope sont stockés dans l'état d'affichage JSF. Ainsi, le point de vue scope les haricots ne sont disponibles après la phase de restauration de la vue. Cependant, les pistes d'attributs de binding pendant la phase de restauration de la vue, tandis que la vue scope les haricots ne sont pas encore disponibles. Cela provoque la création d'une toute nouvelle vue scope instance de haricot, qui est ensuite remplacé plus tard par la vue réelle scope haricot qui a été stocké à l'état de vue JSF restauré.

Ceci est rapporté comme numéro JSF 1492 et JSF spec isssue 787 qui sera fixé pour JSF 2.2. Jusque-là, le mieux est d'utiliser binding sur demande des haricots scope exclusivement, ou de chercher des moyens alternatifs pour l'exigence fonctionnelle particulière.


Mise à jour (mars 2015): Le JSF 2.2 correctif a été backported à Mojarra 2.1.18. Donc, si vous êtes toujours en utilisant JSF 2.0 / 2.1, vous feriez mieux de mise à niveau au moins cette version. Voir aussi A.O. Qu'est-ce que composant de liaison dans JSF? Quand on préfère utiliser et JSTL dans JSF2 Facelets ... logique

Autres conseils

Comme autre dit, je dirais que la meilleure chose à faire est de laisser tomber composant de liaison (vous n'avez pas besoin ici).

Mais je voudrais ajouter que vous pouvez obtenir la même chose que vous essayez de le 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);
}

Si vous avez un haricot viewscoped et si vous voulez conserver les valeurs qui ont été saisies dans le formulaire ou ne veulent pas PostConstruct tiré, vous devez retourner null de votre méthode d'action.

Si vous revenez certains résultats (par exemple non valide), puis pointez le résultat non valide à la même page en utilisant les faces-config.xml, le haricot viewscoped recréé et donc il provoque PostConstruct à nouveau le feu.

Autre solution:

  • la liaison HtmlDataTable dans un grain de périmètre de la requête.
  • Injecter ce grain de périmètre de la requête dans le champ de haricot vue.

JBoss Seam utiliser cette solution pour la liaison Componentes JSF à un composant de champ de conversation.

La réponse de balusc m'a beaucoup aidé, je voudrais dire que j'ai eu ce bug avec la version 2.1.7 mojarra, je l'utilise actuellement 2.1.29-01 publié en janvier 2015, ce bug est corrigé, mon problème a une liaison TabView à un haricot viewscoped. Avec cette version je n'ai pas ce bug et obligatoire et PostConstruct fonctionne très bien. J'utiliser Jboss 5.2 et je dois utiliser mojarra 2.1.x donc j'espère que cette réponse aider 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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top