I want to use keyboard shortcuts in a vaadin flow 23 application inside an active grid editor. I get occasionally an exception in the test server which I can not reproduce locally:
java.lang.NullPointerException: Cannot invoke "com.vaadin.flow.component.Component.isVisible()" because "component" is null
2023-11-13 08:10:45.030 ERROR 1 --- [nio-8000-exec-9] c.v.flow.server.DefaultErrorHandler :
at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:447) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:292) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:475) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:233) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.component.ShortcutRegistration.lambda$updateHandlerListenerRegistration$89e5c563$1(ShortcutRegistration.java:551) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.component.ShortcutRegistration.fireShortcutEvent(ShortcutRegistration.java:591) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.component.ShortcutRegistration.ancestorsOrSelfAreVisible(ShortcutRegistration.java:598) ~[flow-server-23.3.18.jar!/:23.3.18]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na]
at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:447) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:62) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:106) ~[vaadin-spring-23.3.18.jar!/:na]
at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:369) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1560) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:320) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:115) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:419) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:438) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:419) ~[flow-server-23.3.18.jar!/:23.3.18]
at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:75) ~[flow-server-23.3.18.jar!/:23.3.18]
I want the shortcuts only to be active while the editor is opened. Therefore my code looks like this:
editColumn.setEditorComponent(getEditRowButtonsLayout());
private HorizontalLayout getEditRowButtonsLayout() {
saveEditButton = new Button();
cancelEditButton = new Button();
saveEditButton.addClickListener(event -> save());
cancelEditButton.addClickListener(event -> editor.cancel());
return new HorizontalLayout(saveEditButton, cancelEditButton);
}
editor.addOpenListener(event -> registerShortcuts());
editor.addCloseListener(event -> removeShortcuts());
private void registerShortcuts() {
enterShortcut = saveEditButton.addClickShortcut(Key.ENTER);
numpadEnterShortcut = saveEditButton.addClickShortcut(Key.NUMPAD_ENTER);
escapeShortcut = cancelEditButton.addClickShortcut(Key.ESCAPE);
}
private void removeShortcuts() {
enterShortcut.remove();
numpadEnterShortcut.remove();
escapeShortcut.remove();
}
Is this a bug in the event firing mechanism or am I implementing this feature wrong?
UPDATE: Unfortunately rejoyed too soon. I changed the code as suggested and still get occasionally the exception as described above. Can not reproduce it either.
private void registerShortcuts() {
enterShortcut = UI.getCurrent().addShortcutListener(this::saveEdited, Key.ENTER);
numpadEnterShortcut = UI.getCurrent().addShortcutListener(this::saveEdited, Key.NUMPAD_ENTER);
escapeShortcut = UI.getCurrent().addShortcutListener(event -> editor.cancel(), Key.ESCAPE);
}
To me it looks like a bug because there is a "isVisible()" check in the ShorcutRegistration class without null check. Still can't wrap it up because it is not reproducible and works most of the time.