Spring 3.2.9 Upgradehttps://github.com/Jasig/uPortal/pull/524
Spring 4.0.5 Upgrade
https://github.com/Jasig/uPortal/pull/525
Outstanding Issues
Issue with Spring 3.2.10+ and 4.0.6+
ERROR [uP-PortletExec-1-guest-RENDER_HEADER-[dynamic-respondr-skin]] o.s.w.p.HeaderHandlingDispatcherPortlet 2015-02-23 14:27:05,808 - Could not complete request
java.lang.IllegalArgumentException: Object of class [org.springframework.web.portlet.context.PortletRequestAttributes] must be an instance of class org.springframework.web.context.request.ServletRequestAttributes
at org.springframework.util.Assert.isInstanceOf(Assert.java:339) ~[spring-core-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.util.Assert.isInstanceOf(Assert.java:319) ~[spring-core-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.servlet.view.ContentNegotiatingViewResolver.resolveViewName(ContentNegotiatingViewResolver.java:281) ~[spring-webmvc-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.portlet.DispatcherPortlet.resolveViewName(DispatcherPortlet.java:1148) ~[spring-webmvc-portlet-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.portlet.DispatcherPortlet.render(DispatcherPortlet.java:1090) ~[spring-webmvc-portlet-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.portlet.DispatcherPortlet.doRenderService(DispatcherPortlet.java:789) ~[spring-webmvc-portlet-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.portlet.HeaderHandlingDispatcherPortlet.doRenderService(HeaderHandlingDispatcherPortlet.java:85) [HeaderHandlingDispatcherPortlet.class:4.0.9.RELEASE]
at org.springframework.web.portlet.FrameworkPortlet.processRequest(FrameworkPortlet.java:536) [spring-webmvc-portlet-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.portlet.FrameworkPortlet.doDispatch(FrameworkPortlet.java:483) [spring-webmvc-portlet-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.web.portlet.HeaderHandlingDispatcherPortlet.doHeaders(HeaderHandlingDispatcherPortlet.java:50) [HeaderHandlingDispatcherPortlet.class:4.0.9.RELEASE]
at javax.portlet.GenericPortlet.render(GenericPortlet.java:242) [portlet-api.jar:na]
at org.jasig.portal.portlet.container.FilterChainImpl.doFilter(FilterChainImpl.java:183) [FilterChainImpl.class:na]
at org.jasig.portal.portlet.container.FilterChainImpl.processFilter(FilterChainImpl.java:99) [FilterChainImpl.class:na]
at org.jasig.portal.portlet.container.FilterManagerImpl.processFilter(FilterManagerImpl.java:110) [FilterManagerImpl.class:na]
at org.apache.pluto.container.driver.PortletServlet.dispatch(PortletServlet.java:340) [pluto-container-driver-api.jar:2.1.0-M3]
at org.apache.pluto.container.driver.PortletServlet.doGet(PortletServlet.java:261) [pluto-container-driver-api.jar:2.1.0-M3]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api.jar:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [catalina.jar:7.0.56]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.56]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748) [catalina.jar:7.0.56]
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:604) [catalina.jar:7.0.56]
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:543) [catalina.jar:7.0.56]
at org.apache.pluto.driver.container.DefaultPortletInvokerService.invoke(DefaultPortletInvokerService.java:233) [pluto-portal-driver-2.1.0-M3.jar:2.1.0-M3]
at org.apache.pluto.driver.container.DefaultPortletInvokerService.render(DefaultPortletInvokerService.java:117) [pluto-portal-driver-2.1.0-M3.jar:2.1.0-M3]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_31]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_31]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_31]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_31]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:85) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.jasig.portal.portlet.dao.jpa.ThreadContextClassLoaderAspect.doThreadContextClassLoaderUpdate(ThreadContextClassLoaderAspect.java:69) [ThreadContextClassLoaderAspect.class:na]
at sun.reflect.GeneratedMethodAccessor117.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_31]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_31]
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) [spring-aop-4.0.9.RELEASE.jar:4.0.9.RELEASE]
at com.sun.proxy.$Proxy205.render(Unknown Source) [na:na]
at org.apache.pluto.container.impl.PortletContainerImpl.doRender(PortletContainerImpl.java:157) [pluto-container-2.1.0-M3.jar:2.1.0-M3]
at org.jasig.portal.portlet.rendering.PortletRendererImpl.doRender(PortletRendererImpl.java:405) [PortletRendererImpl.class:na]
at org.jasig.portal.portlet.rendering.PortletRendererImpl.doRenderHeader(PortletRendererImpl.java:218) [PortletRendererImpl.class:na]
at org.jasig.portal.portlet.rendering.worker.PortletRenderHeaderExecutionWorker.callInternal(PortletRenderHeaderExecutionWorker.java:90) [PortletRenderHeaderExecutionWorker.class:na]
at org.jasig.portal.portlet.rendering.worker.PortletRenderHeaderExecutionWorker.callInternal(PortletRenderHeaderExecutionWorker.java:39) [PortletRenderHeaderExecutionWorker.class:na]
at org.jasig.portal.portlet.rendering.worker.PortletExecutionWorker$1.call(PortletExecutionWorker.java:135) [PortletExecutionWorker$1.class:na]
at org.jasig.portal.portlet.rendering.worker.PortletExecutionWorker$ExecutionLifecycleCallable.call(PortletExecutionWorker.java:175) [PortletExecutionWorker$ExecutionLifecycleCallable.class:na]
at org.jasig.portal.portlet.rendering.worker.PortletExecutionCallable.call(PortletExecutionCallable.java:118) [PortletExecutionCallable.class:na]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_31]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_31]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_31]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_31]
Â
https://jira.spring.io/browse/SPR-11295
https://github.com/spring-projects/spring-framework/commit/7d94b5e8536fc9084b5749b02af708296417cce5
Issue revolves around the above Spring change where ServletRequestAttributes are now being coerced to PortletRequestAttributes. uPortal leverages some Spring classes that only work with ServletRequestAttributes objects.
Deprecated / Removed JPA Classes
These classes have been deprecated and are no longer included in Spring 4.0.x.Â
https://issues.jasig.org/browse/UP-4553
- org.springframework.orm.jpa.JpaAccessor.java
- This class is only used as a parent class for JpaPortletExecutionInterceptor
- It is used to wrap the execution/thread of a portlet with an EntityManager
- org.springframework.orm.jpa.JpaInterceptor.java
- This class is instantiated as a bean in persistenceContext.xml, but is never referenced by main Java code
- This class is only found in comments in the main Java code
- This class is used in BaseJpaDaoTest  in test code and is used extensively
- This class is defined as a bean in sharedJpaTestContext
- Attempt to replace this in test with @Transactional was successful - (Maybe REQUIRED_NEW would help?)
Ideally, we need to refactor the uPortal code to no longer use these classes. Â However, in the short term, these two classes have been copied into the uPortal codebase at: Â uportal-war/src/main/java/org/springframework/orm/jpa
The above classes are used to addÂ
Resolved Issues
Unit Tests Failing with ObjectOptimisticLockingFailure
org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest#testPersistentWithPrefsNotInDb()
org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest#testPersistentNoPrefsNotInDb()
[exec] Tests run: 8, Failures: 0, Errors: 2, Skipped: 0, Time elapsed: 1.3 sec <<< FAILURE!
[exec] testPersistentNoPrefsNotInDb(org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest) Time elapsed: 0.218 sec <<< ERROR!
[exec] org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [org.jasig.portal.portlet.dao.jpa.PortletEntityImpl] with identifier [4]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jasig.portal.portlet.dao.jpa.PortletEntityImpl#4]
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2479)
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3306)
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3506)
[exec] at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:100)
[exec] at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
[exec] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
[exec] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:280)
[exec] at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
[exec] at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
[exec] at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
[exec] at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
[exec] at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
[exec] at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
[exec] at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
[exec] at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
[exec] at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
[exec] at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
[exec] at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
[exec] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
[exec] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
[exec] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[exec] at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
[exec] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[exec] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
[exec] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[exec] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
[exec] at com.sun.proxy.$Proxy104.deletePortletEntity(Unknown Source)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImpl.deletePortletEntity(PortletEntityRegistryImpl.java:519)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImpl.storePortletEntity(PortletEntityRegistryImpl.java:342)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest$10.call(PortletEntityRegistryImplTest.java:377)
[exec] at org.jasig.portal.test.BaseJpaDaoTest$MethodInvocationCallable.proceed(BaseJpaDaoTest.java:213)
[exec] at org.springframework.orm.jpa.JpaInterceptor.invoke(JpaInterceptor.java:101)
[exec] at org.jasig.portal.test.BaseJpaDaoTest.execute(BaseJpaDaoTest.java:125)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest.testPersistentNoPrefsNotInDb(PortletEntityRegistryImplTest.java:329)
[exec]
[exec] testPersistentWithPrefsNotInDb(org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest) Time elapsed: 0.115 sec <<< ERROR!
[exec] org.springframework.orm.ObjectOptimisticLockingFailureException: Object of class [org.jasig.portal.portlet.dao.jpa.PortletPreferencesImpl] with identifier [15]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jasig.portal.portlet.dao.jpa.PortletPreferencesImpl#15]
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2479)
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3189)
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3087)
[exec] at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3416)
[exec] at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
[exec] at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
[exec] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
[exec] at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:276)
[exec] at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
[exec] at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
[exec] at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
[exec] at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
[exec] at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
[exec] at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
[exec] at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
[exec] at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
[exec] at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
[exec] at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
[exec] at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
[exec] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
[exec] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
[exec] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[exec] at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
[exec] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[exec] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
[exec] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
[exec] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
[exec] at com.sun.proxy.$Proxy104.updatePortletEntity(Unknown Source)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImpl.storePortletEntity(PortletEntityRegistryImpl.java:319)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest$6.call(PortletEntityRegistryImplTest.java:259)
[exec] at org.jasig.portal.test.BaseJpaDaoTest$MethodInvocationCallable.proceed(BaseJpaDaoTest.java:213)
[exec] at org.springframework.orm.jpa.JpaInterceptor.invoke(JpaInterceptor.java:101)
[exec] at org.jasig.portal.test.BaseJpaDaoTest.execute(BaseJpaDaoTest.java:125)
[exec] at org.jasig.portal.portlet.registry.PortletEntityRegistryImplTest.testPersistentWithPrefsNotInDb(PortletEntityRegistryImplTest.java:209)
[exec]
...
[exec]
[exec] Results :
[exec]
[exec] Tests in error:
[exec] PortletEntityRegistryImplTest.testPersistentNoPrefsNotInDb:329->BaseJpaDaoTest.execute:125 » ObjectOptimisticLockingFailure
[exec] PortletEntityRegistryImplTest.testPersistentWithPrefsNotInDb:209->BaseJpaDaoTest.execute:125 » ObjectOptimisticLockingFailure
[exec]
[exec] Tests run: 539, Failures: 0, Errors: 2, Skipped: 5
[exec]
The issue here was that the unit tests specifically catch org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException, but now need to catch org.springframework.dao.OptimisticLockingFailureException.  The former is what the org.hibernate.StaleObjectStateException used to be mapped to in Spring 3.x, and the latter is what the exception gets mapped to in Spring 4.x. Â
Resources
Â