How to handle exceptions thrown in DataProvider methods centrallyVaadin & Joda DateTimeVaadin: centralizing custom exception handlingHow to set authorization on View level in VaadinVaadin Table throwing Cannot Convert Object to Number Exception on a manual refreshUsing Navigator in Vaadin's ErrorHandlerVaadin Flow &Spring Boot cant find resource via servlet contextProvide a Converter for data-binding by defining a pair of SerializableFunction objectsWhy setDefaultErrorHandler crash my view in vaadin flow?Vaadin 10+: How do I handle uncaught exceptions?View Constructor with Dependency Injection throws NPE

Cutting numbers into a specific decimals

How to say "I only speak one language which is English" in French?

In how many ways we can distribute 7 distinct balls among 3 students such that everyone gets at least 2 balls?

Was the six engine Boeing-747 ever seriously considered by Boeing?

Is the internet in Madagascar faster than in UK?

The meaning of asynchronous vs synchronous

Inspiration for failed idea?

Why can't you say don't instead of won't?

How to prevent a hosting company from accessing a VM's encryption keys?

Defending Castle from Zombies

Is belaying with a hip belay unsafe?

Why might one *not* want to use a capo?

How to handle inventory and story of a player leaving

Are there any to-scale diagrams of the TRAPPIST-1 system?

What is Soda Fountain Etiquette?

Notice period 60 days but I need to join in 45 days

What does GDPR mean to myself regarding my own data?

Why didn't Doc believe Marty was from the future?

Journal published a paper, ignoring my objections as a referee

What to do about my 1-month-old boy peeing through diapers?

Why does this London Underground poster from 1924 have a Star of David atop a Christmas tree?

Why does glibc's strlen need to be so complicated to run quickly?

Alternatives to Network Backup

What's the point of fighting monsters in Zelda BotW?



How to handle exceptions thrown in DataProvider methods centrally


Vaadin & Joda DateTimeVaadin: centralizing custom exception handlingHow to set authorization on View level in VaadinVaadin Table throwing Cannot Convert Object to Number Exception on a manual refreshUsing Navigator in Vaadin's ErrorHandlerVaadin Flow &Spring Boot cant find resource via servlet contextProvide a Converter for data-binding by defining a pair of SerializableFunction objectsWhy setDefaultErrorHandler crash my view in vaadin flow?Vaadin 10+: How do I handle uncaught exceptions?View Constructor with Dependency Injection throws NPE






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








1















When a DataProvider fetch or count method throws an exception, e.g. because the user is not authorized, how could I handle these exceptions centrally? I know there is HasErrorParameter interface to show error views when there is an exception thrown when routing. But these error views are not triggered when DataProvider throws the exception.



Example:



 new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
...


@Override
protected int sizeInBackEnd(Query<String, Void> query)
throw new UnsupportedOperationException("test");



@Route("failed")
public class FailView extends VerticalLayout
implements HasErrorParameter<UnsupportedOperationException> ...


Even if I do a try catch within the DataProvider methods, I don't see how I could navigate to the appropriate error view just by using the caught exception and not the view component class (this wouldn't trigger setErrorParameter method).



BTW: I miss the router exception handling topic in Vaadin Flow 13 documentation. I wonder why they removed it.










share|improve this question



















  • 1





    This is a known issue/limitation/bug in current HesErrorParameter implementation and there is many issue tickets filed related to this github.com/vaadin/flow/issues/4715 github.com/vaadin/flow/issues/4549 github.com/vaadin/flow/issues/4607 github.com/vaadin/flow/issues/3192

    – Tatu Lund
    Mar 18 at 8:43

















1















When a DataProvider fetch or count method throws an exception, e.g. because the user is not authorized, how could I handle these exceptions centrally? I know there is HasErrorParameter interface to show error views when there is an exception thrown when routing. But these error views are not triggered when DataProvider throws the exception.



Example:



 new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
...


@Override
protected int sizeInBackEnd(Query<String, Void> query)
throw new UnsupportedOperationException("test");



@Route("failed")
public class FailView extends VerticalLayout
implements HasErrorParameter<UnsupportedOperationException> ...


Even if I do a try catch within the DataProvider methods, I don't see how I could navigate to the appropriate error view just by using the caught exception and not the view component class (this wouldn't trigger setErrorParameter method).



BTW: I miss the router exception handling topic in Vaadin Flow 13 documentation. I wonder why they removed it.










share|improve this question



















  • 1





    This is a known issue/limitation/bug in current HesErrorParameter implementation and there is many issue tickets filed related to this github.com/vaadin/flow/issues/4715 github.com/vaadin/flow/issues/4549 github.com/vaadin/flow/issues/4607 github.com/vaadin/flow/issues/3192

    – Tatu Lund
    Mar 18 at 8:43













1












1








1








When a DataProvider fetch or count method throws an exception, e.g. because the user is not authorized, how could I handle these exceptions centrally? I know there is HasErrorParameter interface to show error views when there is an exception thrown when routing. But these error views are not triggered when DataProvider throws the exception.



Example:



 new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
...


@Override
protected int sizeInBackEnd(Query<String, Void> query)
throw new UnsupportedOperationException("test");



@Route("failed")
public class FailView extends VerticalLayout
implements HasErrorParameter<UnsupportedOperationException> ...


Even if I do a try catch within the DataProvider methods, I don't see how I could navigate to the appropriate error view just by using the caught exception and not the view component class (this wouldn't trigger setErrorParameter method).



BTW: I miss the router exception handling topic in Vaadin Flow 13 documentation. I wonder why they removed it.










share|improve this question














When a DataProvider fetch or count method throws an exception, e.g. because the user is not authorized, how could I handle these exceptions centrally? I know there is HasErrorParameter interface to show error views when there is an exception thrown when routing. But these error views are not triggered when DataProvider throws the exception.



Example:



 new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
...


@Override
protected int sizeInBackEnd(Query<String, Void> query)
throw new UnsupportedOperationException("test");



@Route("failed")
public class FailView extends VerticalLayout
implements HasErrorParameter<UnsupportedOperationException> ...


Even if I do a try catch within the DataProvider methods, I don't see how I could navigate to the appropriate error view just by using the caught exception and not the view component class (this wouldn't trigger setErrorParameter method).



BTW: I miss the router exception handling topic in Vaadin Flow 13 documentation. I wonder why they removed it.







vaadin vaadin-grid vaadin-flow vaadin10






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 17 at 18:53









Steffen HarbichSteffen Harbich

1,93619 silver badges43 bronze badges




1,93619 silver badges43 bronze badges










  • 1





    This is a known issue/limitation/bug in current HesErrorParameter implementation and there is many issue tickets filed related to this github.com/vaadin/flow/issues/4715 github.com/vaadin/flow/issues/4549 github.com/vaadin/flow/issues/4607 github.com/vaadin/flow/issues/3192

    – Tatu Lund
    Mar 18 at 8:43












  • 1





    This is a known issue/limitation/bug in current HesErrorParameter implementation and there is many issue tickets filed related to this github.com/vaadin/flow/issues/4715 github.com/vaadin/flow/issues/4549 github.com/vaadin/flow/issues/4607 github.com/vaadin/flow/issues/3192

    – Tatu Lund
    Mar 18 at 8:43







1




1





This is a known issue/limitation/bug in current HesErrorParameter implementation and there is many issue tickets filed related to this github.com/vaadin/flow/issues/4715 github.com/vaadin/flow/issues/4549 github.com/vaadin/flow/issues/4607 github.com/vaadin/flow/issues/3192

– Tatu Lund
Mar 18 at 8:43





This is a known issue/limitation/bug in current HesErrorParameter implementation and there is many issue tickets filed related to this github.com/vaadin/flow/issues/4715 github.com/vaadin/flow/issues/4549 github.com/vaadin/flow/issues/4607 github.com/vaadin/flow/issues/3192

– Tatu Lund
Mar 18 at 8:43












1 Answer
1






active

oldest

votes


















2















I believe all Exceptions that don't occur while routing will be given to the ErrorHandler of the VaadinSession the error occured in.



The best way to set the ErrorHandler seems to be to override the sessionInit method in a custom SessionInitListener



You can add a custom SessionInitListener inside the servletInitialized method of a custom VaadinServlet.



class CustomServlet extends VaadinServlet
@Override
protected void servletInitialized() throws ServletException
super.servletInitialized();
getService().addSessionInitListener(new CustomSessionInitListener());




And that SessionInitListener (in this example CustomSessionInitListener) has to set the errorHandler of the sessions that get initialized.



class CustomSessionInitListener implements SessionInitListener
@Override
public void sessionInit(SessionInitEvent event) throws ServiceException
event.getSession().setErrorHandler(new CustomErrorHandler());




For further information on how to create your own Servlet take a look at Vaadin's tutorial page(you need to scroll down to "Customizing Vaadin Servlet")



Edit:
To show the error page you need to get Vaadin to reroute to an error. To achieve that we can use an BeforeEnterEvent, BeforeEnterEvents have a rerouteToError method which we can use to let Vaadin show our ErrorView.



But we also want to pass along the Exception instance, so we have to store that as well. I did exactly that with the following class:



@Route("error-view") // Route shown in the user's browser
public class ErrorViewShower extends Div implements BeforeEnterObserver
// Class to store the current Exception of each UI in
private static class UIExceptionContainer extends HashMap<UI, Exception>



// Method to call when we want to show an error
public static void showError(Exception exception)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);
// Creating and setting the exceptionContainer in case it hasn't been set yet.
if (exceptionContainer == null)
exceptionContainer = new UIExceptionContainer();
VaadinSession.getCurrent().setAttribute(UIExceptionContainer.class, exceptionContainer);


// Storing the exception for the beforeEnter method
exceptionContainer.put(UI.getCurrent(), exception);

// Now we navigate to an Instance of this class, to use the BeforeEnterEvent to reroute to the actual error view
UI.getCurrent().navigate(ErrorViewShower.class);// If this call doesn't work you might want to wrap into UI.access


@Override
public void beforeEnter(BeforeEnterEvent event)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);

// Retrieving the previously stored exception. You might want to handle if this has been called without setting any Exception.
Exception exception = exceptionContainer.get(UI.getCurrent());

//Clearing out the now handled Exception
exceptionContainer.remove(UI.getCurrent());

// Using the BeforeEnterEvent to show the error
event.rerouteToError(exception, "Possible custom message for the ErrorHandler here");





Usage of it in combination with the error handler looks like this:



public class CustomErrorHandler implements ErrorHandler 
@Override
public void error(ErrorEvent event)
// This can easily throw an exception itself, you need to add additional checking before casting.
// And it's possible that this method is called outside the context of an UI(when a dynamic resource throws an exception for example)
Exception exception = (Exception) event.getThrowable();
ErrorViewShower.showError(exception);





Edit2:
As it turns out that Exceptions occuring inside internal method calls don't get handled by the UI's ErrorHandler or the VaadinSession's ErrorHandler but instead by another error handler which causes the client side to terminate and show the Error Notification,



a solution is to catch the Exceptions inside the methods of the DataProvider and pass them to ErrorViewShower.showError() and still return without any Exception flying the stacktrace upwards. (Or don't throw any Exception yourself and instead simply pass a new to the ErrorViewShower.showError() method).



By returning normally Vaadin doesn't even know something went wrong.
ErrorViewShower.showError() calls ui.navigate, that navigation command seems to get "queued" behind the calls to the DataProvider, meaning the view of the user will change in the same request.



Dataprovider with such an implementation:



new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
try
//Code that can throw an Exception here
catch(Exception e)
ErrorViewShower.showError(e);
//We have to make sure that query.getLimit and query.getOffset gets called, otherwise Vaadin throws an Exception with the message "the data provider hasn't ever called getLimit() method on the provided query. It means that the the data provider breaks the contract and the returned stream contains unxpected data."
query.getLimit();
query.getOffset();
return Stream.of(); //Stream of empty Array to return without error



@Override
protected int sizeInBackEnd(Query<String, Void> query)
//Second way i mentioned, but this will not catch any Exception you didn't create, where as the try...catch has no way to let any Exception reach Vaadin.
if(badThingsHappened)
ErrorViewShower.showError(new UnsupportedOperationException("Bad things..."));
return 0;//Exiting without error








share|improve this answer



























  • Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

    – Steffen Harbich
    Mar 26 at 8:51






  • 1





    @SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

    – froemijojo
    Mar 26 at 11:10











  • Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

    – Steffen Harbich
    Mar 26 at 12:21











  • Copied your approach, still getting no redirect to error view.

    – Steffen Harbich
    Mar 26 at 12:36






  • 1





    Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

    – Steffen Harbich
    Mar 28 at 6:52










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55210726%2fhow-to-handle-exceptions-thrown-in-dataprovider-methods-centrally%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2















I believe all Exceptions that don't occur while routing will be given to the ErrorHandler of the VaadinSession the error occured in.



The best way to set the ErrorHandler seems to be to override the sessionInit method in a custom SessionInitListener



You can add a custom SessionInitListener inside the servletInitialized method of a custom VaadinServlet.



class CustomServlet extends VaadinServlet
@Override
protected void servletInitialized() throws ServletException
super.servletInitialized();
getService().addSessionInitListener(new CustomSessionInitListener());




And that SessionInitListener (in this example CustomSessionInitListener) has to set the errorHandler of the sessions that get initialized.



class CustomSessionInitListener implements SessionInitListener
@Override
public void sessionInit(SessionInitEvent event) throws ServiceException
event.getSession().setErrorHandler(new CustomErrorHandler());




For further information on how to create your own Servlet take a look at Vaadin's tutorial page(you need to scroll down to "Customizing Vaadin Servlet")



Edit:
To show the error page you need to get Vaadin to reroute to an error. To achieve that we can use an BeforeEnterEvent, BeforeEnterEvents have a rerouteToError method which we can use to let Vaadin show our ErrorView.



But we also want to pass along the Exception instance, so we have to store that as well. I did exactly that with the following class:



@Route("error-view") // Route shown in the user's browser
public class ErrorViewShower extends Div implements BeforeEnterObserver
// Class to store the current Exception of each UI in
private static class UIExceptionContainer extends HashMap<UI, Exception>



// Method to call when we want to show an error
public static void showError(Exception exception)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);
// Creating and setting the exceptionContainer in case it hasn't been set yet.
if (exceptionContainer == null)
exceptionContainer = new UIExceptionContainer();
VaadinSession.getCurrent().setAttribute(UIExceptionContainer.class, exceptionContainer);


// Storing the exception for the beforeEnter method
exceptionContainer.put(UI.getCurrent(), exception);

// Now we navigate to an Instance of this class, to use the BeforeEnterEvent to reroute to the actual error view
UI.getCurrent().navigate(ErrorViewShower.class);// If this call doesn't work you might want to wrap into UI.access


@Override
public void beforeEnter(BeforeEnterEvent event)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);

// Retrieving the previously stored exception. You might want to handle if this has been called without setting any Exception.
Exception exception = exceptionContainer.get(UI.getCurrent());

//Clearing out the now handled Exception
exceptionContainer.remove(UI.getCurrent());

// Using the BeforeEnterEvent to show the error
event.rerouteToError(exception, "Possible custom message for the ErrorHandler here");





Usage of it in combination with the error handler looks like this:



public class CustomErrorHandler implements ErrorHandler 
@Override
public void error(ErrorEvent event)
// This can easily throw an exception itself, you need to add additional checking before casting.
// And it's possible that this method is called outside the context of an UI(when a dynamic resource throws an exception for example)
Exception exception = (Exception) event.getThrowable();
ErrorViewShower.showError(exception);





Edit2:
As it turns out that Exceptions occuring inside internal method calls don't get handled by the UI's ErrorHandler or the VaadinSession's ErrorHandler but instead by another error handler which causes the client side to terminate and show the Error Notification,



a solution is to catch the Exceptions inside the methods of the DataProvider and pass them to ErrorViewShower.showError() and still return without any Exception flying the stacktrace upwards. (Or don't throw any Exception yourself and instead simply pass a new to the ErrorViewShower.showError() method).



By returning normally Vaadin doesn't even know something went wrong.
ErrorViewShower.showError() calls ui.navigate, that navigation command seems to get "queued" behind the calls to the DataProvider, meaning the view of the user will change in the same request.



Dataprovider with such an implementation:



new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
try
//Code that can throw an Exception here
catch(Exception e)
ErrorViewShower.showError(e);
//We have to make sure that query.getLimit and query.getOffset gets called, otherwise Vaadin throws an Exception with the message "the data provider hasn't ever called getLimit() method on the provided query. It means that the the data provider breaks the contract and the returned stream contains unxpected data."
query.getLimit();
query.getOffset();
return Stream.of(); //Stream of empty Array to return without error



@Override
protected int sizeInBackEnd(Query<String, Void> query)
//Second way i mentioned, but this will not catch any Exception you didn't create, where as the try...catch has no way to let any Exception reach Vaadin.
if(badThingsHappened)
ErrorViewShower.showError(new UnsupportedOperationException("Bad things..."));
return 0;//Exiting without error








share|improve this answer



























  • Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

    – Steffen Harbich
    Mar 26 at 8:51






  • 1





    @SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

    – froemijojo
    Mar 26 at 11:10











  • Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

    – Steffen Harbich
    Mar 26 at 12:21











  • Copied your approach, still getting no redirect to error view.

    – Steffen Harbich
    Mar 26 at 12:36






  • 1





    Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

    – Steffen Harbich
    Mar 28 at 6:52















2















I believe all Exceptions that don't occur while routing will be given to the ErrorHandler of the VaadinSession the error occured in.



The best way to set the ErrorHandler seems to be to override the sessionInit method in a custom SessionInitListener



You can add a custom SessionInitListener inside the servletInitialized method of a custom VaadinServlet.



class CustomServlet extends VaadinServlet
@Override
protected void servletInitialized() throws ServletException
super.servletInitialized();
getService().addSessionInitListener(new CustomSessionInitListener());




And that SessionInitListener (in this example CustomSessionInitListener) has to set the errorHandler of the sessions that get initialized.



class CustomSessionInitListener implements SessionInitListener
@Override
public void sessionInit(SessionInitEvent event) throws ServiceException
event.getSession().setErrorHandler(new CustomErrorHandler());




For further information on how to create your own Servlet take a look at Vaadin's tutorial page(you need to scroll down to "Customizing Vaadin Servlet")



Edit:
To show the error page you need to get Vaadin to reroute to an error. To achieve that we can use an BeforeEnterEvent, BeforeEnterEvents have a rerouteToError method which we can use to let Vaadin show our ErrorView.



But we also want to pass along the Exception instance, so we have to store that as well. I did exactly that with the following class:



@Route("error-view") // Route shown in the user's browser
public class ErrorViewShower extends Div implements BeforeEnterObserver
// Class to store the current Exception of each UI in
private static class UIExceptionContainer extends HashMap<UI, Exception>



// Method to call when we want to show an error
public static void showError(Exception exception)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);
// Creating and setting the exceptionContainer in case it hasn't been set yet.
if (exceptionContainer == null)
exceptionContainer = new UIExceptionContainer();
VaadinSession.getCurrent().setAttribute(UIExceptionContainer.class, exceptionContainer);


// Storing the exception for the beforeEnter method
exceptionContainer.put(UI.getCurrent(), exception);

// Now we navigate to an Instance of this class, to use the BeforeEnterEvent to reroute to the actual error view
UI.getCurrent().navigate(ErrorViewShower.class);// If this call doesn't work you might want to wrap into UI.access


@Override
public void beforeEnter(BeforeEnterEvent event)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);

// Retrieving the previously stored exception. You might want to handle if this has been called without setting any Exception.
Exception exception = exceptionContainer.get(UI.getCurrent());

//Clearing out the now handled Exception
exceptionContainer.remove(UI.getCurrent());

// Using the BeforeEnterEvent to show the error
event.rerouteToError(exception, "Possible custom message for the ErrorHandler here");





Usage of it in combination with the error handler looks like this:



public class CustomErrorHandler implements ErrorHandler 
@Override
public void error(ErrorEvent event)
// This can easily throw an exception itself, you need to add additional checking before casting.
// And it's possible that this method is called outside the context of an UI(when a dynamic resource throws an exception for example)
Exception exception = (Exception) event.getThrowable();
ErrorViewShower.showError(exception);





Edit2:
As it turns out that Exceptions occuring inside internal method calls don't get handled by the UI's ErrorHandler or the VaadinSession's ErrorHandler but instead by another error handler which causes the client side to terminate and show the Error Notification,



a solution is to catch the Exceptions inside the methods of the DataProvider and pass them to ErrorViewShower.showError() and still return without any Exception flying the stacktrace upwards. (Or don't throw any Exception yourself and instead simply pass a new to the ErrorViewShower.showError() method).



By returning normally Vaadin doesn't even know something went wrong.
ErrorViewShower.showError() calls ui.navigate, that navigation command seems to get "queued" behind the calls to the DataProvider, meaning the view of the user will change in the same request.



Dataprovider with such an implementation:



new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
try
//Code that can throw an Exception here
catch(Exception e)
ErrorViewShower.showError(e);
//We have to make sure that query.getLimit and query.getOffset gets called, otherwise Vaadin throws an Exception with the message "the data provider hasn't ever called getLimit() method on the provided query. It means that the the data provider breaks the contract and the returned stream contains unxpected data."
query.getLimit();
query.getOffset();
return Stream.of(); //Stream of empty Array to return without error



@Override
protected int sizeInBackEnd(Query<String, Void> query)
//Second way i mentioned, but this will not catch any Exception you didn't create, where as the try...catch has no way to let any Exception reach Vaadin.
if(badThingsHappened)
ErrorViewShower.showError(new UnsupportedOperationException("Bad things..."));
return 0;//Exiting without error








share|improve this answer



























  • Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

    – Steffen Harbich
    Mar 26 at 8:51






  • 1





    @SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

    – froemijojo
    Mar 26 at 11:10











  • Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

    – Steffen Harbich
    Mar 26 at 12:21











  • Copied your approach, still getting no redirect to error view.

    – Steffen Harbich
    Mar 26 at 12:36






  • 1





    Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

    – Steffen Harbich
    Mar 28 at 6:52













2














2










2









I believe all Exceptions that don't occur while routing will be given to the ErrorHandler of the VaadinSession the error occured in.



The best way to set the ErrorHandler seems to be to override the sessionInit method in a custom SessionInitListener



You can add a custom SessionInitListener inside the servletInitialized method of a custom VaadinServlet.



class CustomServlet extends VaadinServlet
@Override
protected void servletInitialized() throws ServletException
super.servletInitialized();
getService().addSessionInitListener(new CustomSessionInitListener());




And that SessionInitListener (in this example CustomSessionInitListener) has to set the errorHandler of the sessions that get initialized.



class CustomSessionInitListener implements SessionInitListener
@Override
public void sessionInit(SessionInitEvent event) throws ServiceException
event.getSession().setErrorHandler(new CustomErrorHandler());




For further information on how to create your own Servlet take a look at Vaadin's tutorial page(you need to scroll down to "Customizing Vaadin Servlet")



Edit:
To show the error page you need to get Vaadin to reroute to an error. To achieve that we can use an BeforeEnterEvent, BeforeEnterEvents have a rerouteToError method which we can use to let Vaadin show our ErrorView.



But we also want to pass along the Exception instance, so we have to store that as well. I did exactly that with the following class:



@Route("error-view") // Route shown in the user's browser
public class ErrorViewShower extends Div implements BeforeEnterObserver
// Class to store the current Exception of each UI in
private static class UIExceptionContainer extends HashMap<UI, Exception>



// Method to call when we want to show an error
public static void showError(Exception exception)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);
// Creating and setting the exceptionContainer in case it hasn't been set yet.
if (exceptionContainer == null)
exceptionContainer = new UIExceptionContainer();
VaadinSession.getCurrent().setAttribute(UIExceptionContainer.class, exceptionContainer);


// Storing the exception for the beforeEnter method
exceptionContainer.put(UI.getCurrent(), exception);

// Now we navigate to an Instance of this class, to use the BeforeEnterEvent to reroute to the actual error view
UI.getCurrent().navigate(ErrorViewShower.class);// If this call doesn't work you might want to wrap into UI.access


@Override
public void beforeEnter(BeforeEnterEvent event)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);

// Retrieving the previously stored exception. You might want to handle if this has been called without setting any Exception.
Exception exception = exceptionContainer.get(UI.getCurrent());

//Clearing out the now handled Exception
exceptionContainer.remove(UI.getCurrent());

// Using the BeforeEnterEvent to show the error
event.rerouteToError(exception, "Possible custom message for the ErrorHandler here");





Usage of it in combination with the error handler looks like this:



public class CustomErrorHandler implements ErrorHandler 
@Override
public void error(ErrorEvent event)
// This can easily throw an exception itself, you need to add additional checking before casting.
// And it's possible that this method is called outside the context of an UI(when a dynamic resource throws an exception for example)
Exception exception = (Exception) event.getThrowable();
ErrorViewShower.showError(exception);





Edit2:
As it turns out that Exceptions occuring inside internal method calls don't get handled by the UI's ErrorHandler or the VaadinSession's ErrorHandler but instead by another error handler which causes the client side to terminate and show the Error Notification,



a solution is to catch the Exceptions inside the methods of the DataProvider and pass them to ErrorViewShower.showError() and still return without any Exception flying the stacktrace upwards. (Or don't throw any Exception yourself and instead simply pass a new to the ErrorViewShower.showError() method).



By returning normally Vaadin doesn't even know something went wrong.
ErrorViewShower.showError() calls ui.navigate, that navigation command seems to get "queued" behind the calls to the DataProvider, meaning the view of the user will change in the same request.



Dataprovider with such an implementation:



new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
try
//Code that can throw an Exception here
catch(Exception e)
ErrorViewShower.showError(e);
//We have to make sure that query.getLimit and query.getOffset gets called, otherwise Vaadin throws an Exception with the message "the data provider hasn't ever called getLimit() method on the provided query. It means that the the data provider breaks the contract and the returned stream contains unxpected data."
query.getLimit();
query.getOffset();
return Stream.of(); //Stream of empty Array to return without error



@Override
protected int sizeInBackEnd(Query<String, Void> query)
//Second way i mentioned, but this will not catch any Exception you didn't create, where as the try...catch has no way to let any Exception reach Vaadin.
if(badThingsHappened)
ErrorViewShower.showError(new UnsupportedOperationException("Bad things..."));
return 0;//Exiting without error








share|improve this answer















I believe all Exceptions that don't occur while routing will be given to the ErrorHandler of the VaadinSession the error occured in.



The best way to set the ErrorHandler seems to be to override the sessionInit method in a custom SessionInitListener



You can add a custom SessionInitListener inside the servletInitialized method of a custom VaadinServlet.



class CustomServlet extends VaadinServlet
@Override
protected void servletInitialized() throws ServletException
super.servletInitialized();
getService().addSessionInitListener(new CustomSessionInitListener());




And that SessionInitListener (in this example CustomSessionInitListener) has to set the errorHandler of the sessions that get initialized.



class CustomSessionInitListener implements SessionInitListener
@Override
public void sessionInit(SessionInitEvent event) throws ServiceException
event.getSession().setErrorHandler(new CustomErrorHandler());




For further information on how to create your own Servlet take a look at Vaadin's tutorial page(you need to scroll down to "Customizing Vaadin Servlet")



Edit:
To show the error page you need to get Vaadin to reroute to an error. To achieve that we can use an BeforeEnterEvent, BeforeEnterEvents have a rerouteToError method which we can use to let Vaadin show our ErrorView.



But we also want to pass along the Exception instance, so we have to store that as well. I did exactly that with the following class:



@Route("error-view") // Route shown in the user's browser
public class ErrorViewShower extends Div implements BeforeEnterObserver
// Class to store the current Exception of each UI in
private static class UIExceptionContainer extends HashMap<UI, Exception>



// Method to call when we want to show an error
public static void showError(Exception exception)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);
// Creating and setting the exceptionContainer in case it hasn't been set yet.
if (exceptionContainer == null)
exceptionContainer = new UIExceptionContainer();
VaadinSession.getCurrent().setAttribute(UIExceptionContainer.class, exceptionContainer);


// Storing the exception for the beforeEnter method
exceptionContainer.put(UI.getCurrent(), exception);

// Now we navigate to an Instance of this class, to use the BeforeEnterEvent to reroute to the actual error view
UI.getCurrent().navigate(ErrorViewShower.class);// If this call doesn't work you might want to wrap into UI.access


@Override
public void beforeEnter(BeforeEnterEvent event)
UIExceptionContainer exceptionContainer = VaadinSession.getCurrent().getAttribute(UIExceptionContainer.class);

// Retrieving the previously stored exception. You might want to handle if this has been called without setting any Exception.
Exception exception = exceptionContainer.get(UI.getCurrent());

//Clearing out the now handled Exception
exceptionContainer.remove(UI.getCurrent());

// Using the BeforeEnterEvent to show the error
event.rerouteToError(exception, "Possible custom message for the ErrorHandler here");





Usage of it in combination with the error handler looks like this:



public class CustomErrorHandler implements ErrorHandler 
@Override
public void error(ErrorEvent event)
// This can easily throw an exception itself, you need to add additional checking before casting.
// And it's possible that this method is called outside the context of an UI(when a dynamic resource throws an exception for example)
Exception exception = (Exception) event.getThrowable();
ErrorViewShower.showError(exception);





Edit2:
As it turns out that Exceptions occuring inside internal method calls don't get handled by the UI's ErrorHandler or the VaadinSession's ErrorHandler but instead by another error handler which causes the client side to terminate and show the Error Notification,



a solution is to catch the Exceptions inside the methods of the DataProvider and pass them to ErrorViewShower.showError() and still return without any Exception flying the stacktrace upwards. (Or don't throw any Exception yourself and instead simply pass a new to the ErrorViewShower.showError() method).



By returning normally Vaadin doesn't even know something went wrong.
ErrorViewShower.showError() calls ui.navigate, that navigation command seems to get "queued" behind the calls to the DataProvider, meaning the view of the user will change in the same request.



Dataprovider with such an implementation:



new AbstractBackEndDataProvider<String, Void>() 
@Override
protected Stream<String> fetchFromBackEnd(Query<String, Void> query)
try
//Code that can throw an Exception here
catch(Exception e)
ErrorViewShower.showError(e);
//We have to make sure that query.getLimit and query.getOffset gets called, otherwise Vaadin throws an Exception with the message "the data provider hasn't ever called getLimit() method on the provided query. It means that the the data provider breaks the contract and the returned stream contains unxpected data."
query.getLimit();
query.getOffset();
return Stream.of(); //Stream of empty Array to return without error



@Override
protected int sizeInBackEnd(Query<String, Void> query)
//Second way i mentioned, but this will not catch any Exception you didn't create, where as the try...catch has no way to let any Exception reach Vaadin.
if(badThingsHappened)
ErrorViewShower.showError(new UnsupportedOperationException("Bad things..."));
return 0;//Exiting without error









share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 27 at 21:14

























answered Mar 21 at 15:26









froemijojofroemijojo

714 bronze badges




714 bronze badges















  • Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

    – Steffen Harbich
    Mar 26 at 8:51






  • 1





    @SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

    – froemijojo
    Mar 26 at 11:10











  • Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

    – Steffen Harbich
    Mar 26 at 12:21











  • Copied your approach, still getting no redirect to error view.

    – Steffen Harbich
    Mar 26 at 12:36






  • 1





    Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

    – Steffen Harbich
    Mar 28 at 6:52

















  • Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

    – Steffen Harbich
    Mar 26 at 8:51






  • 1





    @SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

    – froemijojo
    Mar 26 at 11:10











  • Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

    – Steffen Harbich
    Mar 26 at 12:21











  • Copied your approach, still getting no redirect to error view.

    – Steffen Harbich
    Mar 26 at 12:36






  • 1





    Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

    – Steffen Harbich
    Mar 28 at 6:52
















Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

– Steffen Harbich
Mar 26 at 8:51





Indeed, the error handler is called, but that doesn't help me much because navigation or UI.getCurrent().getPage().executeJavaScript("window.location = '/my-error-page'") does not work within the error handler. My goal is to show an appropriate error page.

– Steffen Harbich
Mar 26 at 8:51




1




1





@SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

– froemijojo
Mar 26 at 11:10





@SteffenHarbich i edited my answer to include a way to get Vaadin to reroute to an error view.

– froemijojo
Mar 26 at 11:10













Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

– Steffen Harbich
Mar 26 at 12:21





Thank you for your answers. So this code is working in your case? I ask because when I call a UI.getCurrent().navigate in my error handler nothing happens except the usual Vaadin Flow error panel "Internal Error..take note of unsaved data..." in the upper right corner of the view. No redirect.

– Steffen Harbich
Mar 26 at 12:21













Copied your approach, still getting no redirect to error view.

– Steffen Harbich
Mar 26 at 12:36





Copied your approach, still getting no redirect to error view.

– Steffen Harbich
Mar 26 at 12:36




1




1





Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

– Steffen Harbich
Mar 28 at 6:52





Nice, that works fine. Let's hope Vaadin will fix the exception handling some day, so this workaround will not be required anymore. Thanks a lot for your help!

– Steffen Harbich
Mar 28 at 6:52








Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.







Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55210726%2fhow-to-handle-exceptions-thrown-in-dataprovider-methods-centrally%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

SQL error code 1064 with creating Laravel foreign keysForeign key constraints: When to use ON UPDATE and ON DELETEDropping column with foreign key Laravel error: General error: 1025 Error on renameLaravel SQL Can't create tableLaravel Migration foreign key errorLaravel php artisan migrate:refresh giving a syntax errorSQLSTATE[42S01]: Base table or view already exists or Base table or view already exists: 1050 Tableerror in migrating laravel file to xampp serverSyntax error or access violation: 1064:syntax to use near 'unsigned not null, modelName varchar(191) not null, title varchar(191) not nLaravel cannot create new table field in mysqlLaravel 5.7:Last migration creates table but is not registered in the migration table

은진 송씨 목차 역사 본관 분파 인물 조선 왕실과의 인척 관계 집성촌 항렬자 인구 같이 보기 각주 둘러보기 메뉴은진 송씨세종실록 149권, 지리지 충청도 공주목 은진현