FAQ JSF2 : solutions aux erreurs les plus courantes

De $1

Version de 19:14, 19 Avr 2024

cette version.

Revenir à liste des archives.

Voir la version actuelle

Q : Il ne s'affiche rien dans ma datatable et je n'ai pas de message d'erreur

  • Réponse :
    1. soit vous vous êtes trompés dans le nom du backing bean (par ex : #{customerMBean.customers} au lieu de #{CustomerMBean.customers} par exemple, en effet EL ne provoque pas d'erreur en cas de bean non trouvé dans aucun des scopes.
    2. Vous avez oublié d'activer l'injection de code dans le projet. Vous pouvez réactiver cela en créeant un fichier beans.xml VIDE dans le répertoire WEB-INF de la partie web du projet.
    3. Vous vous êtes trompés dans les imports des Scope. Par exemple javax.faces.context.SessionScoped au lieu de javax.entreprise.context.SessionScoped.

Q : ma table PrimeFaces ne se trie pas

  • Réponse :
    1. Il faut cacher la variable qui contient la liste des objets à afficher dans le tableau. Le getter de la propriété étant appelé plusieurs fois, si la liste retournée est updatée plusieurs fois le tri ne peut avoir lieu. Exemple : dans getCustomers() du TP1 : cacher la liste. Attention si vous êtes en SessionScoped, si les données changent -> pas de modifications visibles étant donné qu'on a caché la variable. Solution : un bouton refresh ou passer avec un autre Scope.

Q : j'ai une erreur au déploiement EJBvalidator ou EJBBundle errors

  • Réponse :
    1. Suite à un clean and build, netbeans 7.0 peut ajouter des ejb-refs dans le fichier web.xml, c'est un bug. Solution : virer les lignes ejb-ref et ejb-local-ref du fichier web.xml, redéployer.

Q : J'ai une erreur Caused by: java.lang.IllegalStateException: PWC3999: Cannot create a session after the response has been committed

  • Réponse :
    1. c'est une erreur sur les datatables PrimeFaces entre autres, intervient en ViewScope ou ConversationScope lorsque le buffer de sortie est trop gros. C'est un bug mojara ou PF, les deux parties sont en train de discuter pour corriger.
    2. Solutions à voir sur : http://java.net/jira/browse/JAVASERVERFACES-2215
    3. Ce bug n'intervient que sur des gros tableaux...  

 Solution donc : ajouter un événement preRenderView dans la page qui contient la dataTable (ligne 8) :

<h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
        <link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
    </h:head>
    <h:body>

<f:event type="javax.faces.event.PreRenderViewEvent" listener="#{customerMBean.preRenderView}"/> 


        <f:view>
            <h:form>
                <h1><h:outputText value="List"/></h1>
                    <p:dataTable value="#{customerMBean.customers}" var="item" 
                                 emptyMessage="No customer found with given criteria" 
                                 widgetVar="customerTable"
                                 paginator="true"
                                 rows="10">

Ajouter dans la méthode envoyée par l'événement, il faut la forcer à créer une session bidon avant toutes choses :

@ManagedBean 
@ViewScoped
public class CustomerMBean implements Serializable {

    @EJB
    private DiscountCodeManager discountCodeManager;
    @EJB
    private CustomerManager customerManager;
    /* Client courant dans la session, utilisé pour afficher ses détails ou
     * pour faire une mise à jour du client modifié dans la base */
    private Customer customer;
    private List<Customer> customers;
    /**
     * Id du client dont on veut les détails.
     */
    private int idDetails;

     public void preRenderView() {
      HttpSession session = ( HttpSession ) FacesContext.getCurrentInstance().getExternalContext().getSession( true );
      //tune session params, eg. session.setMaxInactiveInterval(..);

      //perform other pre-render stuff, like setting user context...
   }

Q : comment marche le ConversationScoped ?

  • Réponse :
    1. Pas facile de trouver des exemples, on se perd facilement sur le net à cause du même scope qui existe dans le framework Seam de JBoss.

Voici un exemple d'utilisation : on ajoute @ConversationScoped dans le backing bean et on injecte une variable de type Conversation. Puis on appelle conversation.begin() et conversation.end() pour contrôler la création et la suppression de l'instance du bean.

Exemple (voir lignes 7, 10, 11, 16, 27...) :

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Inject;


@Named(value = "customerMBean")
@ConversationScoped
public class CustomerMBean implements Serializable {

    @Inject
    Conversation conversation;
    @EJB
    private DiscountCodeManager discountCodeManager;

    public String showDetails(Customer customer) {
        conversation.begin();
        this.customer = customer;
        currentDiscoutCode = customer.getDiscountCode().getDiscountCode().toString();
        return "CustomerDetails";
    }

...
    public String update() {
        DiscountCode code = discountCodeManager.getDiscountCodeFromStringCode(currentDiscoutCode);
        customer.setDiscountCode(code);
        customer = customerManager.update(customer);
        conversation.end();
        return "CustomerList";
    }