2

My question is quite simple (to ask). How can I create and manage my Exceptions in a JSF application?

First we have the separation from normal and Ajax requests. Problem solved by using FullAjaxExceptionHandler by Omnifaces.

Ok, now my Ajax exceptions follow the JSF/web.xml path. Next step is to create the mappings in web.xml:

<error-page>
    <exception-type>java.lang.SecurityException</exception-type>
    <location>/errors/security.xhtml</location>
</error-page>

The problem then is that Exceptions are not going to match above rules as they have been wrapped by other Exception types. Ok, Omnifaces to the rescue again with FacesExceptionFilter.

Ok, so now I can throw Exceptions from my beans, e.g.

@PostConstruct
public void init() {
    throw new SecurityException("Go away!");
}

Unfortunately this won't work, because Exception is thrown during bean initialization and not when calling a method.

Omnifaces unwrap method will stop to the occurrence of aFacesException and CDI (Weld) will wrap any exceptions during Bean initialization to a FacesException (which I assume is conforming to the spec).

I could write my own Exception filter that will not stop unwrapping a FacesException, you quickly realize that you might go deeper in the stacktrace than one would like.

How can I manage Exceptions during Bean initialization?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Ioannis Deligiannis
  • 2,679
  • 5
  • 25
  • 48

1 Answers1

2

The managed bean creation and initialization is not supposed to throw an exception in first place.

You'd better move this security checking logic elsewhere. E.g. a real security framework (container managed via JAAS/JASPIC or 3rd party like Shiro), or a servlet filter, or if you really really want to keep it in "the JSF house", use <f:viewAction> instead.

<f:viewAction action="#{bean.init}" />

(don't forget to remove the @PostConstruct annotation)

If you're not on JSF 2.2 yet, use preRenderView event instead.

<f:event type="preRenderView" listener="#{bean.init}" />

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • The actual authentication is handled inside a filter, but the resource authorization happens in the bean. The bean will try to verify that the authenticated user has access to the specific resource.This is difficult to move to a filter. The preRenderView would work on a Request scoped bean, but in a @Viewscoped bean like the one I have will run init more than once right? I could get around this by having a bool to make sure it runs only once, but the logic becomes ugly.I considered extending your filter by also checking if the exception comes from CDI,but then again portability will be lost – Ioannis Deligiannis Jul 10 '14 at 14:59
  • `preRenderView` runs regardless of bean scope on every request, also on postbacks. But I now realized that you're using JSF 2.2, you'd better use `` instead. See updated answer. – BalusC Jul 10 '14 at 15:20
  • Thanks for the edit and reply. What i meant is that request scope bean init matches the lifecycle of prerenderview (initialized on every request/postback where a viewscoped only initialized on init request). I'll have a look on the frameworks you suggested – Ioannis Deligiannis Jul 11 '14 at 04:47