Thursday, 3 May 2012

Binding spring form using bean with map attribute retrieved using hibernate

Another one exception bit me today. Spring forms nicely support maps as bean properties using 'mapProperty[key].mapElementProperty' paths, but each time I tried to submit form, exception was thrown (see below). As it turns out, problem was caused by hibernate which returned bean proxy. When setting map element property values after form submit, Spring tries to find out what type of elements map contains using generics information (... using some kind of magic), but in the end it didn't work. Not sure, but I suppose it could be because javassist can't handle generics because of type erasure. Solution was simple - modify DAO method which returned editable object (getById(id)) so that it would not return a hibernate-managed object, but a cloned object. As soon as those changes were applied, everything started to work.
java.lang.NullPointerException
 at org.springframework.beans.BeanWrapperImpl.createDefaultPropertyValue(BeanWrapperImpl.java:620)
 at org.springframework.beans.BeanWrapperImpl.setDefaultValue(BeanWrapperImpl.java:614)
 at org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:579)
 at org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:553)
 at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:914)
 at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
 at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:692)
 at org.springframework.validation.DataBinder.doBind(DataBinder.java:588)
 at org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:191)
 at org.springframework.web.portlet.bind.PortletRequestDataBinder.bind(PortletRequestDataBinder.java:113)
 at org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter$PortletHandlerMethodInvoker.doBind(AnnotationMethodHandlerAdapter.java:570)
 at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:813)
 at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:367)
 at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
 at org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:362)
 at org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter.doHandle(AnnotationMethodHandlerAdapter.java:349)
 at org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter.handleAction(AnnotationMethodHandlerAdapter.java:283)
 at org.springframework.web.portlet.DispatcherPortlet.doActionService(DispatcherPortlet.java:641)
 at org.springframework.web.portlet.FrameworkPortlet.processRequest(FrameworkPortlet.java:519)
 at org.springframework.web.portlet.FrameworkPortlet.processAction(FrameworkPortlet.java:460)
 at org.jasig.portal.portlet.container.FilterChainImpl.doFilter(FilterChainImpl.java:130)
 at org.jasig.portal.portlet.container.FilterChainImpl.processFilter(FilterChainImpl.java:92)
 at org.jasig.portal.portlet.container.FilterManagerImpl.processFilter(FilterManagerImpl.java:119)
 at org.apache.pluto.container.driver.PortletServlet.dispatch(PortletServlet.java:359)
 at org.apache.pluto.container.driver.PortletServlet.doPost(PortletServlet.java:267)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
 at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
 at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:551)
 at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:488)
 at org.apache.pluto.driver.container.DefaultPortletInvokerService.invoke(DefaultPortletInvokerService.java:233)
 at org.apache.pluto.driver.container.DefaultPortletInvokerService.action(DefaultPortletInvokerService.java:101)
 at sun.reflect.GeneratedMethodAccessor295.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
 at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
 at org.jasig.portal.portlet.dao.jpa.ThreadContextClassLoaderAspect.doThreadContextClassLoaderUpdate(ThreadContextClassLoaderAspect.java:56)
 at sun.reflect.GeneratedMethodAccessor105.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
 at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
 at $Proxy207.action(Unknown Source)
 at org.apache.pluto.container.impl.PortletContainerImpl.doAction(PortletContainerImpl.java:251)
 at org.jasig.portal.portlet.rendering.PortletRendererImpl.doAction(PortletRendererImpl.java:165)
 at org.jasig.portal.portlet.rendering.worker.PortletActionExecutionWorker.callInternal(PortletActionExecutionWorker.java:46)
 at org.jasig.portal.portlet.rendering.worker.PortletActionExecutionWorker.callInternal(PortletActionExecutionWorker.java:31)
 at org.jasig.portal.portlet.rendering.worker.PortletExecutionWorker$1.call(PortletExecutionWorker.java:145)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
 at java.util.concurrent.FutureTask.run(FutureTask.java:138)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 at java.lang.Thread.run(Thread.java:662)