IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JSF Java Discussion :

Erreur "Cannot forward after response has been committed" due à un StreamResult


Sujet :

JSF Java

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2010
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2010
    Messages : 39
    Points : 27
    Points
    27
    Par défaut Erreur "Cannot forward after response has been committed" due à un StreamResult
    Bonjour à tous.

    J'ai une erreur déclenchée par la FacesServlet de JSF dont voici la trace :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    javax.faces.FacesException: Cannot forward after response has been committed
    	at com.sun.faces.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:142)
    	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
    	at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
    	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:630)
    	at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:535)
    	at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:472)
    En debuggant les sources de mon implémentation de JSF (mojarra 2.1.4) j'ai remarqué que cette exception était levée lors de l'instruction suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lifecycle.render(context);
    J'ai aussi remarqué que c'est le bout d'instruction suivant qui conduit à cette erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    			StreamResult iStreamResult = new StreamResult(new StringWriter());
    			
    			if (pageContext != null) {
    				iStreamResult = new StreamResult(pageContext.getOut());
    			}
    			
    	        Source source = new DOMSource(iNode);
    
    	        // Perform the transformation
    			iTransformer.transform(source, iStreamResult);
    
    			iStreamResult.getWriter().close();
    notamment la ligne en gras. Si je remplace le
    iStreamResult
    par, par exemple,
    new StreamResult(new StringWriter())
    je n'ai plus d'exception levée mais bien évidemment je n'ai pas non plus le résultat escompté.
    Ce que je ne comprends pas c'est que le problème vienne de la ligne en gras; si c'était le StreamResult qui posait problème, alors l'exception devrait toujours être levée si je met la ligne en gras en commentaire (ce qui n'est pas le cas). De plus je pense avoir fait le necessaire pour clore le flux.

    Je précise que je fais appel à la servlet FacesServlet via une autre servlet (
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    			iServletRequest.getRequestDispatcher("/FacesServlet/*").include(iServletRequest,iServletResponse);
    ).

    Je sais que ce problème est assez pointilleux mais j'espère que vous pourrez m'éclaircir.
    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Cette exception est en fait explicite.
    "Cannot forward" -> Tu as donc exécuté une action JSF dont le résultat implique une navigation via un forward (navigation rules dans ton faces-config)

    "after response has been committed" -> Mais tu as déjà dans ton code envoyé une partie deréponse au client, que ce soit par le biais d'un appel à response.getOutputStream() ou dans la servlet appelant le include.

    Comme le forwarde se fait exclusivement par l'envoi d'un header Location au client et que les header doivent être envoyés avant tout contenu, impossible de faire le forward après qu'on aie fait du contenu.

    Bref quelque part dans ton code tu envoie toi même la réponse au client alors que tu devrais laisser JSF s'en charger au moment opportun.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2010
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2010
    Messages : 39
    Points : 27
    Points
    27
    Par défaut
    Merci pour ta réponse claire tchize_
    je pensais justement avoir commenté toutes les lignes de code pouvant envoyer une réponse au client.
    Peut-être en ai-je oublié ...

    J'ai oublié de préciser que je travaillais avec des portlets. Est-ce-que l'erreur pourrait venir de là, la réponse envoyée n'étant pas complète...

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    particulièrement si t'es en portlet, tu ne dois pas envoyer de réponse toi même. Normalement tu dois juste mettre tes bean à jour, ta base de donnée à jour et laisser jsf se charger de l'affichage.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2010
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2010
    Messages : 39
    Points : 27
    Points
    27
    Par défaut
    Justement, je ne sais pas comment lui dire de s'occuper de l'affichage car je ne peux pas modifier l'URL de la requête. Ce qui veut dire que je ne peux pas mappé directement la Faces Servlet. D'où le getRequestDispatcher.

    En fait j'essaye d'envoyer un flux (le flux http avec le xml transformé) directement à la Faces Servlet mais je n'y arrive pas. En passant par la création d'un fichier intermédiaire cela fonctionne (presque) parfaitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    HttpServletRequest r = (HttpServletRequest) aServletRequest;
    String rootPath = r.getSession().getServletContext().getRealPath("/");
    File fileSR = new File(rootPath + "test.xhtml");
    final StreamResult sr = new StreamResult(fileSR);
    iTransformer.transform(domSource, sr);
    et l'appel à la Faces Servlet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    getServletContext().getRequestDispatcher("/test.jsf").forward(iServletRequest, iServletResponse);
    Mais je ne peux pas créer un fichier pour chaque utilisateur !

  6. #6
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Tu n'as que deux possibilité dans ta requete:

    soit tu génère le fichier xml dans ton response.getOutputStream (ce que tu fait) et alors tu ne peux pas passer par JSF car tu as DEJA envoyé une réponse au client (le fichier xml)
    soit tu utilise le requestDispatcher pour envoyer la requete à JSF, et dans ce cas là tu ne touche pas à la réponse.

    Je ne comprend pas ce que tu essaie de faire? Générer deux réponses en même temps pour le client? Ca ne passera pas.

Discussions similaires

  1. Erreur "Cannot create a session after the response has been committed"
    Par aurelientp dans le forum Développement Web en Java
    Réponses: 0
    Dernier message: 07/12/2011, 11h14
  2. Réponses: 0
    Dernier message: 06/05/2011, 10h56
  3. Réponses: 5
    Dernier message: 02/07/2010, 18h53
  4. Réponses: 2
    Dernier message: 11/08/2008, 17h24
  5. [JSP]Cannot forward after response has been committed
    Par hinanui dans le forum Servlets/JSP
    Réponses: 9
    Dernier message: 03/02/2007, 03h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo