Uploaded image for project: 'Kuali Rice Development'
  1. Kuali Rice Development
  2. KULRICE-10916

Sorting is broken for tables using server side paging

    Details

    • Type: Bug Fix
    • Status: Closed
    • Priority: Critical
    • Resolution: Fixed
    • Affects Version/s: 2.4
    • Fix Version/s: 2.4
    • Component/s: Development
    • Security Level: Public (Public: Anyone can view)
    • Labels:
      None
    • Rice Module:
      KRAD
    • KRAD Feature Area:
      UIF Component
    • Sprint:
      2.4.0-m2 KRAD Sprint 4
    • KAI Review Status:
      Not Required
    • KTI Review Status:
      Not Required
    • Code Review Status:
      Not Required
    • Include in Release Notes?:
      Yes

      Description

      Sorting is broken when server paging is enabled. To reproduce in the KRAD sample app:

      • Navigate to Library -> Collections -> Server Paging
      • Click on the header for any sortable column

      You'll get a JS alert similar to "DataTables warning (table id = 'u100101'): DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error."

      In the server log you'll get a stack trace:

      java.lang.IllegalStateException: View context is not active
      	at org.kuali.rice.krad.uif.component.ComponentBase.copy(ComponentBase.java:2192)
      	at org.kuali.rice.krad.uif.util.MultiColumnComparator.buildPrototypeRow(MultiColumnComparator.java:406)
      	at org.kuali.rice.krad.uif.util.MultiColumnComparator.<init>(MultiColumnComparator.java:103)
      	at org.kuali.rice.krad.web.controller.helper.DataTablesPagingHelper.applyTableJsonSort(DataTablesPagingHelper.java:223)
      	at org.kuali.rice.krad.web.controller.helper.DataTablesPagingHelper.processPagingRequest(DataTablesPagingHelper.java:80)
      	at org.kuali.rice.krad.web.controller.UifControllerBase.tableJsonRetrieval(UifControllerBase.java:1243)
      	at org.kuali.rice.krad.web.controller.UifControllerBase$$FastClassByCGLIB$$7929303a.invoke(<generated>)
      	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
      	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
      	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
      	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
      	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
      	at org.kuali.rice.krad.demo.uif.controller.ServerPagingTestController$$EnhancerByCGLIB$$28bb2b06.tableJsonRetrieval(<generated>)
      	at sun.reflect.GeneratedMethodAccessor771.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
      	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
      	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
      	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
      	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
      	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
      	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
      	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
      	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
      	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
      	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
      	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.kuali.rice.krad.web.filter.CharsetFilter.doFilter(CharsetFilter.java:58)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.kuali.rice.krad.web.filter.UserLoginFilter.doFilter(UserLoginFilter.java:89)
      	at org.kuali.rice.krad.web.filter.UserLoginFilter.doFilter(UserLoginFilter.java:77)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.kuali.rice.krad.web.filter.BootstrapFilterChain.doFilter(BootstrapFilter.java:327)
      	at org.kuali.rice.krad.web.filter.DummyLoginFilter.doFilter(DummyLoginFilter.java:82)
      	at org.kuali.rice.krad.web.filter.DummyLoginFilter.doFilter(DummyLoginFilter.java:62)
      	at org.kuali.rice.krad.web.filter.BootstrapFilterChain.doFilter(BootstrapFilter.java:320)
      	at org.kuali.rice.krad.web.filter.BootstrapFilter.doFilter(BootstrapFilter.java:199)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.kuali.rice.krad.web.filter.UifSessionTimeoutFilter.doFilter(UifSessionTimeoutFilter.java:106)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.kuali.rice.core.web.Log4JContextClearingFilter.doFilterInternal(Log4JContextClearingFilter.java:37)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.kuali.rice.krad.web.filter.HideWebInfFilter.doFilter(HideWebInfFilter.java:68)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:213)
      	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
      	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
      	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
      	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
      	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
      	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
      	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
      	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563)
      	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
      	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:399)
      	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:317)
      	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:204)
      	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:182)
      	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:311)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
      	at java.lang.Thread.run(Thread.java:662)
      

        Attachments

          Activity

          Hide
          gilesp Peter Giles (Inactive) added a comment -

          Hi Mark, the sort for server paging broke somewhere in this cluster of commits last friday: r41980, r41981, r41982. The MultiColumnComparator is (on line 406) copying components for use as prototypes, and this is happening when the view state is not active. I'm not sure why it's forbidden to copy components at that time. Can you please take a look? Thanks

          Show
          gilesp Peter Giles (Inactive) added a comment - Hi Mark, the sort for server paging broke somewhere in this cluster of commits last friday: r41980, r41981, r41982. The MultiColumnComparator is (on line 406) copying components for use as prototypes, and this is happening when the view state is not active. I'm not sure why it's forbidden to copy components at that time. Can you please take a look? Thanks
          Hide
          mwfyffe Mark Fyffe (Inactive) added a comment -

          Hi Peter - I'll look into this over the weekend. It should be relatively straightforward to address. I'll follow up with details tomorrow or Sunday.

          Show
          mwfyffe Mark Fyffe (Inactive) added a comment - Hi Peter - I'll look into this over the weekend. It should be relatively straightforward to address. I'll follow up with details tomorrow or Sunday.
          Hide
          mwfyffe Mark Fyffe (Inactive) added a comment -

          Committed a fix.

          Since MultiColumnComparator creates copies of selected components from the posted view, it needs to be encapsulated in a lifecycle or initialization call to enable modification. Since the sorting isn't really part of the lifecycle, I wrapped the MultiColumnComparator constructor in an encapsulateInitialization call() and am no longer seeing this issue.

          @@ -224,7 +225,13 @@
                           sortIndices[i] = i;
                       }
          
          -            Arrays.sort(sortIndices, new MultiColumnComparator(modelCollection, collectionGroup, newColumnSorts, view));
          +            MultiColumnComparator comparator = ViewLifecycle
          +                    .encapsulateInitialization(new Callable<MultiColumnComparator>(){
          +                @Override
          +                public MultiColumnComparator call() throws Exception {
          +                    return new MultiColumnComparator(modelCollection, collectionGroup, newColumnSorts, view);
          +                }});
          +            Arrays.sort(sortIndices, comparator);
          
                       // apply the sort to the modelCollection
                       Object[] sorted = new Object[sortIndices.length];
          
          Show
          mwfyffe Mark Fyffe (Inactive) added a comment - Committed a fix. Since MultiColumnComparator creates copies of selected components from the posted view, it needs to be encapsulated in a lifecycle or initialization call to enable modification. Since the sorting isn't really part of the lifecycle, I wrapped the MultiColumnComparator constructor in an encapsulateInitialization call() and am no longer seeing this issue. @@ -224,7 +225,13 @@ sortIndices[i] = i; } - Arrays.sort(sortIndices, new MultiColumnComparator(modelCollection, collectionGroup, newColumnSorts, view)); + MultiColumnComparator comparator = ViewLifecycle + .encapsulateInitialization(new Callable<MultiColumnComparator>(){ + @Override + public MultiColumnComparator call() throws Exception { + return new MultiColumnComparator(modelCollection, collectionGroup, newColumnSorts, view); + }}); + Arrays.sort(sortIndices, comparator); // apply the sort to the modelCollection Object[] sorted = new Object[sortIndices.length];
          Hide
          acampbell Adam Campbell (Inactive) added a comment -

          validated on env14
          closing as fixed

          Show
          acampbell Adam Campbell (Inactive) added a comment - validated on env14 closing as fixed

            People

            • Assignee:
              mwfyffe Mark Fyffe (Inactive)
              Reporter:
              gilesp Peter Giles (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 1 day, 4 hours
                1d 4h
                Remaining:
                Time Spent - 4 hours Remaining Estimate - 1 day
                1d
                Logged:
                Time Spent - 4 hours Remaining Estimate - 1 day
                4h