Ioannis Deligiannis
Ioannis Deligiannis

Reputation: 2719

Exception during bean's @PostConstruct does not end up in right <error-page>

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?

Upvotes: 2

Views: 2429

Answers (1)

BalusC
BalusC

Reputation: 1108802

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:

Upvotes: 2

Related Questions