Hi all,
I followed the content of the article referenced below to create a custom process advisor plugin that is designed to walk the relationship of linked work items. I am using RTC 3.0 and I did make the necessary translations from the article (written against 2.x) and was able to get the example in the article fully deployed and working. The problems started after I needed to add several imports to create the functionality I am looking for. The relevant custom source code is below.
http://jazz.net/library/article/495/
When it runs I get the following error in the process advisor:
An unhandled exception occurred during "Prohibit Save (Hello World Advisor)".The service 'helloworldadvisor.HelloWorldProhibitSave@245c245c' failed to find the required service 'interface com.ibm.team.links.common.service.ILinkService'. Check <prerequisites> in plugin.xml.
I Googled this and looked it up in the forums and it appears that others are saying that I would have to manually edit the plug.xml file. This seems an unlikely task to me. So, I tried anyway but it had no effect. I'm sure I did something wrong because I didn't know what to enter for some of the element attributes.
When I looked up the jar that contains the offending interface I scanned the tomcat directories and was unable to find it on the server. That makes me think that perhaps it needs to be packaged with my plugin. No idea how I would do that.
Hoping some can point out what I need to change in my plugin, feature or site update project.
The source code is follows.
package helloworldadvisor;
import org.eclipse.core.runtime.IProgressMonitor;
import com.ibm.team.links.common.service.ILinkService;
import com.ibm.team.links.common.factory.IReferenceFactory;
import com.ibm.team.links.common.IItemReference;
import com.ibm.team.links.common.ILink;
import com.ibm.team.links.common.ILinkCollection;
import com.ibm.team.links.common.ILinkQueryPage;
import com.ibm.team.links.common.IReference;
import com.ibm.team.links.service.ILinkServiceLibrary;
//import com.ibm.team.process.common.advice.IReportInfo;
import com.ibm.team.process.common.advice.IProcessReport;
//import com.ibm.team.process.common.advice.runtime.IParticipantInfoCollector;
import com.ibm.team.repository.service.AbstractService;
import com.ibm.team.repository.service.IRepositoryItemService;
import com.ibm.team.workitem.common.IWorkItemCommon;
import com.ibm.team.workitem.common.model.*;
import com.ibm.team.workitem.common.workflow.IWorkflowInfo;
import com.ibm.team.workitem.service.IWorkItemServer;
import com.ibm.team.process.common.IProcessConfigurationElement;
import com.ibm.team.process.common.advice.AdvisableOperation;
import com.ibm.team.process.common.advice.IAdvisorInfo;
import com.ibm.team.process.common.advice.IAdvisorInfoCollector;
import com.ibm.team.process.common.advice.runtime.IOperationAdvisor;
//import com.ibm.team.repository.common.IAuditable;
import com.ibm.team.repository.common.TeamRepositoryException;
import com.ibm.team.workitem.common.ISaveParameter;
import com.ibm.team.workitem.common.model.IWorkItem;
public class HelloWorldProhibitSave extends AbstractService implements IOperationAdvisor {
public static final String PROBLEM_TYPE = " HelloWorldAdvisor.prohibitSave";
// Constrain the parent and child work item types.
private final static String CHILD_WORK_ITEM_TYPE_ID = "defect";
private final static String PARENT_WORK_ITEM_TYPE_ID = "task";
// The parent must be in a state of "Done" (state id = "s3")
private final static String PARENT_WORK_ITEM_STATE_ID = "3"; //"s3";
// The action to perform on the child (this action id maps to "Released to QA")
private final static String CHILD_RESOLVING_WORKFLOW_ACTION_ID = "com.ibm.team.workitem.defectWorkflow.action.verify";
private final static String CHILD_DEST_WORK_ITEM_STATE = "Released to QA";
public void run(AdvisableOperation operation,
IProcessConfigurationElement advisorConfiguration,
IAdvisorInfoCollector collector,
IProgressMonitor monitor)
throws TeamRepositoryException
{
/*
Object data = operation.getOperationData();
if (data instanceof ISaveParameter) {
ISaveParameter param = (ISaveParameter) data;
IAuditable auditable = param.getNewState();
if (auditable instanceof IWorkItem) {
IWorkItem sourceworkItem = (IWorkItem) auditable;
IAdvisorInfo problem = collector.createProblemInfo(
"Hello World!", "This work item is of type: "
+ sourceworkItem.getWorkItemType(),
PROBLEM_TYPE);
collector.addInfo(problem);
}
}
*/
// If the work item is of type defect and new state is "Release to QA" then
// Get the work item children
// for each work item child
// Set the state to "Release to QA"
// If work item child state could not be set then
// Add a problem and exit
// Part 1 - check input constraints.
//
// Get the work item that is being saved (the parent work item).
ISaveParameter saveParam = (ISaveParameter) operation.getOperationData();
IWorkItem parent = (IWorkItem) saveParam.getNewState();
System.out.println("HelloWorldProhibitSave: 1");
// Types other than PARENT_WORK_ITEM_TYPE_ID are not interesting.
if (!PARENT_WORK_ITEM_TYPE_ID.equals(parent.getWorkItemType()))
{
System.out.println("HelloWorldProhibitSave: 1.1 - parent.getWorkItemType()=" + parent.getWorkItemType());
return;
}
// When the state of the parent is not PARENT_WORK_ITEM_STATE_ID we are not interested in affecting the child work items.
if (!PARENT_WORK_ITEM_STATE_ID.equals(parent.getState2().getStringIdentifier()))
{
System.out.println("HelloWorldProhibitSave: 1.2 - parent.getState2().getStringIdentifier()=" + parent.getState2().getStringIdentifier() + " parent.getState2().toString()=" + parent.getState2().toString());
return;
}
// Part 2 - Get a collection of the child work items.
//
// Get a service to find the linked work items on the parent work item.
ILinkService linkService = getService(ILinkService.class);
ILinkServiceLibrary linkLibrary = (ILinkServiceLibrary) linkService.getServiceLibrary(ILinkServiceLibrary.class);
// Use the service to find all the related work items linked to the parent.
IItemReference workItemRef = IReferenceFactory.INSTANCE.createReferenceToItem(parent);
ILinkQueryPage linkPage = linkLibrary.findLinks(WorkItemLinkTypes.RELATED_WORK_ITEM, workItemRef);
System.out.println("HelloWorldProhibitSave: 2 - Number of child work items found = " + linkPage.getResultSize());
if (linkPage.getResultSize() == 0)
{
// No child work items, nothing to do.
System.out.println("HelloWorldProhibitSave: 2.1");
return;
}
// Part 3 - Process each child work item.
//
// Get some service to help query and save work items.
IRepositoryItemService repositoryItemService = getService(IRepositoryItemService.class);
IWorkItemServer workItemService = getService(IWorkItemServer.class);
IWorkItemCommon workItemCommon = getService(IWorkItemCommon.class);
// Process each child work item.
int count = 0;
ILinkCollection links = linkPage.getAllLinksFromHereOn();
System.out.println("HelloWorldProhibitSave: 3");
for (ILink link : links)
{
// Get the child work item through the link.
IReference otherRef = link.getOtherRef(workItemRef);
IWorkItemHandle childHandle = (IWorkItemHandle) otherRef.resolve();
IWorkItem child = (IWorkItem) repositoryItemService.fetchItem(childHandle, null);
// Process only closed items of type CHILD_WORK_ITEM_TYPE_ID.
System.out.println("HelloWorldProhibitSave: 3.1");
if(CHILD_WORK_ITEM_TYPE_ID.equals(child.getWorkItemType()) && !isClosed(workItemCommon, child))
{
// Change the state and save the child work item.
IWorkItem childWorkingCopy = (IWorkItem) child.getWorkingCopy();
workItemService.saveWorkItem2(childWorkingCopy, null, CHILD_RESOLVING_WORKFLOW_ACTION_ID);
count++;
System.out.println("HelloWorldProhibitSave: 3.2 - processed work item id = " + child.getId());
}
}
// Part 4 - Offer some feedback.
//
System.out.println("HelloWorldProhibitSave: 4");
addAdvisorInfo(
IProcessReport.OK,
"Saved child defects.",
count + " defects where moved to state \"" + CHILD_DEST_WORK_ITEM_STATE + "\"",
collector);
}
private boolean isClosed(IWorkItemCommon workItemCommon, IWorkItem workItem)
{
if (workItem != null)
{
Identifier<IState> state= workItem.getState2();
if (state != null)
{
try
{
IWorkflowInfo workflowInfo= workItemCommon.findWorkflowInfo(workItem, null);
if (workflowInfo.stateGroupContains(IWorkflowInfo.CLOSED_STATES, state))
{
return true;
}
}
catch (TeamRepositoryException e)
{
return false;
}
}
}
return false;
}
private static void addAdvisorInfo(int severity, String summary, String description, IAdvisorInfoCollector collector)
{
if (collector != null)
{
IAdvisorInfo message =
collector.createProblemInfo(summary,
description,
PROBLEM_TYPE);
message.setSeverity(severity);
collector.addInfo(message);
}
}
}