2

The ViewExpiredException is being handled by a redirect to the login screen. The problem is that the exception is still logged, and the customer would strongly like to have the server.log exception-free.

While it may be a questionable requirement in this case, I still have to make it happen. We use Mojarra and deploy on JBoss EAP 5.1

The MyFaces approach does not help as I obviously cannot wrap the MyFacesServlet using Mojarra

I could not apply the advice given in the JBoss JSF guide to wrap the Faces servlet as I cannot find the jsf-integration-deployer-jboss-beans.xml anywhere.

I cannot get the approach proposed by Ed Burns to work either. I guess the reason is that it is targeted at JSF2 for I cannot find the javax.faces.context.ExceptionHandlerFactory in my jars.

Making the matter worse, I am quite new to JSF, so I have to rely on detailed guidance, in search of which I have found the above approaches but failed to apply them.

Thank you

kostja
  • 60,521
  • 48
  • 179
  • 224
  • 1
    Any reason you cannot handle it in log4j config with a filter or by blocking certain logger? – mrembisz Nov 10 '11 at 15:49
  • @mrembisz Not really. Striving for the JSF-y solution, I just haven't thought of that yet. I'll get to it. Thanks – kostja Nov 10 '11 at 15:54

2 Answers2

3

That article is indeed targeted on JSF 2.x. JSF 1.x does not have any exception handling facility.

Just catch and redirect yourself instead of letting the container do. A filter is a sensible place for this:

try {
    chain.doFilter(request, response);
} catch (ServletException e) {
    if (e.getRootCause() instanceof ViewExpiredException) {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        res.sendRedirect(req.getContextPath() + "/errors/session-expired.jsf");
    } else {
        throw e;
    }
}

Map this in web.xml on the servlet name of the FacesServlet to get it to run.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you, sounds resonable. I have found a tutorial on servlet filters and reading it right now. Will provide feedback ASAP – kostja Nov 10 '11 at 16:07
  • It's rather simple though. The above code needs to go fully in the `doFilter()` method. The `init()` and `destroy()` can be kept empty. You can find a template in our servlet filters wiki: http://stackoverflow.com/tags/servlet-filters/info The only difference with filter mapping is that you should use `TheServletNameOfYourFacesServlet` instead of ``. – BalusC Nov 10 '11 at 16:10
  • It is a close match, and it managed to get rid of the stacktrace in the log. But I still get the `SEVERE [javax.enterprise.resource.webcontainer.jsf.lifecycle] ... Exception thrown during phase execution: javax.faces.event.PhaseEvent`. This is logged immediately before the exception is thrown. – kostja Nov 10 '11 at 17:04
  • Oh right, this one. Well, that's really food for the logger configuration. For detail, see here: http://stackoverflow.com/questions/7162134/in-jsf-1-2-how-do-i-changing-logging-level-of-renderresponsephase/7163040#7163040 – BalusC Nov 10 '11 at 17:06
  • I was not able to influence the `util logging` despite putting a logging.properties into my WEB-INF. But log4j config saved the day. Thanks again. – kostja Nov 10 '11 at 18:14
1

I faced the same issue in JSF 2.0, the implementation is provided by the IBM Websphere 8.5.5.3 .

I tried to use an ExceptionHandlerWrapper to check for the ViewExpiredException and redirect to session expired page (or login page), but I couldn't silence the below error, sadly this error is printed before the handler:

StateUtils E View State cannot be reconstructed

But I manged to solve it by implementing a servlet filter which will check for any potential ViewExpiredException, it will redirect it to session expired page if any.

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;

HttpSession session = request.getSession(false);

boolean requestContainsViewState = (request.getParameter("javax.faces.ViewState") != null);
boolean potentialViewExpiredException = (session == null && requestContainsViewState);
if (potentialViewExpiredException) {
    // No session found and potential ViewExpiredException, redirect to session expired page.
    response.sendRedirect(request.getContextPath() + "/pages/error/expired.xhtml");
} else {
    chain.doFilter(req, res);
}

Edit : you need to make sure that this is the first filter in the filters chain, if there's a previous filter and this filter created a session the above solution will not work for you.

Mu'ath Baioud
  • 41
  • 1
  • 3