My problem is that in my app not show notification.
My application does that each time a button is pressed I create new thread and show notification with info that thread is running or waiting (this works fine). Then, if the thread is running, it will randomly sleep for 5-10 seconds and get data from the rest api and a notification should be displayed that the thread is finished (this notification is not displayed).
Fineshed notifications show after i press again button. As you can see in the image.
constructor view:
public MainView() {
Button ipButton = getIpButton();
setMargin(true);
setHorizontalComponentAlignment(Alignment.START, ipButton);
add(ipButton);
}
button:
private Button getIpButton() {
final UI ui = UI.getCurrent();
final VaadinSession session = VaadinSession.getCurrent();
Button ipButton = new Button("My IP");
AtomicInteger orderIndex = new AtomicInteger();
ipButton.addClickListener(_e -> {
int orderThread = orderIndex.getAndIncrement();
openBeginNotification(orderThread);
executor.submit(() -> {
try {
UI.setCurrent(ui);
VaadinSession.setCurrent(session);
long sleepTime = (long) (Math.random() * (10 - 5) 5);
System.out.printf("%d: %ds\n", orderThread, sleepTime);
Thread.sleep(sleepTime * 1000);
IpDTO ip = restTemplate.getForObject("http://ip.jsontest.com/", IpDTO.class);
System.out.printf("%d: %s\n", orderThread, ip);
try {
VaadinSession.getCurrent().lock();
getFinishNotification(orderThread).open(); // here not show notification
VaadinSession.getCurrent().unlock();
} catch (Exception e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
});
return ipButton;
}
notification methods:
private void openBeginNotification(int orderThread) {
Notification notification;
if (executor.getActiveCount() == MAX_THREADS) {
// thread is in front
notification = getWaitNotification(orderThread);
} else {
// thread run
notification = getRunNotification(orderThread);
}
notification.open();
}
private Notification getRunNotification(int orderThread) {
return getNotification("Task " orderThread ": run", NotificationVariant.LUMO_PRIMARY);
}
private Notification getWaitNotification(int orderThread) {
return getNotification("Task " orderThread ": wait", NotificationVariant.LUMO_CONTRAST);
}
private Notification getFinishNotification(int orderThread) {
return getNotification("Task " orderThread ": finish", NotificationVariant.LUMO_SUCCESS);
}
private Notification getNotification(String notificationText, NotificationVariant variant) {
Notification notification = new Notification(notificationText, 1000);
notification.addThemeVariants(variant);
return notification;
}
CodePudding user response:
First, you need to enable @Push
to make Vaadin open a websocket connection that makes it possible for the server to directly send messages to the browser without waiting for the browser to send a message asking for changes (which happens when you click a button). The @Push
annotation should be in different location depending on the Vaadin version you're using, so please refer to documentation to find the right place.
Second, please use UI::access
instead of manually doing setCurrent
and locking. While I didn't spot anything in your example that would break the happy case, there are still also a whole bunch of edge cases that you'd need to take into account. As an example, you're not cleaning up after setCurrent
which might cause memory leaks and you're not unlocking in case something related to the notification throws an exception.