2009-05-28 10 views
0

J'ai un filtre de servlet qui gère les erreurs pour les servlets vanilla et les pages JSF.Paramètre HTTP GET SOMETIMES manquant lors de l'utilisation de JSF

Si une erreur est détectée, l'utilisateur est redirigé vers une page d'erreur où il peut donner son avis. Ensuite, j'essaie de lire la valeur dans l'objet ErrorBean. Cependant, parfois l'erreur n'est pas présente - il y a une chance 50-50 de l'erreur étant présente.

Lorsque j'utilise

FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap() 

il retourne parfois une carte avec 1 entrée et parfois une carte vide. Dans tous les cas, l'identifiant est transmis au niveau http.

Je n'arrive pas vraiment à reproduire la cause de cette erreur. Voici le code correspondant (méthodes d'assistance + implémentations vides omises). Le ErrorFilter est mappé à /* et le ErrorBean est un bean de portée de session géré par JSF.

ErrorFilter

public class ErrorFilter implements Filter 
{ 
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException 
    { 
    HttpServletRequest hreq = (HttpServletRequest) req; 
    HttpServletResponse hres = (HttpServletResponse) resp; 

    try 
    { 
     chain.doFilter(req, resp); 
    } 
    catch (IOException e) 
    { 
     handleError(e, hreq, hres); 
    } 
    catch (ServletException e) 
    { 
     handleError(e, hreq, hres); 
    } 
    catch (RuntimeException e) 
    { 
     handleError(e, hreq, hres); 
    } 
    } 

    private static void handleError(Throwable e, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 
    { 
    final RequestInfo requestInfo = new RequestInfo(getUri(req), req.getSession().getId(), null, null, UserFactory.getUser(), InetAddress.getByName(req.getRemoteAddr())); 
    String token = new DecimalFormat("00000000").format(Math.abs(RANDOM.nextInt() % Integer.MAX_VALUE)); 
    //log msg 
    //send mail in a different thread 

    if (!req.getRequestURI().startsWith("/faces/error.jsp")) 
    { 
     resp.sendRedirect("/faces/error.jsp?token=" + token); 
    } 
    else 
    { 
     //log that an infite loop occurred 
     throw new ServletException(crapMsg, e); 
    } 
    } 
} 

ErrorBean

public class ErrorBean implements Serializable 
{ 
    private String feedback; 
    private String lastToken; 

    public String getLastErrorCode() 
    { 
    return "your token: " + getToken(); 
    } 

    private String getToken() 
    { 
    final String token = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("token"); 
    //here the "token" returns null although it is sent via get. 

    if (token != null) 
    { 
     if (!token.equals(lastToken)) 
     { 
      // reset data on token change. 
      feedback = null; 
     } 
     lastToken = token; 
    } 

    return lastToken; 
    } 

    public void setFeedback(String feedback) 
    { 
    this.feedback = feedback; 
    } 

    public String getFeedback() 
    { 
     if (feedback == null) 
     { 
     feedback = getDefaultMessage(); 
     } 

     return feedback; 
    } 

    public void send() 
    { 
    sendMail(lastToken,feedback); 
    } 
} 

Répondre

2

De mon humble point de vue, les visages Contexte devrait voir le paramètre de la varient première fois la demande est déjà redirigé sur: resp.sendRedirect("/faces/error.jsp?token=" + token);

Mais quand vous faites une autre demande, visages faire la manipulation avec son système de navigation et Redirige la page, et évidemment que le filtre fait chain.doFilter(req,resp); cette fois-ci, ce qui autorise le modèle de Navigation JSF à s'exécuter et ainsi supprimer votre paramètre de requête.

Ma suggestion est que vous pouvez l'ajouter à une autre valeur de session, il sera plus facile à manipuler ensuite.

+0

je n'ai pas compris exactement pourquoi il échoue PARFOIS .. la solution que vous proposez fonctionnait bien, je l'ai implémenté comme une solution de contournement de cette façon. stocker l'attribut de jeton dans la session. Cela fonctionne robuste. –

0

Je ne pense pas que le FacesContext est disponible dans un filtre Servlet. Un filtre ne s'exécute-t-il pas avant de cliquer sur FacesServlet (qui crée le FacesContext)?

Essayez de lire: http://www.thoughtsabout.net/blog/archives/000033.html

+0

Je crois qu'il veut dire que la page d'erreur est une page JSF qui utilise un bean géré pour rechercher un ensemble de paramètres HTTP par le filtre (auquel cas, le contexte serait disponible). – McDowell

+0

Il a le commentaire "Créer un objet errorInfo avec un jeton" int "". Sans voir cet objet et comment il a utilisé, c'est difficile à dire. Le .getToken() sur cet objet pourrait renvoyer null pour tout ce que nous savons. – GreenieMeanie

+0

le jeton est juste une chaîne aléatoire générée comme ceci: \t this.token = new DecimalFormat ("00000000"). Format (Math.abs (RANDOM.nextInt()% Integer.MAX_VALUE)); –

0

pages d'erreur ne sont généralement pas de bons candidats pour JSF dans le contexte de quoi que ce soit plus grand que JSF lui-même (ce qui signifie, par exemple, de la framerwork webapp). Et oui, le FaceContext n'est pas quelque chose que vous pouvez compter sur être disponible quand vous le voulez. Il est créé par le servlet Faces pour gérer une requête JSF et il est ignoré lorsque la requête est terminée. Il n'a pas de persistance à plus long terme de la demande à la demande.

En outre, les URL ont une signification complètement différente dans JSF que dans la plupart des applications Web. Ils sont plus comme une poignée utilisée pour suivre la conversation que d'une indication absolue de quelle page est demandée ou affichée.

Questions connexes