RuntimeException: Unable to access value holder for property (test project included)

There seems to be a problem with the new lazy loading mechanism. Unfortunately the setup to reproduce the bug is a bit complex, but totally relevant to actual applications.

I attached a minimum test project. Just click on invoices and try to edit an invoice.

singlevalueholderexception.zip (100.9 KB)

Steps to reproduce the data: (is already in the test project)

  1. insert two companies
  2. insert two invoices
  3. insert an employee
  4. set both invoices as “paidBy” this employee
  5. open one of the invoices

My breakdown of the problem so far:

  • invoice A (clicked on invoice in browse) gets loaded
  • paidBy employee is in data context
  • lazy loading mechanism trys to load all invoices from employee (because of property Employee.invoices)
  • meta property function getCompany of invoices fails to load (isLoaded() of property == false)
  • lazy loading tries to load it, but requires a field in io.jmix.eclipselink.impl.lazyloading.ValueHoldersSupport#getSingleValueHolder → this field doesn’t exist obviously for meta property function, so we get the RuntimeException

This is really holding me back. Can’t find a work-around also. Any help is greatly appreciated.

Regards,
Klaus

PS:

This is the stacktrace
2021-11-21 14:04:22.082 ERROR 464251 --- [nio-8080-exec-2] i.j.u.exception.DefaultExceptionHandler  : Unhandled exception

com.vaadin.event.ListenerMethod$MethodException: Invocation of method itemClick in io.jmix.ui.component.impl.AbstractTable$$Lambda$1390/0x0000000800d31440 failed.
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:729) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:399) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:363) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1216) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.v7.ui.Table.handleClickEvent(Table.java:3198) ~[vaadin-compatibility-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.v7.ui.Table.changeVariables(Table.java:2988) ~[vaadin-compatibility-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at io.jmix.ui.widget.JmixTable.changeVariables(JmixTable.java:357) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.widget.JmixGroupTable.changeVariables(JmixGroupTable.java:297) ~[jmix-ui-1.1.0.jar:na]
	at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:616) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:468) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:411) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:275) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:83) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1636) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:465) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:750) ~[javax.servlet-api-4.0.1.jar:4.0.1]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:327) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:81) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:121) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:105) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:101) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:92) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:147) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.10.jar:5.3.10]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:110) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.10.jar:5.3.10]
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:211) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.5.2.jar:5.5.2]
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.10.jar:5.3.10]
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.10.jar:5.3.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.10.jar:5.3.10]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.10.jar:5.3.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.10.jar:5.3.10]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.10.jar:5.3.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.10.jar:5.3.10]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.10.jar:5.3.10]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1726) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.53.jar:9.0.53]
	at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: java.lang.RuntimeException: Unable to access value holder for property: company on entity com.company.singlevalueholderexception.entity.Invoice
	at io.jmix.eclipselink.impl.lazyloading.ValueHoldersSupport.getSingleValueHolder(ValueHoldersSupport.java:38) ~[jmix-eclipselink-1.1.0.jar:na]
	at io.jmix.eclipselink.impl.DataEntitySystemStateSupport.mergeLazyLoadingState(DataEntitySystemStateSupport.java:104) ~[jmix-eclipselink-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.mergeLazyLoadingState(DataContextImpl.java:391) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.mergeState(DataContextImpl.java:335) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.internalMerge(DataContextImpl.java:225) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.mergeList(DataContextImpl.java:425) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.mergeState(DataContextImpl.java:307) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.internalMerge(DataContextImpl.java:225) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.mergeState(DataContextImpl.java:315) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.internalMerge(DataContextImpl.java:225) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.DataContextImpl.merge(DataContextImpl.java:157) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.model.impl.InstanceLoaderImpl.load(InstanceLoaderImpl.java:104) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.component.dataloadcoordinator.OnFrameOwnerEventLoadTrigger.load(OnFrameOwnerEventLoadTrigger.java:48) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.component.dataloadcoordinator.OnFrameOwnerEventLoadTrigger.lambda$new$0(OnFrameOwnerEventLoadTrigger.java:39) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.core.common.event.EventHub.publish(EventHub.java:170) ~[jmix-core-1.1.0.jar:na]
	at io.jmix.ui.screen.Screen.fireEvent(Screen.java:124) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.screen.UiControllerUtils.fireEvent(UiControllerUtils.java:58) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.sys.ScreensImpl.fireScreenBeforeShowEvent(ScreensImpl.java:1361) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.sys.ScreensImpl.show(ScreensImpl.java:354) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.screen.Screen.show(Screen.java:306) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.action.list.EditAction.execute(EditAction.java:377) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.action.list.EditAction.actionPerform(EditAction.java:324) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.component.impl.AbstractTable.handleClickAction(AbstractTable.java:1384) ~[jmix-ui-1.1.0.jar:na]
	at io.jmix.ui.component.impl.AbstractTable.lambda$initComponent$db766529$1(AbstractTable.java:1122) ~[jmix-ui-1.1.0.jar:na]
	at jdk.internal.reflect.GeneratedMethodAccessor93.invoke(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:709) ~[vaadin-server-8.14.1-0-jmix.jar:8.14.1-0-jmix]
	... 90 common frames omitted

2021-11-21 14:04:22.097  WARN 464251 --- [nio-8080-exec-2] com.vaadin.event.EventRouter             : Adding listeners with type Object is deprecated, event listener should extend SerializableEventListener

Thank you for the report and the test project.
We are working on a similar issue, perhaps we’ll fix it in the next update.

Regards,
Konstantin

1 Like

Hi @krivopustov ,

I did a monkey patch locally and it fixes the problem for transient fields. There is still an issue with embedded attributes though.

See this line: https://github.com/Haulmont/jmix-ui/blob/d4f5bbe58ba0a1739b0e9a091a4b8f5b4314c328/ui/src/main/java/io/jmix/ui/model/impl/DataContextImpl.java#L389

… and just change it to:

            if (property.getRange().isClass() && !property.getAnnotatedElement().isAnnotationPresent(Transient.class)) {