Exception saving an entity in DataContextImpl.mergeCommitted()

Hi,
I am getting the following exception when saving an entity ‘C’. This entity has a M-t-O association with another entity ‘B’, which at the time has another M-t-O association with an entity ‘A’.

This entity ‘A’ (in my project it is named ‘Empresa’, which means company in spanish) has a @Transient property ‘descriptivo’ dependent on two attributes, one of them is ‘nombre’ (means name in spanish).

So the problem is that upon committing changes I get the following exception:

java.lang.IllegalStateException: Cannot get unfetched attribute [nombre] from detached object contabilidad.entity.Empresa-8c504bd4-dfe1-007d-8b66-dc0a19f7fb00 [detached].
at org.eclipse.persistence.internal.queries.EntityFetchGroup.onUnfetchedAttribute(EntityFetchGroup.java:100)
at io.jmix.eclipselink.impl.JmixEntityFetchGroup.onUnfetchedAttribute(JmixEntityFetchGroup.java:67)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.processUnfetchedAttribute(EntityManagerImpl.java:3027)
at contabilidad.entity.Empresa._persistence_checkFetched(Empresa.java)
at contabilidad.entity.Empresa._persistence_get_nombre(Empresa.java)
at contabilidad.entity.Empresa.getNombre(Empresa.java:98)
at contabilidad.entity.Ejercicio.getDescriptivo(Ejercicio.java:61)
at io.jmix.core.entity.BaseEntityEntry.getAttributeValue(BaseEntityEntry.java:85)
at io.jmix.core.entity.EntityValues.getValue(EntityValues.java:100)
at io.jmix.ui.model.impl.DataContextImpl.mergeState(DataContextImpl.java:275)
at io.jmix.ui.model.impl.DataContextImpl.internalMerge(DataContextImpl.java:234)
at io.jmix.ui.model.impl.DataContextImpl.mergeState(DataContextImpl.java:313)
at io.jmix.ui.model.impl.DataContextImpl.internalMerge(DataContextImpl.java:234)
at io.jmix.ui.model.impl.DataContextImpl.merge(DataContextImpl.java:178)
at io.jmix.ui.model.impl.DataContextImpl.merge(DataContextImpl.java:189)
at io.jmix.ui.model.impl.DataContextImpl.mergeCommitted(DataContextImpl.java:776)
at io.jmix.ui.model.impl.DataContextImpl.commit(DataContextImpl.java:652)
at io.jmix.ui.screen.StandardEditor.lambda$commitChanges$9(StandardEditor.java:410)
at io.jmix.ui.screen.StandardEditor.commitChanges(StandardEditor.java:438)
at contabilidad.screen.asiento.AsientoEdit2.commitChanges(AsientoEdit2.java:869)
at io.jmix.ui.screen.StandardEditor.closeWithCommit(StandardEditor.java:599)
at io.jmix.ui.screen.StandardEditor.commitAndClose(StandardEditor.java:553)
at io.jmix.core.common.event.EventHub.publish(EventHub.java:170)
at io.jmix.ui.action.BaseAction.actionPerform(BaseAction.java:220)
at io.jmix.ui.component.impl.ButtonImpl.buttonClicked(ButtonImpl.java:75)
at io.jmix.ui.widget.JmixButton.fireClick(JmixButton.java:77)
at com.vaadin.ui.Button$1.click(Button.java:57)
at sun.reflect.GeneratedMethodAccessor261.invoke(Unknown Source)
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:153)
at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431)
at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396)
at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260)
at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82)
at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1607)
at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:449)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:101)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:92)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:147)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)

After some debugging, I come to a line of code in DataContextImpl (line 651)

EntitySet committedAndMerged;
try {
Set committed = performCommit();
committedAndMerged = mergeCommitted(committed);
} finally {
nullIdEntitiesMap.clear();
}

where the ‘modifiedInstances’ memeber of the DataContextImpl class, contains all instances with attributes populated, so no problem. But when calling performCommit(), the set of instances returned containts many attributes set to null. And the problem arises inside the next method call mergeCommitted(committed), which tries to merge the committed entities, firing the above provided exception.

Have done quite introspection to find a workaround but I am not getting through. Have even tried specifiying a different fetchplan where all necessary attributes are populated, but no luck either.

Any help is greatly appreciated.

Regards,
Carlos.

Hi Carlos,

Could you provide a small test project where the problem is reproduced?
It would eliminate a lot of uncertainty in modelling the situation.

Regards,
Konstantin

There you have the whole project.

Contabilidad.zip (794.5 KB)

The problem concretely appears upon clicking Ok on the screen AsientoEdit2 (Ver Asientos->Click on any and enter AsientoEdit2.screen. ->Click Ok and you will get the error.

What most confuses me is that the unfetched property is a transient @JmixProperty from Ejercicio class (in fact the nombre property of the related Empresa entity). Don’t really understand why a problem arises at merging this property. Besides, all fetch planning with that screen has been carefully examined ot enable that the Empresa.nombre property is correctly fetched in advance.

But as stated in the first post, the problem comes when merging the committed results, not the commit operation itself. The data is correctly saved, only when merging the committed instances in the datacontext, the exception arises.

Any help is greatly appreciated. Don’t know how to continue, and this is keeping us partially stuck.

For you to reproduce exactly the error will have to load this database. It is a subset of the whole database, but will do to reproduce the exception.

// deleted attachment

Thanks for your help. Best regards.

Carlos.

I think I had the same problem a lot of times. If you set @JmixProperty the @Transient is not taken into account anymore. It appears in Jmix you can’t have an attribute that is both, but it would make sense. I often want a calculated attribute, that has no representation in the data model and is just ignored during datastore logic.

Hi Klaus,

thanks for your answer. Ok. Don’t understand that kind of incompatibililty. It detriments the functionality of the platform from my perspective. Any way what I did was as you suggested, turn that method property into an entity attribute and assign it a column. Not the solution I wanted, since the data is redundant. but for the time being it allows me to keep going.

However won’t mark this post as solved until someone sheds some light about this discussion. It is certainly very inconvenient not to be able to create a property usable in the ui based on a transient property.

Thanks for the discussion.

Regards,
Carlos.

Hi Carlos,

Thank you for the test project.
I’ve checked it with the latest 1.2.0-SNAPSHOT version of Jmix and the problem is gone.
Most probably because of this change: https://github.com/Haulmont/jmix-data/issues/109

Please let us know if you face similar problems after upgrading to Jmix 1.2.

Regards,
Konstantin

1 Like