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

Mass action ActionItem deletion occurs before action invocation

    Details

    • Type: Bug Fix Bug Fix
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 0.9.2.1
    • Fix Version/s: 1.0
    • Component/s: Development
    • Labels:
      None
    • Similar issues:
      KULRICE-7575Fix optimistic locking issues on action items for mass actions
      KULRICE-6593take action button is missing for taking mass actions
      KULRICE-3368RuntimeException occurs when attempting to delete an action list outbox entry.
      KULRICE-8580Jump action occurring on component refresh
      KULRICE-12029Issue with delete functionality on Table Layout library demo
      KULRICE-14082Reduce invocations for edit mode and action flag checks
      KULRICE-2711testIsUserInRouteLogWithSplits when partially populated ActionItem is inserted into DB
      KULRICE-7588Implement maintenance Delete action
      KULRICE-4280RELOAD_ACTION_LIST user options not getting deleted on first load of Action List
      KULRICE-12106Dialog needed for impacting actions such as delete line
    • Rice Module:
      KEW

      Description

      It appears that upon taking a mass action via the Action List, deletion of ActionItems precedes actual invocation of the Action. This can cause a problem with outbox handling, as outbox items are only created for items for which the user has taken action. This condition is necessarily false if the action has not yet been invoked at the time of action item deletion and therefore items taking action on via mass actions will not be saved into the outbox.

      public void takeMassActions(WorkflowUser user, List actionInvocations) {
      for (Iterator iterator = actionInvocations.iterator(); iterator.hasNext() {
      ActionInvocation invocation = (ActionInvocation) iterator.next();
      ActionItem actionItem = KEWServiceLocator.getActionListService().findByActionItemId(invocation.getActionItemId());
      if (actionItem == null)

      { LOG.warn("Could not locate action item for the given action item id [" + invocation.getActionItemId() + "], not taking mass action on it."); continue; }

      KEWServiceLocator.getActionListService().deleteActionItem(actionItem); // <-- Action not yet invoked...actionTaken == null
      ActionInvocationService actionInvocService = MessageServiceNames.getActionInvocationProcessorService(actionItem.getRouteHeader());
      actionInvocService.invokeAction(user, actionItem.getRouteHeaderId(), invocation);
      // ActionInvocationProcessor.queueActionInvocation(user, actionItem.getRouteHeaderId(), invocation);
      }
      }

      Possible solution: defer action item deletion until after/as part of action invocation

        Activity

        Hide
        Eric Westfall added a comment -

        In order for action items to exist you must route a document so that it enters users' action lists. You can see some of the other tests in OutboxTest which have done this. Mainly, this is done using the "WorkflowDocument" API class. Thanks.

        Show
        Eric Westfall added a comment - In order for action items to exist you must route a document so that it enters users' action lists. You can see some of the other tests in OutboxTest which have done this. Mainly, this is done using the "WorkflowDocument" API class. Thanks.
        Hide
        Srikanth Mummadi (Inactive) added a comment -

        Hi,

        I have modified the method testTakeMassActions in OutboxTest

        public void testTakeMassActions() throws Exception {
        final String rkirkendPrincipalId = getPrincipalIdForName("rkirkend");
        List<String> recipients = new ArrayList<String>();
        recipients.add(rkirkendPrincipalId);
        TestRuleAttribute.setRecipientPrincipalIds("TestRole", "qualRole", recipients);
        turnOnOutboxForUser(rkirkendPrincipalId);

        WorkflowDocument document = new WorkflowDocument(getPrincipalIdForName("quickstart"), "TestDocumentType");
        document.routeDocument("");

        document = new WorkflowDocument(rkirkendPrincipalId, document.getRouteHeaderId());
        assertTrue("approve should be requested", document.isApprovalRequested());

        document = new WorkflowDocument(getPrincipalIdForName("user1"), "OutboxTestDocumentType");
        document.routeDocument("");

        document = new WorkflowDocument(rkirkendPrincipalId, document.getRouteHeaderId());
        assertTrue("approve should be requested", document.isApprovalRequested());

        List actionList = new ArrayList(KEWServiceLocator.getActionListService().getActionList(rkirkendPrincipalId, new ActionListFilter()));
        List invocations = new ArrayList();
        ActionToTake actionToTake = new ActionToTake();
        ActionItem actionItem = new ActionItem();

        for (Iterator iterator = actionList.iterator(); iterator.hasNext()

        { ActionItem actinItem = (ActionItem) iterator.next(); actionToTake.setActionItemId(actinItem.getActionItemId()); actionToTake.setActionTakenCd(actinItem.getActionRequestCd()); invocations.add(new ActionInvocation(actinItem.getActionItemId(), actionToTake.getActionTakenCd())); }

        KEWServiceLocator.getWorkflowDocumentService().takeMassActions(rkirkendPrincipalId, invocations);
        assertEquals("Wrong number of outbox items found for rkirkendPrincipalId", 2, KEWServiceLocator.getActionListService().getOutbox(rkirkendPrincipalId, new ActionListFilter()).size());

        }

        In WorkflowDocumentServiceImpl.takeMassActions actionItem was getting deleted before it is saved into the outbox table.
        So,I have commented the method call in WorkflowDocumentServiceImpl.takeMassActions as follows

        public void takeMassActions(String principalId, List actionInvocations) {
        KimPrincipal principal = loadPrincipal(principalId);
        for (Iterator iterator = actionInvocations.iterator(); iterator.hasNext() {
        ActionInvocation invocation = (ActionInvocation) iterator.next();
        ActionItem actionItem = KEWServiceLocator.getActionListService().findByActionItemId(invocation.getActionItemId());
        if (actionItem == null)

        { LOG.warn("Could not locate action item for the given action item id [" + invocation.getActionItemId() + "], not taking mass action on it."); continue; }

        // KEWServiceLocator.getActionListService().deleteActionItem(actionItem);
        ActionInvocationService actionInvocService = MessageServiceNames.getActionInvocationProcessorService(actionItem.getRouteHeader());
        actionInvocService.invokeAction(principalId, actionItem.getRouteHeaderId(), invocation);
        // ActionInvocationProcessor.queueActionInvocation(user, actionItem.getRouteHeaderId(), invocation);
        }
        }

        actionInvocService.invokeAction method internally calls ActionRequestServiceImpl.deactivateRequest which calls deleteActionItems(actionRequest).

        The method call to deleteActionItems(actionRequest) has been commented to resolve the following exception.

        org.springmodules.orm.ojb.OjbOperationException: OJB operation failed; nested exception is org.apache.ojb.broker.OptimisticLockException: Object has been modified or deleted by someone else
        Caused by: org.apache.ojb.broker.OptimisticLockException: Object has been modified or deleted by someone else
        at org.apache.ojb.broker.accesslayer.JdbcAccessImpl.executeDelete(JdbcAccessImpl.java:119)
        at org.apache.ojb.broker.core.PersistenceBrokerImpl.doDelete(PersistenceBrokerImpl.java:583)
        at org.apache.ojb.broker.core.PersistenceBrokerImpl.delete(PersistenceBrokerImpl.java:512)
        at org.apache.ojb.broker.core.PersistenceBrokerImpl.delete(PersistenceBrokerImpl.java:525)
        at org.apache.ojb.broker.core.DelegatingPersistenceBroker.delete(DelegatingPersistenceBroker.java:215)
        at org.apache.ojb.broker.core.DelegatingPersistenceBroker.delete(DelegatingPersistenceBroker.java:215)
        at org.springmodules.orm.ojb.PersistenceBrokerTemplate$10.doInPersistenceBroker(PersistenceBrokerTemplate.java:255)
        at org.springmodules.orm.ojb.PersistenceBrokerTemplate.execute(PersistenceBrokerTemplate.java:141)
        at org.springmodules.orm.ojb.PersistenceBrokerTemplate.delete(PersistenceBrokerTemplate.java:253)
        at org.kuali.rice.kew.actionitem.dao.impl.ActionItemDAOOjbImpl.deleteActionItem(ActionItemDAOOjbImpl.java:59)
        at org.kuali.rice.kew.actionlist.service.impl.ActionListServiceImpl.deleteActionItem(ActionListServiceImpl.java:102)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        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.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:203)
        at $Proxy204.deleteActionItem(Unknown Source)
        at org.kuali.rice.kew.routeheader.service.impl.WorkflowDocumentServiceImpl.takeMassActions(WorkflowDocumentServiceImpl.java:412)

        I have commited the following changed files to the repository.

        org.kuali.rice.kew.actionlist.OutboxTest and
        org.kuali.rice.kew.routeheader.service.impl.WorkflowDocumentServiceImpl.

        Show
        Srikanth Mummadi (Inactive) added a comment - Hi, I have modified the method testTakeMassActions in OutboxTest public void testTakeMassActions() throws Exception { final String rkirkendPrincipalId = getPrincipalIdForName("rkirkend"); List<String> recipients = new ArrayList<String>(); recipients.add(rkirkendPrincipalId); TestRuleAttribute.setRecipientPrincipalIds("TestRole", "qualRole", recipients); turnOnOutboxForUser(rkirkendPrincipalId); WorkflowDocument document = new WorkflowDocument(getPrincipalIdForName("quickstart"), "TestDocumentType"); document.routeDocument(""); document = new WorkflowDocument(rkirkendPrincipalId, document.getRouteHeaderId()); assertTrue("approve should be requested", document.isApprovalRequested()); document = new WorkflowDocument(getPrincipalIdForName("user1"), "OutboxTestDocumentType"); document.routeDocument(""); document = new WorkflowDocument(rkirkendPrincipalId, document.getRouteHeaderId()); assertTrue("approve should be requested", document.isApprovalRequested()); List actionList = new ArrayList(KEWServiceLocator.getActionListService().getActionList(rkirkendPrincipalId, new ActionListFilter())); List invocations = new ArrayList(); ActionToTake actionToTake = new ActionToTake(); ActionItem actionItem = new ActionItem(); for (Iterator iterator = actionList.iterator(); iterator.hasNext() { ActionItem actinItem = (ActionItem) iterator.next(); actionToTake.setActionItemId(actinItem.getActionItemId()); actionToTake.setActionTakenCd(actinItem.getActionRequestCd()); invocations.add(new ActionInvocation(actinItem.getActionItemId(), actionToTake.getActionTakenCd())); } KEWServiceLocator.getWorkflowDocumentService().takeMassActions(rkirkendPrincipalId, invocations); assertEquals("Wrong number of outbox items found for rkirkendPrincipalId", 2, KEWServiceLocator.getActionListService().getOutbox(rkirkendPrincipalId, new ActionListFilter()).size()); } In WorkflowDocumentServiceImpl.takeMassActions actionItem was getting deleted before it is saved into the outbox table. So,I have commented the method call in WorkflowDocumentServiceImpl.takeMassActions as follows public void takeMassActions(String principalId, List actionInvocations) { KimPrincipal principal = loadPrincipal(principalId); for (Iterator iterator = actionInvocations.iterator(); iterator.hasNext() { ActionInvocation invocation = (ActionInvocation) iterator.next(); ActionItem actionItem = KEWServiceLocator.getActionListService().findByActionItemId(invocation.getActionItemId()); if (actionItem == null) { LOG.warn("Could not locate action item for the given action item id [" + invocation.getActionItemId() + "], not taking mass action on it."); continue; } // KEWServiceLocator.getActionListService().deleteActionItem(actionItem); ActionInvocationService actionInvocService = MessageServiceNames.getActionInvocationProcessorService(actionItem.getRouteHeader()); actionInvocService.invokeAction(principalId, actionItem.getRouteHeaderId(), invocation); // ActionInvocationProcessor.queueActionInvocation(user, actionItem.getRouteHeaderId(), invocation); } } actionInvocService.invokeAction method internally calls ActionRequestServiceImpl.deactivateRequest which calls deleteActionItems(actionRequest). The method call to deleteActionItems(actionRequest) has been commented to resolve the following exception. org.springmodules.orm.ojb.OjbOperationException: OJB operation failed; nested exception is org.apache.ojb.broker.OptimisticLockException: Object has been modified or deleted by someone else Caused by: org.apache.ojb.broker.OptimisticLockException: Object has been modified or deleted by someone else at org.apache.ojb.broker.accesslayer.JdbcAccessImpl.executeDelete(JdbcAccessImpl.java:119) at org.apache.ojb.broker.core.PersistenceBrokerImpl.doDelete(PersistenceBrokerImpl.java:583) at org.apache.ojb.broker.core.PersistenceBrokerImpl.delete(PersistenceBrokerImpl.java:512) at org.apache.ojb.broker.core.PersistenceBrokerImpl.delete(PersistenceBrokerImpl.java:525) at org.apache.ojb.broker.core.DelegatingPersistenceBroker.delete(DelegatingPersistenceBroker.java:215) at org.apache.ojb.broker.core.DelegatingPersistenceBroker.delete(DelegatingPersistenceBroker.java:215) at org.springmodules.orm.ojb.PersistenceBrokerTemplate$10.doInPersistenceBroker(PersistenceBrokerTemplate.java:255) at org.springmodules.orm.ojb.PersistenceBrokerTemplate.execute(PersistenceBrokerTemplate.java:141) at org.springmodules.orm.ojb.PersistenceBrokerTemplate.delete(PersistenceBrokerTemplate.java:253) at org.kuali.rice.kew.actionitem.dao.impl.ActionItemDAOOjbImpl.deleteActionItem(ActionItemDAOOjbImpl.java:59) at org.kuali.rice.kew.actionlist.service.impl.ActionListServiceImpl.deleteActionItem(ActionListServiceImpl.java:102) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) 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.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:203) at $Proxy204.deleteActionItem(Unknown Source) at org.kuali.rice.kew.routeheader.service.impl.WorkflowDocumentServiceImpl.takeMassActions(WorkflowDocumentServiceImpl.java:412) I have commited the following changed files to the repository. org.kuali.rice.kew.actionlist.OutboxTest and org.kuali.rice.kew.routeheader.service.impl.WorkflowDocumentServiceImpl.
        Hide
        Srikanth Mummadi (Inactive) added a comment -

        I can not see the link to resolve the issue.

        Show
        Srikanth Mummadi (Inactive) added a comment - I can not see the link to resolve the issue.
        Hide
        Eric Westfall added a comment -

        Hi Srikanth, it looks like your implementation just comments out the code that deletes the action item when mass actions are taken. I think this isn't quite what we want. We want to be able to delete the action item immediately but still have it go into the outbox. I've committed a fix that gives us what we need. Take a look at the following changeset when you get a chance:

        https://test.kuali.org/fisheye/changelog/rice/?cs=6658

        The test you wrote is really helpful, I was able to use it to verify the fix above

        Show
        Eric Westfall added a comment - Hi Srikanth, it looks like your implementation just comments out the code that deletes the action item when mass actions are taken. I think this isn't quite what we want. We want to be able to delete the action item immediately but still have it go into the outbox. I've committed a fix that gives us what we need. Take a look at the following changeset when you get a chance: https://test.kuali.org/fisheye/changelog/rice/?cs=6658 The test you wrote is really helpful, I was able to use it to verify the fix above
        Hide
        Eric Westfall added a comment -

        Bulk change of all Rice 1.0 issues to closed after public release.

        Show
        Eric Westfall added a comment - Bulk change of all Rice 1.0 issues to closed after public release.

          People

          • Assignee:
            Srikanth Mummadi (Inactive)
            Reporter:
            Aaron Hamid (Inactive)
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Time Tracking

              Estimated:
              Original Estimate - 2 hours
              2h
              Remaining:
              Remaining Estimate - 2 hours
              2h
              Logged:
              Time Spent - Not Specified
              Not Specified

                Structure Helper Panel