I’m trying to use the push feature in Vaadin 7, and is working ok with components (Label), but I haven’t found a way to make it work with notifications.
My Runnable class is something like this:
private class MyClass implements Runnable {
Page page;
public NotificarMensajes(Page page) {
this.page = page;
}
@Override
public void run() {
label.setCaption("New Caption"); //Label inside the view
label.setIcon(newIcon);
Notification notification = new Notification("Notification Message"),
Notification.Type.TRAY_NOTIFICATION);
notification.setPosition(Position.TOP_RIGHT);
notification.setDelayMsec(10000);
//None of the below methods is working
notification.show(page); //Page passed in the instantiation
notification.show(UI.getCurrent().getPage());
notification.show(Page.getCurrent());
}
};
I pass a new instance to the access method of a UI configured to use the push feature according to the instruction shown
here . The Label label gets updated correctly, but the notification is never shown.
Am I doing something wrong? or is the Notification not supported with Push?
I also tried to update the page title with no success.
page.setTitle("New title");
Maybe I’ve got the wrong page? if so, then how should I get the valid instance?
Strange. I’m not able to reproduce this - notifications seem to work just fine with push. Could you provide a minimal but complete test application that demonstrates the issue, preferably a single self-contained UI class?
Finally I found the problem, I had an error with the instantiation of the Notification object. My actual code was something like this:
Notification notification = new Notification(String.format(
"You've got %d new messages.", currentUser.getName(),
newMessages), Notification.Type.TRAY_NOTIFICATION);
Where newMessages is an Integer and getName returns a String. Note the error in the string format, where I’m passing a String where should be an Integer. Normally this would lead to a java.util.IllegalFormatConversionException: d != java.lang.String exception, but it seems that the exception is lost inside the Runnable passed to the access method of UI.
In fact, I’ve tested throwing a RuntimeException inside run() in my Runnable and the exception is never shown. I don’t know if this is supposed to work that way, but I’d expected the Exception would be shown somewhere. I really had a bad time trying to find where was my error. BTW I’m using vaadin 7.1.6
Ah, sorry for your debugging woes. The reason for swallowing access() exceptions is that Vaadin internally uses Java FutureTasks to keep track of the access invocations (which can be asynchronous). Now, FutureTask catches all exceptions and stores them in the Future, only to be thrown if Future.get() is called. Fortunately, starting with 7.1.8, Vaadin does call Future.get() for you, and invokes the error handler mechanism if it throws (UI.getErrorHandler() if it’s set and UI.access was called; VaadinSession.getErrorHandler() otherwise). There’s also a “semi-public” interface ErrorHandlingRunnable that you can implement and pass to the access methods to handle errors “inline”.
Oh, thank you very much, I didn’t know about the FutureTask nor the other interface which can be used to handle errors inside runnable. I’ll use that instead, and see how it goes. Thanks!
Note that you have to upgrade to 7.1.8 - in fact, in 7.1.8 your original code would log the exception, instead of swallowing it, without any changes. So this might be a good argument for always using the latest maintenance release available
The FutureTask stuff is mostly implementation details - the main thing to realize is that the access is done asynchronously, possibly from another thread, so exceptions can’t just propagate normally to the method invoking access(). This is done to avoid some very common deadlock scenarios.
For future references, I’d like to point out that Notifications work as expected with Push, the only problem is with error handling inside the Runnable passed to the access method. But, starting with Vaadin 7.1.8, the errors inside Runnable are logged, and don’t get swallowed. The other alternative is to use the ErrorHandlingRunnable interface instead, and log the errors there.