views:

49

answers:

2

Whenever there is an error during the load of a JSF facelet, JSF stops rendering the page at the point of the error and shows the error page instead (default behavior). I want JSF to continue rendering a page instead and show the exception/error within the page. For example if the page is loading a "portlet", which throws an exception, that exception would be shown as text within the portlet. I don't want the whole page to be forwarded to a separate error page.

I have initialized my own ExceptionHandlerFactory and ExceptionHandler implementations and I can iterate over the ExceptionQueueEvents succesfully. However, I don't know how to instruct JSF to continue loading the page despite of the error. Is this even the right approach at all? Is the ExceptionHandler called after (as I suppose) or in the middle processing the facelet? If after, is there anything I can do within my ExceptionHandler?

I know I should:

  • Hide the parts that user cannot access (my specific case relates to security, when user tries to load content he does not have rights to. However, I am looking for a global answer to this)
  • Manually handle the errors so unexpected exceptions would not be thrown

However, I want the user to be able to continue using the system despite of some minor component failure (for example if some newsfeed portlet throws an error that shouldn't prevent the user from seeing other content and using it).

I am using Mojarra 2.0.2. I feel this is a very simple to solve but I cannot figure it out :(

+1  A: 

Doing so would mean that you're giving the enduser a halfbaked HTML page (because JSF hasn't (and can't) complete the HTML rendering) and it's unspecified how the webbrowser would display the page.

Don't do it.

BalusC
Rendering incomplete HTML must be avoided, I agree, but there are cases where the HTML would still be valid. For example if I do <div>#{myBean.someProperty}</div> and the property is forbidden for the current user (throwing an exception), the page might just display the error text in place of the property like <div>AccessDeniedException</div> and HTML would be still valid. Propably I would want to initialize a special bean/facelet to report the thrown exception in a sane way. I do agree that in many cases the page would break, but when used carefully, valid output can be guaranteed as well?
Tuukka Mustonen
There the `rendered` attribtue is for.
BalusC
Yes, I will try to preemptively avoid exception and catch them the best I can. However, let's consider that I have a JSF component, calling a managed bean behind it. In the middle of the execution, a very unexpected exception is thrown and not caught. Is there an approach to, instead of redirecting the user to an error page, to show some generic error in place of the portlet (maybe the whole facelet) and continue rendering the rest of the page? Supposing the portlet doesn't have relations to other elements in the page, would you still consider this a bad thing?
Tuukka Mustonen
This indicates a `RuntimeException`, so yes, it's likely bad. As a completely different alternative, you may consider JSTL's `c:catch`. But still, handling exceptions in the view side is a bad idea. Just catch it in business/model side and set some token/toggle accordingly where the view could intercept on using `rendered` attribtue.
BalusC
Thanks for the pointer to `c:catch`. It seems like it might have some issues, but might as well do the trick, so I'll pick this as the accepted answer. Instead of using `c:catch`, I will, however, propably follow your advice and not ignore mid-page failures but redirect to a separate error page instead, to tell the user about the problem and allow her input some additional information into the crash report. I don't this is necessarily a better way, but certainly safer.
Tuukka Mustonen
+2  A: 

If your page has separate content, consider using (i)frames. This way, if some particular content fails to load, the whole page would still render, but that frame would show the error page. This of course implies that all your separate components are full html pages.

BalusC is absolutely correct that you should NOT try to handle any parsing exception etc. Oddly rendered page segments are not user friendly, and can lead to very bizarre results.

If you have roles/rights issues, those scenarios should be maintained separate from jsf rendering. Authorization should be confirmed before forwarding to a page, not while attempting to render it.

Java Drinker
Using iframes is a nice idea while maybe not too convenient. As I stated in my question "I know I should: Hide the parts that user cannot access". I will try to hide forbidden elements and catch exceptions beforehand. However, there are always exceptions leaking out and I would not like to trash the whole page, if the exception source is some minor component. After re-thinking the issue, I think it is enough to have this replace-the-content-of-the-element-on-failure-with-some-error-text feature on JSF components. Supporting it everywhere is not required. Any further thoughts?
Tuukka Mustonen