Hi.
Once again I find myself in trouble using nested objects and changes to them. Sorry to ask for your help once more but I am unable to explain what I’m doing wrong (or even what is going wrong). Please bare with me.
To allow for editing and creating objects a number of levels deep, I have created a workaround that saves the parent object (if newly created) before child objects are added. The code below shows the general construction on this (within the editor of the parent):
@Inject
private Datasource<Parent> parentDs;
@Named("childsTable.create")
private CreateAction childCreateAction;
private boolean firstSave;
@Override
protected void postInit() {
Parent p = parentDs.getItem();
// If a required field is empty then this a new item
if (p.getTitle() == null) {
firstSave = true;
// If new, then we do not allow childs to be added until the object is saved
childCreateAction.setBeforeActionPerformedHandler(() -> {
// Save the object before adding anything
if (firstSave) {
firstSave = !super.commit();
}
return !firstSave;
});
}
}
Doing this works fine and I can create objects multiple levels deep. However, when altering the data of the parent AFTER the child has been added (and thus the parent already saved), there is an error:
java.lang.ClassCastException: org.eclipse.persistence.indirection.IndirectSet cannot be cast to com.haulmont.cuba.core.entity.Entity
at com.haulmont.cuba.gui.data.impl.DsContextImpl.replaceMasterCopies(DsContextImpl.java:351)
at com.haulmont.cuba.gui.data.impl.DsContextImpl.addToContext(DsContextImpl.java:329)
at com.haulmont.cuba.gui.data.impl.DsContextImpl.createCommitContext(DsContextImpl.java:265)
at com.haulmont.cuba.gui.data.impl.DsContextImpl.commit(DsContextImpl.java:160)
at com.haulmont.cuba.gui.components.EditorWindowDelegate.commit(EditorWindowDelegate.java:266)
at com.haulmont.cuba.web.gui.WebWindow$Editor.commitAndClose(WebWindow.java:1578)
at com.haulmont.cuba.gui.components.AbstractEditor.commitAndClose(AbstractEditor.java:109)
at com.axxemble.base27.web.risk.RiskEdit.onBtnSaveClick(RiskEdit.java:207)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.haulmont.cuba.gui.xml.DeclarativeAction.actionPerform(DeclarativeAction.java:92)
at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:44)
at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:510)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:200)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:163)
at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1037)
at com.vaadin.ui.Button.fireClick(Button.java:377)
at com.haulmont.cuba.web.toolkit.ui.CubaButton.fireClick(CubaButton.java:54)
at com.vaadin.ui.Button$1.click(Button.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:158)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:119)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:442)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:414)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)
at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.lambda$synchronizedHandleRequest$0(CubaVaadinServletService.java:314)
at com.haulmont.cuba.web.sys.CubaVaadinServletService.withUserSession(CubaVaadinServletService.java:196)
at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.synchronizedHandleRequest(CubaVaadinServletService.java:314)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1422)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:384)
at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:276)
at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:185)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:108)
at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:95)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1437)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
This error also occurs when doing this only one level deep (parent -> child).
On trial-and-error I found out that when replacing the default super.commitAndClose() with savind the data myself, I managed to avoid the error:
// Do our own save to avoid issues on the way back
CommitContext cc = new CommitContext().addInstanceToCommit(r);
dm.commit(cc);
// And close (forcefully) - but this doesn't refresh the table on the browser!
super.close(CLOSE_ACTION_ID, true);
However, in this case the initial browser window is not refreshed and newly created items are not shown. I know this can be overcome as well but it seems I’m on the wrong track here. It does however point out that somehow the default commit is “out-of-sync”?
I tried to set up a test project with this issue but somehow everything works fine in the test project. So, next I tried to strip the existing project to only have the essential code. In this way, I found out that when using only the above, the issue already occurs. Why this is different from the test project I have no idea.
The project has become rather big and I’ve not yet decided to make it open source so I am unable to attach it to this topic.
Any ideas what might be wrong here? I am hoping that the error (stacktrace) and description rings a bell to you…
Thanks in advance for your help.