I used the crudui to display a entity which contains a OneToMany relationship with the data type List. Then opening the update dialog fails because of:
java.lang.ClassCastException:
class org.hibernate.collection.internal.PersistentBag cannot be cast to class java.util.Set
CrudUI2.3.1 Vaadin8.11.0
Person.java
@Entity
@Table(name = "TBL_PERSON")
public class Person implements {
@Id
private String serial;
private String firstName;
private String lastName;
@OneToMany(fetch = FetchType.EAGER)
private List<Address> contacts;
}
To reproduce create a crud for the provided model an click on the update pen.
Problem
The problem is, that the form adds a combobox for the field contacts with a default data model of type Set. But of course, hibernate provides a PersistentBag which is a subtype of List. So it's not possible for the crudui to set the loaded data to the form.
Is there a possibility to add support for displaying a @OneToMany realtionship?
Workaround
As workaround i set a custom CrudFormFactory which provices a custom field provider for the field contancs - which seems to be a very hacky.
var grid = new GridCrud(type, listConfigFix(Person.class));
private VerticalCrudFormFactory<?> listConfigFix(Class<?> type) {
var verticalCrudFormFactory = new VerticalCrudFormFactory<>(type);
verticalCrudFormFactory.setFieldProvider("contacts", (FieldProvider) () -> {
var textField = new ComboBox<>();
textField.setValue(List.of());
return textField;
});
return verticalCrudFormFactory;
}
Stacktrace
java.lang.ClassCastException: class org.hibernate.collection.internal.PersistentBag cannot be cast to class java.util.Set (org.hibernate.collection.internal.PersistentBag is in unnamed module of loader 'app'; java.util.Set is in module java.base of loader 'bootstrap')
at com.vaadin.ui.AbstractMultiSelect.setValue(AbstractMultiSelect.java:61)
at com.vaadin.data.Binder$BindingImpl.initFieldValue(Binder.java:1155)
at com.vaadin.data.Binder$BindingImpl.access$100(Binder.java:1001)
at com.vaadin.data.Binder.lambda$readBean$2(Binder.java:1709)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1510)
at com.vaadin.data.Binder.readBean(Binder.java:1702)
at org.vaadin.crudui.form.AbstractAutoGeneratedCrudFormFactory.buildFields(AbstractAutoGeneratedCrudFormFactory.java:146)
at org.vaadin.crudui.form.impl.form.factory.VerticalCrudFormFactory.buildNewForm(VerticalCrudFormFactory.java:23)
at org.vaadin.crudui.crud.impl.GridCrud.gridSelectionChanged(GridCrud.java:138)
at org.vaadin.crudui.crud.impl.GridCrud.lambda$initLayout$5e26faff$1(GridCrud.java:86)
at com.vaadin.ui.components.grid.SingleSelectionModel.lambda$addSelectionListener$91fe6b9f$1(SingleSelectionModel.java:56)
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:564)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:499)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:273)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:237)
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1014)
at com.vaadin.ui.components.grid.SingleSelectionModelImpl.setSelectedFromClient(SingleSelectionModelImpl.java:158)
at com.vaadin.ui.components.grid.SingleSelectionModelImpl$1.select(SingleSelectionModelImpl.java:52)
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:564)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:155)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:116)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:445)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:410)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.PushHandler.lambda$new$1(PushHandler.java:148)
at com.vaadin.server.communication.PushHandler.callWithUi(PushHandler.java:248)
at com.vaadin.server.communication.PushHandler.onMessage(PushHandler.java:534)
at com.vaadin.server.communication.PushAtmosphereHandler.onMessage(PushAtmosphereHandler.java:87)
at com.vaadin.server.communication.PushAtmosphereHandler.onRequest(PushAtmosphereHandler.java:77)
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:225)
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:114)
at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:67)
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2297)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:594)
at org.atmosphere.websocket.DefaultWebSocketProcessor$3.run(DefaultWebSocketProcessor.java:345)
at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:340)
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:448)
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:272)
at org.atmosphere.container.JSR356Endpoint$3.onMessage(JSR356Endpoint.java:269)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82)
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171)
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148)
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:834)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:832)
I used the crudui to display a entity which contains a
OneToMany
relationship with the data typeList
. Then opening the update dialog fails because of:CrudUI
2.3.1
Vaadin
8.11.0
Person.java
To reproduce create a crud for the provided model an click on the update pen.
Problem
The problem is, that the form adds a combobox for the field
contacts
with a default data model of typeSet
. But of course, hibernate provides aPersistentBag
which is a subtype ofList
. So it's not possible for the crudui to set the loaded data to the form.Is there a possibility to add support for displaying a
@OneToMany
realtionship?Workaround
As workaround i set a custom
CrudFormFactory
which provices a custom field provider for the fieldcontancs
- which seems to be a very hacky.Stacktrace