Handling uncaught (vaadin core) exceptions

Hello,

I am now in process of migrating existing project from vaadin 6 to vaadin 7 and hit upon the following problem:

when an exception in vaadin core occurres, e.g. when there is no appropriate converter for a type when binding object to a field, then a com.vaadin.server.ServiceException is thrown and a tomcat 500 error page is shown.

In vaadin 6 there was a method terminalError in Application to override, which, if I am not mistaking, also covered the case where an error in vaadin core occured.

In vaadin 7 there is a possibility to set an error handler on VaadinSession respectivly UI. However if expception like
com.vaadin.data.util.converter.Converter$ConversionException is thrown then the custom error handler has no possiblity to prevent Vaadin from throwing an ServletException in VaadinServlet.service method, which causes then tomcat to display 500 error page with entire stack trace.

Reloading a page does not bring user back to the application again, but still shows 500 error page.

I have tried so far:

  • to derive from VaadinServlet class and overwrite service method such that exception is not thrown, but in this case the loading indicator is shown and the application UI is not visible.
  • also in dereived VaadinServlet to invalidate session to restart application - but at this point it seems to be no session avail.
  • to define custom error page in web.xml using

<error-page> <error-code>500</error-code> <location>/500.html</location> </error-page> and placing 500.html to following folder:

  • WebContent
  • WEB-INF
  • Vaadin

but in either case my page was not shown and in log I could see Exception Processing ErrorPage[errorCode=500, location=/500.html]

Probably because of servlet mapping (or is the mapping correct?):

<servlet-mapping> <servlet-name>Exoportal Application</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> So the question is:
is there a way to prevent vaadin from showing 500 error page and let application handling the exception - log it to file, show user a message that error occured and then “restart” the application for the given user, s.t. he can restart his work.

Hello,

Could you elaborate a bit in which kind of a situation you get a ConversionException that leaks all the way to the container? For instance, can you provide a stack trace? UI-level exceptions like that should be caught and the proper error handler invoked without propagating the exception to the servlet level.

Hello Johannes,

here the stack trace:

description The server encountered an internal error () that prevented it from fulfilling this request.

exceptionjavax.servlet.ServletException: com.vaadin.server.ServiceException: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type com.exocad.exoportal.model.ArticleType to presentation type class java.lang.String. No converter is set and the types are not compatible. com.vaadin.server.VaadinServlet.service(VaadinServlet.java:239) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)root causecom.vaadin.server.ServiceException: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type com.exocad.exoportal.model.ArticleType to presentation type class java.lang.String. No converter is set and the types are not compatible. com.vaadin.server.VaadinService.handleExceptionDuringRequest(VaadinService.java:1463) com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1417) com.vaadin.server.VaadinServlet.service(VaadinServlet.java:237) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)root causecom.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type com.exocad.exoportal.model.ArticleType to presentation type class java.lang.String. No converter is set and the types are not compatible. com.vaadin.data.util.converter.ConverterUtil.convertFromModel(ConverterUtil.java:116) com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:708) com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:693) com.vaadin.ui.AbstractField.getFieldValue(AbstractField.java:316) com.vaadin.ui.AbstractField.validate(AbstractField.java:928) com.vaadin.ui.AbstractField.getErrorMessage(AbstractField.java:1037) com.vaadin.ui.AbstractComponent.beforeClientResponse(AbstractComponent.java:676) com.vaadin.ui.AbstractField.beforeClientResponse(AbstractField.java:1699) com.vaadin.ui.AbstractTextField.beforeClientResponse(AbstractTextField.java:105) com.vaadin.server.communication.UidlWriter.write(UidlWriter.java:97) com.vaadin.server.communication.UIInitHandler.getInitialUidl(UIInitHandler.java:295) com.vaadin.server.communication.UIInitHandler.synchronizedHandleRequest(UIInitHandler.java:80) com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1405) com.vaadin.server.VaadinServlet.service(VaadinServlet.java:237) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)note The full stack trace of the root cause is available in the Apache Tomcat/6.0.26 logs.

Apache Tomcat/6.0.26

The problem I have seems to be similar to this one: https://vaadin.com/forum/#!/thread/4007363.

I have a table and add in drop handler an “composite” item from a tree structure:

table.setDropHandler(new DropHandler() {
public void drop(DragAndDropEvent dropEvent) {
// criteria verify that this is safe
DataBoundTransferable t = (DataBoundTransferable) dropEvent.getTransferable();
if (!(t.getSourceContainer() instanceof Container.Hierarchical)) {
return;
}
Container.Hierarchical source = (Container.Hierarchical) t.getSourceContainer();

            Object sourceItemId = t.getItemId();

            // find and convert the item(s) to move

            Object parentItemId = source.getParent(sourceItemId);
            // map from moved source item Id to the corresponding Hardware
            LinkedHashMap<Object, Object[]> articleMap = new LinkedHashMap<Object, Object[]

();
if (parentItemId == null) {
// move the whole subtree
// String category = getTreeNodeName(source, sourceItemId);
Collection children = source.getChildren(sourceItemId);
if (children != null)
for (Object childId : children) {
Article article = getTreeNodeArticle(source, childId);
if (!canAddArticleToBasket(article))
continue;
articleMap.put(childId, new Object { article,
article.getArticleType(),
article.getName(), 1 });
}
} else {
// move a single hardware item
// String category = getTreeNodeName(source, parentItemId);
Article article = getTreeNodeArticle(source, sourceItemId);
if (canAddArticleToBasket(article))
articleMap.put(sourceItemId, new Object { article,
article.getArticleType(), article.getName(), 1 });
}

            // move item(s) to the correct location in the table

            AbstractSelectTargetDetails dropData = ((AbstractSelectTargetDetails) dropEvent.getTargetDetails());
            Object targetItemId = dropData.getItemIdOver();

            for (Object sourceId : articleMap.keySet()) {
                Object[] data = articleMap.get(sourceId);
                Object newItemId = ((Article) data[0]

);
if (targetItemId != null) {
switch (dropData.getDropLocation()) {
case BOTTOM:
table.addItemAfter(targetItemId, newItemId);
break;
case MIDDLE:
case TOP:
Object prevItemId = table.prevItemId(targetItemId);
table.addItemAfter(prevItemId, newItemId);
break;
}
} else {
table.addItem(newItemId);
}
Item item = table.getItem(newItemId);
item.getItemProperty(a_PROPERTY_THIS).setValue(data[0]
);
item.getItemProperty(a_PROPERTY_CATEGORY).setValue(data[1]
); // enum value
item.getItemProperty(a_PROPERTY_NAME).setValue(data[2]
); // String
item.getItemProperty(a_PROPERTY_QUANTITY).setValue(data[3]
); // int

                source.removeItem(sourceId);
            }
        }

      
    });

All right, so this is during the initial UI rendering when you load the app or refresh the browser page? That’s a somewhat tricky situation regarding to error handling as there’s no UI in which to show any error notifications or similar. I think, though, that in all cases the session error handler
ought
to be able to stop the exception from leaking to the container, if it wants to. The way
VaadinService.handleExceptionDuringRequest
currently works is not very nice. I think I’ll open a ticket about the issue…

In your case, however, I think there may be a bug in your code (incompatible types ArticleType and String without a converter specified), and it wouldn’t matter how many times you try to reload the application. You can’t “bypass” the error as it prevents the UI from being rendered in the first place.

Although, now that I think about this a bit more, the UI rendering could probably benefit from more fine-grained error handling so that an issue with a single component wouldn’t kill the whole application. In this case, specifically, the error originates from
ClientConnector.beforeClientResponse
which is potentially user code and the call in
UidlWriter.write
should be enclosed in a try block. This is also worth a ticket.

I use LegacyAppliction together with LegacyWindow. In window I have a tree with available items on the left and a table (initially empty, serves like a shop basket) on the right. The user can drag&drop items from the tree to the table and choose a quantity and remove the items.

The table has following columns:

  1. Item itself
  2. Item type (ArticleType - which is an enum - enum with custom value like EnumTest in http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
  3. quantity


When I drop article from tree to table an error occurres.

Yes it is a bug at my code, and it is fixed already by introducing converter (In vadin 6 it was however perfect working). However it should
only
serve as example where exception handling would not work perfectly - i.e. user get an entire stack trace of my application.

by the way - the edit functionality in FF 30 is broken, if I click edit then the edit dialog appears but nothing happens if I click “Confirm edit” or “Discard changes”

With Chrome it is working :slight_smile:

Hmm… All right. I’m not sure what exactly is happening

Yes, indeed. Production servers should always be configured to show a custom error page instead of stack traces, but Vaadin error handling could be more customizable as well. I opened tickets
#14212
and
[/url]
#14214
.