Important Notice - Forums is archived
To simplify things and help our users to be more productive, we have archived the current forum and focus our efforts on helping developers on Stack Overflow. You can post new questions on Stack Overflow or join our Discord channel.

Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
Completablefuture with Vaadin
Hello. Trying to use Completablefuture with Vaadin and faced with an issue.
When trying to access from Completablefuture.thenAccept, I get an exception com.vaadin.ui.UIDetachedException. VaadinSession in UI is NULL.
If do execute Future with Executors.newFixedThreadPool(2), u will get com.vaadin.ui.UIDetachedException after two refresh of a page. If u will set 10, will get com.vaadin.ui.UIDetachedException after 10 refresh of a page.
So as i think that old threads cant be reused. Any idea ?
Can you show your code? Are you correctly using UI.access() method in your background threads?
When you refresh a page, if your UI is not annotated with @PreserveOnRefresh, it will be detached.
@Override
protected void init(VaadinRequest vaadinRequest) {
final Button clickMeButton = new Button("Click me", event -> {
doTask()
.thenAccept(onDone())
.handle(handleException());
});
setContent(clickMeButton);
}
private CompletableFuture<Void> doTask() {
return CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
}
private Consumer<Void> onDone() {
return aVoid -> UI.getCurrent().access(() -> Notification.show("Task id done"));
}
private BiFunction<Void, Throwable, Object> handleException() {
return (aVoid, throwable) -> {
Logger.getAnonymousLogger().log(Level.SEVERE, "", throwable);
return aVoid;
};
}
On first load all would be fine but if you will refresh a page and try again you will get
java.util.concurrent.CompletionException: com.vaadin.ui.UIDetachedException
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:273)
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:280)
at java.util.concurrent.CompletableFuture.uniAccept(CompletableFuture.java:659)
at java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:632)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1624)
at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1610)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1689)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
Caused by: com.vaadin.ui.UIDetachedException
at com.vaadin.ui.UI.access(UI.java:1434)
at hk.lear.MyUI.lambda$onDone$2(MyUI.java:57)
at hk.lear.MyUI$$Lambda$6/1880129221.accept(Unknown Source)
at java.util.concurrent.CompletableFuture.uniAccept(CompletableFuture.java:656)
... 8 more
Then run Future with ExecutorService
private CompletableFuture<Void> doTask() {
return CompletableFuture.runAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, [b]Executors.newSingleThreadExecutor()[/b]);
}
And you will never get previous Exception because Future always getting a fresh Thread
And yes. After UI.access with over time getting this error
Oct 26, 2015 10:14:53 AM org.atmosphere.container.Jetty9WebSocketHandler onWebSocketError
SEVERE: {}
java.net.SocketTimeoutException: Timeout on Read
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onReadTimeout(AbstractWebSocketConnection.java:526)
at org.eclipse.jetty.io.AbstractConnection.onFillInterestedFailed(AbstractConnection.java:173)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillInterestedFailed(AbstractWebSocketConnection.java:496)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback$1.run(AbstractConnection.java:582)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
So, you probably don't have @PreserveOnRefresh, this makes Vaadin detach the UI on refresh and create a new one. When you execute the task after refresh, it will try to access the old UI, because it was set for the thread previously.
To solve the problem, remove UI.getCurrent() and just call this.access, or use @PreserveOnRefresh.
Hope this works, tell us the result.
Actually, second thought, you can't just use @PreserveOnRefresh, you have to use this.access.
If you just use preserve on refresh, then if the user opens two tabs, all notifications will be shown in the first one, regardless of in which UI the button was pressed.
Is it right to get UI from Vaadin Component ? for example Panel.getUI. Coz in average i invoking UI.access not from main UI.
And what about this error ?
Oct 26, 2015 10:14:53 AM org.atmosphere.container.Jetty9WebSocketHandler onWebSocketError
SEVERE: {}
java.net.SocketTimeoutException: Timeout on Read
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onReadTimeout(AbstractWebSocketConnection.java:526)
at org.eclipse.jetty.io.AbstractConnection.onFillInterestedFailed(AbstractConnection.java:173)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillInterestedFailed(AbstractWebSocketConnection.java:496)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback$1.run(AbstractConnection.java:582)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
Michael Tzukanov: Actually, second thought, you can't just use @PreserveOnRefresh, you have to use this.access.
If you just use preserve on refresh, then if the user opens two tabs, all notifications will be shown in the first one, regardless of in which UI the button was pressed.
I've tried to do this.access - it works. So if i need an actual UI i can get it from attached Component ?
P.S. I don't want to use @PreserveOnRefresh
Yes, Component.getUI() should work correctly, if the component is attached.
Provide more details on how you get the SocketTimeoutException, I currently have no clue what causes it.
Dunno just using previous code and after execute UI.access with over time getting this exception.
Jetty 9.2.7v20150116. I think if you will create project with mine code with Jetty 9 you will get this error.
Hi Zhilin,
Do you have exmaple code for this case? Do you have tested your project with Vaadin 7.6.X? It shoukld have improvements for client server communication.