Hi,
we are trying to develop a Follow up action with the following logic:
- When the status of a parent WorkItem changes to a "final" state (like "Done" or "Invalid"), fetch all children from the repository and set their status to the same as the parent.
We developed a participant (see code below), but we are getting this exception when the "saveWorkItem2" method is invoked:
012-02-01 17:01:04,608 ERROR com.ibm.team.process.common - assertion failed:
org.eclipse.core.runtime.AssertionFailedException: assertion failed:
at org.eclipse.core.runtime.Assert.isTrue(Assert.java:110)
at org.eclipse.core.runtime.Assert.isTrue(Assert.java:96)
at com.ibm.team.workitem.service.internal.WorkItemRepositoryService.reconcileWithCurrent(WorkItemRepositoryService.java:862)
at com.ibm.team.workitem.service.internal.WorkItemRepositoryService.detectConflictingUpdates(WorkItemRepositoryService.java:313)
at com.ibm.team.workitem.service.internal.WorkItemRepositoryService.access$0(WorkItemRepositoryService.java:303)
at com.ibm.team.workitem.service.internal.WorkItemRepositoryService$1.run(WorkItemRepositoryService.java:262)
at com.ibm.team.workitem.service.internal.WorkItemRepositoryService$1.run(WorkItemRepositoryService.java:1)
at com.ibm.team.repository.service.internal.TransactionService$2.run(TransactionService.java:204)
at com.ibm.team.repository.service.internal.rdb.RepositoryDatabase.runTransaction(RepositoryDatabase.java:312)
at com.ibm.team.repository.service.internal.rdb.RepositoryDatabase.runInTransaction(RepositoryDatabase.java:236)
at com.ibm.team.repository.service.internal.TransactionService.runInTransaction(TransactionService.java:119)
at com.ibm.team.repository.service.internal.TransactionService.runInTransaction(TransactionService.java:88)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:618)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord.invoke(ExportProxyServiceRecord.java:370)
can someone please give us a hint of what we are doing wrong?
package com.ei.test.checkstatusparticipant;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import com.ibm.team.links.common.IItemReference;
import com.ibm.team.links.common.IReference;
import com.ibm.team.process.common.IProcessConfigurationElement;
import com.ibm.team.process.common.advice.AdvisableOperation;
import com.ibm.team.process.common.advice.IReportInfo;
import com.ibm.team.process.common.advice.runtime.IOperationParticipant;
import com.ibm.team.process.common.advice.runtime.IParticipantInfoCollector;
import com.ibm.team.repository.common.IItemHandle;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.repository.service.AbstractService;
import com.ibm.team.repository.service.IRepositoryItemService;
import com.ibm.team.workitem.common.ISaveParameter;
import com.ibm.team.workitem.common.model.IState;
import com.ibm.team.workitem.common.model.IWorkItem;
import com.ibm.team.workitem.common.model.IWorkItemHandle;
import com.ibm.team.workitem.common.model.IWorkItemReferences;
import com.ibm.team.workitem.common.model.Identifier;
import com.ibm.team.workitem.common.model.WorkItemEndPoints;
import com.ibm.team.workitem.common.workflow.IWorkflowAction;
import com.ibm.team.workitem.common.workflow.IWorkflowInfo;
import com.ibm.team.workitem.service.IWorkItemServer;
public class StatusConsistency extends AbstractService implements
IOperationParticipant {
public void run(AdvisableOperation operation,
IProcessConfigurationElement participantConfig,
IParticipantInfoCollector collector, IProgressMonitor monitor)
throws TeamRepositoryException {
/*
* First check that the operation data is work item save data.
*/
Object data = operation.getOperationData();
ISaveParameter saveParameter = null;
if (data instanceof ISaveParameter) {
saveParameter = (ISaveParameter) data;
/*
* If the state id has not changed, do nothing.
*/
IWorkItem newState = (IWorkItem) saveParameter.getNewState();
Identifier<IState> newStateId = newState.getState2();
Identifier<IState> oldStateId = null;
IWorkItem oldState = (IWorkItem) saveParameter.getOldState();
if (oldState != null) // New work item check.
oldStateId = oldState.getState2();
if ((newStateId != null) && !(newStateId.equals(oldStateId))) {
/*
* There was status update. Fetch full list of States first
*/
IWorkItemServer workItemServer = getService(IWorkItemServer.class);
IWorkflowInfo workflowInfo = workItemServer.findWorkflowInfo(newState, monitor);
//Identifier<IState>[] states = workflowInfo.getAllStateIds();
//for (int i = 0; i < states.length; i++) {
// System.out.println(workflowInfo.getStateName(states[i]));
//}
//If the new state of the current WI is "Done" or "Invalid", assign an action for the children
String actionForChildren="";
if (workflowInfo.getStateName(newStateId).equalsIgnoreCase("Done") ||
workflowInfo.getStateName(newStateId).equalsIgnoreCase("Invalid")){
Identifier<IWorkflowAction>[] actions=workflowInfo.getActionIds(newStateId);
actionForChildren = actions[0].getStringIdentifier();
}
if (actionForChildren.length()>1){ //Fetch the children and apply action if required
// Getting workitem references
IWorkItemReferences references = saveParameter.getNewReferences();
// Get all workitem children or parent references.
List<IReference> listReferences = references.getReferences(WorkItemEndPoints.CHILD_WORK_ITEMS);
// Fetch reference to child workitems, filtered by type
List<IWorkItem> typedChildren = findReferenceByType(listReferences, "task");
if (typedChildren!=null && !typedChildren.isEmpty()) {
for (IWorkItem childWI : typedChildren) {
Identifier<IState> childStateId = childWI.getState2();
if (workflowInfo.getStateName(childStateId).equalsIgnoreCase("New")||
workflowInfo.getStateName(childStateId).equalsIgnoreCase("In Progress")||
workflowInfo.getStateName(childStateId).equalsIgnoreCase("Waiting")){
saveWorkItem(workItemServer, childWI, actionForChildren);
IReportInfo createInfo = collector.createInfo("Status updated", childWI.getHTMLSummary().getPlainText());
collector.addInfo(createInfo);
}
}
}
}
}
}
}
/**
* * Find all WorkItens references for a given EndPointDescriptor *
* * @param listReferences *
* List<IReference>
* * @param type
* String workitem type or null to all types
* * @return List of WorkItens
* * @throws TeamRepositoryException */
public List<IWorkItem> findReferenceByType(List<IReference> listReferences, String type) throws TeamRepositoryException
{
IItemHandle referencedItem = null;
IWorkItem workChild = null; // Default result, empty list
List<IWorkItem> listWorkChildren = new ArrayList<IWorkItem>();
// Repository service to fetch item
IRepositoryItemService repositoryItemService = getService(IRepositoryItemService.class);
// has items
if (listReferences!=null && !listReferences.isEmpty()) {
for (IReference reference : listReferences) {
// It is indeed a item reference
if (reference.isItemReference()) {
// Cast and check if it is an IWorkItem
referencedItem = ((IItemReference) reference).getReferencedItem();
if (referencedItem instanceof IWorkItemHandle) {
// Fetch item
workChild = (IWorkItem) repositoryItemService.fetchItem(referencedItem,
IRepositoryItemService.COMPLETE);
// Apply filter for type
if ((type == null) || (type.equals(workChild.getWorkItemType()))) {
listWorkChildren.add(workChild);
}
}
}
}
}
return listWorkChildren;
}
public void saveWorkItem(IWorkItemServer service, IWorkItem wiToSave, String action) throws TeamRepositoryException{
service.saveWorkItem2(wiToSave,null, action);
System.out.println("Work Item " + wiToSave.getHTMLSummary().getPlainText() + " has been saved.");
System.out.println("Action triggered: " + action);
}
}