Hi there,
I have a client websocket which receives messages from a server. I want to update my view every time a messages is received. But unfortunately it does not work. I get a NoSuchElementException: No value present when accessing the UI to do the update. When I use fireAsync()/@ObserveAsyncinstead of fire()/@Observe I even do not get an excecption at all (nor is my view updated).
Can someone please guide me in the right direction. I am kind of new to CDI. Maybe I missed something?
I am using Vaadin CDI + Event + Push.
- Vaadin Version 14.1.28
- Vaadin CDI 11.0.1
- Java EE 8.0.1
- WildFly 18.0.0
My view class, which shall be update:
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.page.Push;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.Command;
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.shared.communication.PushMode;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
@Route("")
@PWA(name = "Project Base for Vaadin Flow with CDI", shortName = "Project Base", enableInstallPrompt = false)
@CssImport("./styles/shared-styles.css")
@CssImport(value = "./styles/vaadin-text-field-styles.css", themeFor = "vaadin-text-field")
@Push(PushMode.MANUAL)
public class MainView extends VerticalLayout {
@Inject
private ClientWebsocket clientWebsocket;
private Button buConnect;
private Button buDisconnect;
private Label label;
@PostConstruct
public void init() {
buConnect = new Button("Connect", new ComponentEventListener<ClickEvent<Button>>() {
@Override
public void onComponentEvent(ClickEvent<Button> t) {
clientWebsocket.connect();
}
});
add(buConnect);
buDisconnect = new Button("DisConnect", new ComponentEventListener<ClickEvent<Button>>() {
@Override
public void onComponentEvent(ClickEvent<Button> t) {
clientWebsocket.disconnect();
}
});
add(buDisconnect);
label = new Label("Message: ");
add(label);
}
//public void updateView(@ObservesAsync MessageReceivedEvent messageReceivedEvent) {
public void updateView(@Observes MessageReceivedEvent messageReceivedEvent) {
System.out.println("Updating view.");
getUI().get().access(new Command() { // <-- This is where the exception gets thrown
@Override
public void execute() {
label.setText("Message: " + messageReceivedEvent.getMessage().getMessage());
getUI().get().push();
}
});
}
}
My websocket class:
import com.vaadin.cdi.annotation.VaadinSessionScoped;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
@VaadinSessionScoped
@ClientEndpoint(decoders = {MessageDecoder.class}, encoders = {MessageEncoder.class})
public class ClientWebsocket implements Serializable {
private String uri = "ws://localhost:8080/TestWebsocketsServer-1.0-SNAPSHOT/websockettest1";
private Session session = null;
@Inject
private Event<MessageReceivedEvent> messageReceivedEvent;
public ClientWebsocket() {
}
public boolean connect() {
try {
WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
webSocketContainer.connectToServer(this, new URI(uri));
return true;
} catch (URISyntaxException | DeploymentException | IOException ex) {
Logger.getLogger(ClientWebsocket.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}
public boolean disconnect() {
try {
session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Closed on user request."));
return true;
} catch (IOException ex) {
Logger.getLogger(ClientWebsocket.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
}
public boolean isClosed() {
return session == null || !session.isOpen();
}
@OnOpen
public void onOpen(Session session) {
this.session = session;
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
this.session = null;
}
@OnMessage
public void onMessage(Message message) {
System.out.println("Client - Received message: " + message.getMessage());
messageReceivedEvent.fireAsync(new MessageReceivedEvent(message));
}
}
The exception I get:
10:43:23,308 INFO [stdout]
(default task-60) Received message: Counter: 50
10:43:23,308 INFO [stdout]
(default task-60) Updating view.
10:43:23,308 ERROR [io.undertow.websockets.core.request]
(default task-60) UT025007: Unhandled exception for annotated endpoint com.packagename.myapp.ClientWebsocket@10aad88c: java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:141)
at deployment.my-starter-project-1.0-SNAPSHOT.war//com.packagename.myapp.MainView.updateView(MainView.java:65)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:95)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:85)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.injection.MethodInvocationStrategy$SimpleMethodInvocationStrategy.invoke(MethodInvocationStrategy.java:168)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:330)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:308)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:286)
at javax.enterprise.api//javax.enterprise.inject.spi.ObserverMethod.notify(ObserverMethod.java:124)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.util.Observers.notify(Observers.java:166)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.event.ObserverNotifier.notifySyncObservers(ObserverNotifier.java:285)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.event.ObserverNotifier.notify(ObserverNotifier.java:273)
at org.jboss.weld.core@3.1.2.Final//org.jboss.weld.event.EventImpl.fire(EventImpl.java:96)
at deployment.my-starter-project-1.0-SNAPSHOT.war//com.packagename.myapp.ClientWebsocket.onMessage(ClientWebsocket.java:81)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.annotated.BoundMethod.invoke(BoundMethod.java:87)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.annotated.AnnotatedEndpoint$2.onMessage(AnnotatedEndpoint.java:142)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.FrameHandler$7.run(FrameHandler.java:284)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:170)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.ServerWebSocketContainer$1.call(ServerWebSocketContainer.java:167)
at io.undertow.servlet@2.0.26.Final//io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow@18.0.0.Final//org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow@18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow@18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow@18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow@18.0.0.Final//org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.ServerWebSocketContainer.invokeEndpointMethod(ServerWebSocketContainer.java:604)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.ServerWebSocketContainer$6.run(ServerWebSocketContainer.java:590)
at io.undertow.websocket@2.0.26.Final//io.undertow.websockets.jsr.OrderedExecutor$ExecutorTask.run(OrderedExecutor.java:67)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads@2.3.3.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.base/java.lang.Thread.run(Thread.java:830)