Kuali Rice Development
  1. Kuali Rice Development
  2. KULRICE-3609

Cancelling the creation of a new delegate rule results in a NullPointerException

    Details

    • Similar issues:
      KULRICE-3344Parent Responsibility and NullPointerException problems on the "Delegate Routing Rule Creation" screen.
      KULRICE-2666Update links in RuleQuickLinks so that they point to the proper urls for the new rule and rule delegation maintenance documents and lookups
      KULRICE-3109New portal has incorrect link for Routing Rules and Delegation is shown as 'Deligation'
      KULRICE-2644Implement a "front page" for routing rule creation that allows the user to select the document type and rule template prior to creating the rule
      KULRICE-3677Rule lookup does not export delegate rules
      KULRICE-13929Looking up delegation rules by delegateRuleId doesn't work
      KULRICE-5582Rice Dev: Create new Routing Rule and Routing Rule Delegation bombs
      KULRICE-4344 Rule Delegation - Create new delegation - Unable to determine Future Action Requests
      KULRICE-3575when a new rule delegation is created, the document requeuer is never invoked
      KULRICE-3356"Travel Account" field on Travel Request creation page is not working properly
    • Rice Team:
      QA

      Description

      On the delegate rule maintenance document, if a user clicks the "cancel" button while creating a new rule and then clicks "yes" on the question prompt, the user is presented with the incident report screen and the following stack trace:

      java.lang.NullPointerException
      at org.kuali.rice.kew.document.RoutingRuleDelegationMaintainable.getDocumentTitle(RoutingRuleDelegationMaintainable.java:134)
      at org.kuali.rice.kns.document.MaintenanceDocumentBase.getDocumentTitle(MaintenanceDocumentBase.java:166)
      at org.kuali.rice.kns.service.impl.DocumentServiceImpl.populateDocumentTitle(DocumentServiceImpl.java:725)
      at org.kuali.rice.kns.service.impl.DocumentServiceImpl.prepareWorkflowDocument(DocumentServiceImpl.java:711)
      at org.kuali.rice.kns.service.impl.DocumentServiceImpl.cancelDocument(DocumentServiceImpl.java:282)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      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:304)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:172)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:139)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:203)
      at $Proxy48.cancelDocument(Unknown Source)
      at org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase.cancel(KualiDocumentActionBase.java:855)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:270)
      at org.kuali.rice.kns.web.struts.action.KualiAction.dispatchMethod(KualiAction.java:171)
      at org.kuali.rice.kns.web.struts.action.KualiAction.execute(KualiAction.java:122)
      at org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase.execute(KualiDocumentActionBase.java:154)
      at org.kuali.rice.kns.web.struts.action.KualiMaintenanceDocumentAction.execute(KualiMaintenanceDocumentAction.java:98)
      at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor$1.doInTransaction(KualiRequestProcessor.java:497)
      at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)
      at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor.processActionPerform(KualiRequestProcessor.java:493)
      at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
      at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor.process(KualiRequestProcessor.java:99)
      at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
      at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
      at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:491)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1074)
      at org.kuali.rice.kew.web.UserLoginFilter.doFilter(UserLoginFilter.java:92)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
      at org.kuali.rice.kew.web.BootstrapFilterChain.doFilter(BootstrapFilter.java:305)
      at org.kuali.rice.kew.web.DummyLoginFilter.doFilter(DummyLoginFilter.java:88)
      at org.kuali.rice.kew.web.BootstrapFilterChain.doFilter(BootstrapFilter.java:298)
      at org.kuali.rice.kew.web.BootstrapFilter.doFilter(BootstrapFilter.java:166)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
      at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
      at org.kuali.rice.kns.web.filter.HideWebInfFilter.doFilter(HideWebInfFilter.java:66)
      at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
      at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:365)
      at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:185)
      at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
      at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:689)
      at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:391)
      at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
      at org.mortbay.jetty.Server.handle(Server.java:285)
      at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:457)
      at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:751)
      at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:500)
      at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:209)
      at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:357)
      at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:217)
      at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:475)

        Activity

        Hide
        Eric Westfall added a comment -

        I found this one lurking around without a fix version, can you look into this one when you get a chance? Thanks.

        Show
        Eric Westfall added a comment - I found this one lurking around without a fix version, can you look into this one when you get a chance? Thanks.
        Hide
        Chad Hagstrom added a comment -

        I've identified the NullPointerException cause. The RoutingRuleDelegationMaintainable relies on the RuleDelegation's associated RuleBaseValues instance when generating the document's title in the maintainable's getDocumentTitle() method, and that method assumes the RuleBaseValues object is not null. However, I've noticed that the BusinessObject-refreshing code in DocumentServiceImpl.cancelDocument sets the RuleBaseValues instance to null when the RuleDelegation's refresh() method is called, resulting in a NullPointerException when obtaining the document title. I had added that BusinessObject-refreshing code to the cancelDocument() method back in Rice 1.0 for KULRICE-3141, which prevented StackOverflowErrors resulting from the cancellation of certain edited but unsaved document types. Should RuleDelegation override the refresh() method to have it also refresh its RuleBaseValues instance? Or should DocumentSearchServiceImpl.cancelDocument be modified so that it performs a more extensive refresh of the business object(s) prior to cancellation? Or would it be better to just have the RuleDelegation document title generation be independent of the associated RuleBaseValues?

        Show
        Chad Hagstrom added a comment - I've identified the NullPointerException cause. The RoutingRuleDelegationMaintainable relies on the RuleDelegation's associated RuleBaseValues instance when generating the document's title in the maintainable's getDocumentTitle() method, and that method assumes the RuleBaseValues object is not null. However, I've noticed that the BusinessObject-refreshing code in DocumentServiceImpl.cancelDocument sets the RuleBaseValues instance to null when the RuleDelegation's refresh() method is called, resulting in a NullPointerException when obtaining the document title. I had added that BusinessObject-refreshing code to the cancelDocument() method back in Rice 1.0 for KULRICE-3141 , which prevented StackOverflowErrors resulting from the cancellation of certain edited but unsaved document types. Should RuleDelegation override the refresh() method to have it also refresh its RuleBaseValues instance? Or should DocumentSearchServiceImpl.cancelDocument be modified so that it performs a more extensive refresh of the business object(s) prior to cancellation? Or would it be better to just have the RuleDelegation document title generation be independent of the associated RuleBaseValues?
        Hide
        Chad Hagstrom added a comment -

        Discussed this with Eric, where we agreed that we should try to simply leave the title empty if the RuleBaseValues instance is null. However, I've just tried this solution, and I'm now getting the following exception under certain rule delegation cancellation circumstances:

        java.lang.RuntimeException: Unable to resolve collection property: class org.kuali.rice.kew.rule.RuleDelegation:delegationRuleBaseValues.personResponsibilities
        at org.kuali.rice.kns.service.impl.BusinessObjectAuthorizationServiceImpl.addMaintainableItemRestrictions(BusinessObjectAuthorizationServiceImpl.java:518)
        at org.kuali.rice.kns.service.impl.BusinessObjectAuthorizationServiceImpl.getMaintenanceDocumentRestrictions(BusinessObjectAuthorizationServiceImpl.java:169)
        at org.kuali.rice.kns.web.struts.action.KualiMaintenanceDocumentAction.populateAuthorizationFields(KualiMaintenanceDocumentAction.java:968)
        at org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase.execute(KualiDocumentActionBase.java:199)
        at org.kuali.rice.kns.web.struts.action.KualiMaintenanceDocumentAction.execute(KualiMaintenanceDocumentAction.java:98)
        at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor$1.doInTransaction(KualiRequestProcessor.java:498)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127)
        at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor.processActionPerform(KualiRequestProcessor.java:494)
        at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
        at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor.process(KualiRequestProcessor.java:99)
        at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
        at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:491)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1074)
        at org.kuali.rice.kew.web.UserLoginFilter.doFilter(UserLoginFilter.java:92)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
        at org.kuali.rice.kew.web.BootstrapFilterChain.doFilter(BootstrapFilter.java:305)
        at org.kuali.rice.kew.web.DummyLoginFilter.doFilter(DummyLoginFilter.java:88)
        at org.kuali.rice.kew.web.BootstrapFilterChain.doFilter(BootstrapFilter.java:298)
        at org.kuali.rice.kew.web.BootstrapFilter.doFilter(BootstrapFilter.java:166)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
        at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
        at org.kuali.rice.kns.web.filter.HideWebInfFilter.doFilter(HideWebInfFilter.java:66)
        at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:365)
        at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:185)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:689)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:391)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
        at org.mortbay.jetty.Server.handle(Server.java:285)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:457)
        at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:751)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:500)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:209)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:357)
        at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:217)
        at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:475)

        Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Collection
        at org.kuali.rice.kns.service.impl.BusinessObjectAuthorizationServiceImpl.addMaintainableItemRestrictions(BusinessObjectAuthorizationServiceImpl.java:483)
        ... 40 more

        I'm still investigating to determine the best workaround for this problem.

        Show
        Chad Hagstrom added a comment - Discussed this with Eric, where we agreed that we should try to simply leave the title empty if the RuleBaseValues instance is null. However, I've just tried this solution, and I'm now getting the following exception under certain rule delegation cancellation circumstances: java.lang.RuntimeException: Unable to resolve collection property: class org.kuali.rice.kew.rule.RuleDelegation:delegationRuleBaseValues.personResponsibilities at org.kuali.rice.kns.service.impl.BusinessObjectAuthorizationServiceImpl.addMaintainableItemRestrictions(BusinessObjectAuthorizationServiceImpl.java:518) at org.kuali.rice.kns.service.impl.BusinessObjectAuthorizationServiceImpl.getMaintenanceDocumentRestrictions(BusinessObjectAuthorizationServiceImpl.java:169) at org.kuali.rice.kns.web.struts.action.KualiMaintenanceDocumentAction.populateAuthorizationFields(KualiMaintenanceDocumentAction.java:968) at org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase.execute(KualiDocumentActionBase.java:199) at org.kuali.rice.kns.web.struts.action.KualiMaintenanceDocumentAction.execute(KualiMaintenanceDocumentAction.java:98) at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor$1.doInTransaction(KualiRequestProcessor.java:498) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:127) at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor.processActionPerform(KualiRequestProcessor.java:494) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236) at org.kuali.rice.kns.web.struts.action.KualiRequestProcessor.process(KualiRequestProcessor.java:99) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196) at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:414) at javax.servlet.http.HttpServlet.service(HttpServlet.java:689) at javax.servlet.http.HttpServlet.service(HttpServlet.java:802) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:491) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1074) at org.kuali.rice.kew.web.UserLoginFilter.doFilter(UserLoginFilter.java:92) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065) at org.kuali.rice.kew.web.BootstrapFilterChain.doFilter(BootstrapFilter.java:305) at org.kuali.rice.kew.web.DummyLoginFilter.doFilter(DummyLoginFilter.java:88) at org.kuali.rice.kew.web.BootstrapFilterChain.doFilter(BootstrapFilter.java:298) at org.kuali.rice.kew.web.BootstrapFilter.doFilter(BootstrapFilter.java:166) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065) at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065) at org.kuali.rice.kns.web.filter.HideWebInfFilter.doFilter(HideWebInfFilter.java:66) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1065) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:365) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:185) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:689) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:391) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139) at org.mortbay.jetty.Server.handle(Server.java:285) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:457) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:751) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:500) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:209) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:357) at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:217) at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:475) Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Collection at org.kuali.rice.kns.service.impl.BusinessObjectAuthorizationServiceImpl.addMaintainableItemRestrictions(BusinessObjectAuthorizationServiceImpl.java:483) ... 40 more I'm still investigating to determine the best workaround for this problem.
        Hide
        Chad Hagstrom added a comment -

        It seems that even though ignoring the nulled RuleBaseValues parameter in the title generation is sufficient to prevent the originally-reported error, it does not stop problems from occurring when the authorization field population is taking place since it still expects some of the Collection properties in the RuleBaseValues object to still be reachable. In light of this, I have been experimenting with an alternate solution, where I've overriden the RuleDelegation's refresh() method so that it preserves the old RuleBaseValues instance as needed. This new method will store the old RuleBaseValues and then call the superclass's refresh() method, and then it will call refreshReferenceObject() for the delegationRuleBaseValues property if it becomes null due to the refresh, and finally it will use the old RuleBaseValues instance as the new delegationRuleBaseValues property value if the refreshReferenceObject() call fails to make it non-null (which I believe is usually the case when canceling unsaved rule delegations). Such a solution does appear to solve the rule delegation cancellation problem (though I am not entirely certain if the refreshReferenceObject() call actually does any good), so unless this fix introduces some new problems that I am not currently aware of, I think this workaround is safe to commit.

        Show
        Chad Hagstrom added a comment - It seems that even though ignoring the nulled RuleBaseValues parameter in the title generation is sufficient to prevent the originally-reported error, it does not stop problems from occurring when the authorization field population is taking place since it still expects some of the Collection properties in the RuleBaseValues object to still be reachable. In light of this, I have been experimenting with an alternate solution, where I've overriden the RuleDelegation's refresh() method so that it preserves the old RuleBaseValues instance as needed. This new method will store the old RuleBaseValues and then call the superclass's refresh() method, and then it will call refreshReferenceObject() for the delegationRuleBaseValues property if it becomes null due to the refresh, and finally it will use the old RuleBaseValues instance as the new delegationRuleBaseValues property value if the refreshReferenceObject() call fails to make it non-null (which I believe is usually the case when canceling unsaved rule delegations). Such a solution does appear to solve the rule delegation cancellation problem (though I am not entirely certain if the refreshReferenceObject() call actually does any good), so unless this fix introduces some new problems that I am not currently aware of, I think this workaround is safe to commit.

          People

          • Assignee:
            Chad Hagstrom
            Reporter:
            Chad Hagstrom
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Structure Helper Panel