Dynamic attributes and inherited entities

I found (at least for me) a strange behavior of the great dynamic attributes feature. I have a main entity Substance with defined dynamic attributes, and another entity Solution that inherits from Substance, with “single table” as inheritance strategy.

Storing values in dynamic attributes in the parent entity works fine. But when I edit a dynamic attribute for a Solution in the Substance.edit screen and save it, it throws a NullPointerException and fails. Every other field works ok, the problem is on the dynamic field.

I found that creating the same dynamic attributes, with the same names but no target visualization for the Solution seems to solve the problem. Although the Substance.edit screen works only with the parent entity substances, it seems that the dynamic attributes values go to the inherited entity. It has some logic, but I’m not sure if I’m doing things right or perhaps is there any other way to prevent duplicating dynamic attributed in each inherited entity.

Am I right ?

Thanks !

Alejandro

Hi Alejandro,
Could you provide the exception stack trace?

Here you are

java.lang.NullPointerException

               at com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesManager.doStoreDynamicAttributes(DynamicAttributesManager.java:259)

               at com.haulmont.cuba.core.app.dynamicattributes.DynamicAttributesManager.storeDynamicAttributes(DynamicAttributesManager.java:191)

               at com.haulmont.cuba.core.app.RdbmsStore.commit(RdbmsStore.java:416)

               at com.haulmont.cuba.core.app.DataManagerBean.commit(DataManagerBean.java:161)

               at com.haulmont.cuba.core.app.DataServiceBean.commit(DataServiceBean.java:41)

               at sun.reflect.GeneratedMethodAccessor760.invoke(Unknown Source)

               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

               at java.lang.reflect.Method.invoke(Method.java:498)

               at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)

               at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)

               at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)

               at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:84)

               at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:117)

               at sun.reflect.GeneratedMethodAccessor123.invoke(Unknown Source)

               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

               at java.lang.reflect.Method.invoke(Method.java:498)

               at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:627)

               at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:616)

               at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70)

               at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)

               at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)

               at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)

               at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)

               at com.sun.proxy.$Proxy105.commit(Unknown Source)

               at sun.reflect.GeneratedMethodAccessor759.invoke(Unknown Source)

               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

               at java.lang.reflect.Method.invoke(Method.java:498)

               at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:94)

               at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:154)

               at com.sun.proxy.$Proxy246.commit(Unknown Source)

               at com.haulmont.cuba.client.sys.DataManagerClientImpl.commit(DataManagerClientImpl.java:100)

               at com.haulmont.cuba.gui.data.impl.GenericDataSupplier.commit(GenericDataSupplier.java:105)

               at com.haulmont.cuba.gui.data.impl.DsContextImpl.commit(DsContextImpl.java:166)

               at com.haulmont.cuba.gui.components.EditorWindowDelegate.commit(EditorWindowDelegate.java:271)

               at com.haulmont.cuba.web.gui.WebWindow$Editor.commitAndClose(WebWindow.java:1773)

               at com.haulmont.cuba.gui.components.AbstractEditor.commitAndClose(AbstractEditor.java:111)

               at com.haulmont.cuba.gui.components.EditorWindowDelegate.lambda$wrapBy$1(EditorWindowDelegate.java:94)

               at com.haulmont.cuba.gui.components.actions.BaseAction.actionPerform(BaseAction.java:228)

               at com.haulmont.cuba.web.gui.components.WebButton.performAction(WebButton.java:46)

               at com.haulmont.cuba.web.gui.components.WebButton.lambda$new$61446b05$1(WebButton.java:38)

               at sun.reflect.GeneratedMethodAccessor417.invoke(Unknown Source)

               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:69)

               at com.vaadin.ui.Button$1.click(Button.java:54)

               at sun.reflect.GeneratedMethodAccessor392.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:158)

               at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:119)

               at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:444)

               at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:409)

               at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:274)

               at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:90)

               at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)

               at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1435)

               at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:361)

               at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:312)

               at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:203)

               at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)

               at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812)

               at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)

               at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107)

               at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73)

               at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:107)

               at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)

               at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)

               at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)

               at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)

               at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)

               at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)

               at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)

               at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)

               at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)

               at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)

               at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110)

               at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)

               at org.eclipse.jetty.server.Server.handle(Server.java:499)

               at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)

               at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)

               at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)

               at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)

               at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)

               at java.lang.Thread.run(Thread.java:748)

Konstantin,

There is another negative side effect to this behavior. Since the dynamic attributes are stored in the inherited entity, you can’t use them in a filter when you browse the parent entity (Substance.browse). When you apply the filter, it only works on the parent entity. No instance of the inherited matches the filter.

Thanks !!

Alejandro

Hi Alejandro
I’ve created an issue for NPE: NPE when saving dynamic attributes in edit screen of base entity · Issue #2002 · cuba-platform/cuba · GitHub
But I’m not sure that the attributes of the inherited entity must be available when searching for base entity. It’s the same as for regular attributes: a parent cannot work with attributes of its children.

Hi,
Unfortunately, inheritance doesn’t work for dynamic attributes. We have an enhancement: Support dynamic attribute on superclass · Issue #916 · cuba-platform/cuba · GitHub

Thanks guys for your wonderful support !!

Hi,

Is there any update on this enhancement ?

Thanks,

Alejandro

Hi Alejandro,
I’m sorry, but it’s not on our roadmap.

Regards,
Konstantin

No problem, thanks for the update.