You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wicket.apache.org by Jeremy Thomerson <je...@wickettraining.com> on 2010/04/16 08:27:24 UTC

Handling errors on a per-component basis?

Core devs (and others),

  I had someone ask me how to handle errors on a per-component basis.  That
is, if a component on the page encounters an error during rendering, it
would be nice to be able to just replace it with an empty panel that says
"foo component encountered an error".  Obviously, there are only certain
places you would want this, but it could be valuable for certain situations.

  So, I have a couple ideas on how to implement it.  None of them seem very
clean.  I'd like your feedback.  Basically, I need to be able to
wrap Component#renderComponent(final MarkupStream markupStream) so that I
can catch any error coming out of there.  So, the flow should be something
like:

   1. somehow cache exactly where the response is (before the component
   writes something to it) - either by copying the internal buffers, etc, or
   whatever, but not letting it go back to the client until the component is
   done being rendered
   2. then, inside of a try / catch, I could call
   super.renderComponent(final MarkupStream markupStream) so that the component
   is rendered (calling Response#write to output it's stuff....)
   3. then, if I caught an error, I rollback the response buffer to where it
   was before that component, and write my "this component didn't work" thing,
   and then close the tag and continue rendering

Because most of the methods that actually do the rendering are final, and
this is hard to accomplish.  And, of course, I can't actually globally
override a method in Component. Behaviors get calls before and after render,
as well as on an error, but they can't stop the error from being rethrown.

So, it appears that the only way to do the above is by creating a proxy
class that wraps that single renderComponent method in Component.  This
dynamic proxy could be created in a component instantiation listener.  Then
I could proxy for that method.  Do you have any other options or thoughts?

--
Jeremy Thomerson
http://www.wickettraining.com

Re: Handling errors on a per-component basis?

Posted by Igor Vaynberg <ig...@gmail.com>.
what if a component throws an exception during onbeforerender?

what if it throws an exception during a post-order traversal?

there are a lot of dependencies, im not sure how feasible this idea
is. whats the usecase? the only one that makes sense is if an error is
thrown during model.getobject() and we want to handle it then? why not
make the model exception-aware then? or hook in directly there and
skip the component render?

as far as "remembering" where the response is i think you can
accomplish it by swapping a different response in. like the
transformer behaviors do - which actually come pretty close to what
you want...

-igor

On Thu, Apr 15, 2010 at 11:27 PM, Jeremy Thomerson
<je...@wickettraining.com> wrote:
> Core devs (and others),
>
>  I had someone ask me how to handle errors on a per-component basis.  That
> is, if a component on the page encounters an error during rendering, it
> would be nice to be able to just replace it with an empty panel that says
> "foo component encountered an error".  Obviously, there are only certain
> places you would want this, but it could be valuable for certain situations.
>
>  So, I have a couple ideas on how to implement it.  None of them seem very
> clean.  I'd like your feedback.  Basically, I need to be able to
> wrap Component#renderComponent(final MarkupStream markupStream) so that I
> can catch any error coming out of there.  So, the flow should be something
> like:
>
>   1. somehow cache exactly where the response is (before the component
>   writes something to it) - either by copying the internal buffers, etc, or
>   whatever, but not letting it go back to the client until the component is
>   done being rendered
>   2. then, inside of a try / catch, I could call
>   super.renderComponent(final MarkupStream markupStream) so that the component
>   is rendered (calling Response#write to output it's stuff....)
>   3. then, if I caught an error, I rollback the response buffer to where it
>   was before that component, and write my "this component didn't work" thing,
>   and then close the tag and continue rendering
>
> Because most of the methods that actually do the rendering are final, and
> this is hard to accomplish.  And, of course, I can't actually globally
> override a method in Component. Behaviors get calls before and after render,
> as well as on an error, but they can't stop the error from being rethrown.
>
> So, it appears that the only way to do the above is by creating a proxy
> class that wraps that single renderComponent method in Component.  This
> dynamic proxy could be created in a component instantiation listener.  Then
> I could proxy for that method.  Do you have any other options or thoughts?
>
> --
> Jeremy Thomerson
> http://www.wickettraining.com
>