RTC API - Creating WorkItems and modifying them - serverside
Hi guys,
I'm trying to automate defect workitem creation on a server extension but I'm getting confused by the API.
The goal is to create the workItem and add a link of type "Related Change Request" to the "Links" tab of the workItem on a DeliverOperation.
So far this is what I have:
@Override
public void run(AdvisableOperation operation,
IProcessConfigurationElement advisorConfiguration,
IAdvisorInfoCollector collector, IProgressMonitor monitor)
throws TeamRepositoryException {
// TODO Auto-generated method stub
IWorkItemServer workItemService = getService(IWorkItemServer.class);
fItemService = getService(IRepositoryItemService.class);
IProjectArea projectArea = (IProjectArea) fItemService.fetchItem(operation.getProcessArea().getProjectArea(), null);
IWorkItemType defect = workItemService.findWorkItemType(projectArea, "defect", monitor);
if (defect!=null){
IWorkItem newWorkItem = workItemService.createWorkItem2(defect);
newWorkItem.setCreator(getAuthenticatedContributor());
newWorkItem.setOwner(getAuthenticatedContributor());
}else{
System.out.println("handle error");
}
}
Here are several questions based on basic mild runtime debugging:
1) Is the related change request link considered a workItem on it's own (It's an oslc link to a database entry in an external database)? because when I try to add a link to the workitem manually it seems to search for only other workItems and greys out the 'OK' button in the dialog box
2) The CreateWorkItem2 method takes an object of type 'workType', I'm assuming that this specified the type of workItem that you want to create; in this case a "Defect" is that correct? Can it fail without throwing an exception? I can't seem to find the Documentation for this function (SDK 4.0.7)
3) I'm also assuming that one way to retrieve such workType 'template' for use with workItem creation is to use findWorkItemType which searches for the type given its name case insensitive in the given project area.
4) The code included here executed without throwing any exceptions but I don't know whether it fails or not. When I query for all the workitems I don't find the most recent one (looking at timestamps). Are other things that need to be done in order to actually create the workItem? Can the workItem be created from an IOperationAdvisor extending AbstractService or must it extend another class?
5) After the workItem is created how would I link the defect to the external database entry; the most relevant info that I've found regarding this is at this link : https://rsjazz.wordpress.com/2012/09/20/the-rtc-workitem-server-link-api-linking-to-work-items-and-other-elements/
much of the rest of what I've learned is from here:
https://www.ibm.com/developerworks/community/blogs/extendingrtc/?lang=en
Thanks
Accepted answer
1) Is the related change request link considered a workItem on it's own No, it is a Link (It's an oslc link to a database entry in an external database)? because when I try to add a link to the workitem manually it seems to search for only other workItems and greys out the 'OK' button in the dialog box
you need to have a server friend relationship for a related change request..
you can have a related workitem, or a related artifact (which can point to anything with a url)
2) The CreateWorkItem2 method takes an object of type 'workType', I'm assuming that this specified the type of workItem that you want to create; in this case a "Defect" is that correct? Can it fail without throwing an exception? I can't seem to find the Documentation for this function (SDK 4.0.7)
there is no doc for the server side apis. I don't 'know' the answer, but you are probably correct.
3) I'm also assuming that one way to retrieve such workType 'template' for use with workItem creation is to use findWorkItemType which searches for the type given its name case insensitive in the given project area.
correct
looking in the project process xml for the defect workitem type you find this
<type category="com.ibm.team.workitem.workItemType" icon="processattachment:/workitemtype/bug.gif" id="defect" name="Defect">
things usually take the ID, not the name.
4) The code included here executed without throwing any exceptions but I don't know whether it fails or not. When I query for all the workitems I don't find the most recent one (looking at timestamps). Are other things that need to be done in order to actually create the workItem? Can the workItem be created from an IOperationAdvisor extending AbstractService or must it extend another class?
you must SAVE the workitem you created (in memory). Any class should be able to call the api.
note however that Advisors are not supposed to do operations that CHANGE the database.. only ADVISE.
(participants change things). Also remember, when u do the save, all the Advisors and Participants will be called AGAIN for that workitem (and an advisor could reject it)
5) After the workItem is created how would I link the defect to the external database entry;
you need to create a related artifact link type. you can do that BEFORE you issue the save operation.
good reference for links from Ralph's stuff.
the most relevant info that I've found regarding this is at this link : https://rsjazz.wordpress.com/2012/09/20/the-rtc-workitem-server-link-api-linking-to-work-items-and-other-elements/
much of the rest of what I've learned is from here:
https://www.ibm.com/developerworks/community/blogs/extendingrtc/?lang=en
Comments
See also https://rsjazz.wordpress.com/2012/12/14/do-not-modify-the-triggering-element-in-an-operationadvisor/
You can do all this and Sam's explanations are great - as always. Unfortunately I haven't gotten to blog an example yet. It is high on my list.
1 vote
I thought that the 'workitem' newstate was effectively a temporary read only copy of the workitem changes proposed by the thread that initiated the save. any change made to that read only copy would be lost.
reading the workitem AGAIN from the database in an Advisor and then initiating a save breaks the chain of modifications, as you are attempting to override change1 while it is in flight with change 2 (which MUST complete its pass thru the advisors and participants before the advisor for change 1 can get control back from the save operation.. thus you can have change 1 overlay the changes done in change 2.
you have NO idea what the other advisors/participants might depend on, or the order in which they will execute.
You can't modify the item in an advisor - the interface discourages it. it works today, but noone guarantees it will in the future.
Use a participant to do that. You can create new workItems in a participant like this:
IWorkItem aWorkItem = IWorkItemServer.createWorkItem2(wIType);Once you have created the work item, you can create the relationship and then save the relationship to this work item (the one you work with in the participant)// Set the values
// Save with additional parameters to alert this participant to ignore to avoid recursion Set<string> additionalParams = new HashSet<string>(); additionalParams.add("I WAS HERE");
fWorkItemServer.saveWorkItem3(aWorkItem, null, null, additionalParams);
</string></string>
1 vote
One other answer
Object data = operation.getOperationData();
ISaveParameter saveParameter = null;
if (data instanceof ISaveParameter)
{
saveParameter = (ISaveParameter) data;
// check to see if we are being called again from our save
// if not, process, otherwise skip the work
if ( (saveParameter.getAdditionalSaveParameters() == null)
||
(!saveParameter.getAdditionalSaveParameters().contains("I WAS HERE"))
)
Comments
I think adding a
Object o = operation.getOperationData();
if (!(o instanceof DeliverOperationData)) {
return;
}
at the very beginning of the participant should serve the same purpose (because I only need to process things on a deliver operation). This condition is always true for a save instance, correct? (We will always return from this if block on a save operation)
No it does not. If you create a work item in a participant it will trigger work item save operational behavior for that work item. The object will be a work item.
So if you write a participant that, on creation of a work item, creates new work items (with links), the participant will trigger for the new work items and could kill the system by creating new work items and so forth. This is one of the few reasons the Additional Parameters are used for.
I understand what the message is: Participants are always triggered on creations of workitems/saving workitems. So for the multiple triggers operation.getOperationData() will always be an instance of DeliverOperationData? i.e operation.getOperation() instance of DeliverOperationData and operation.getOperation() instance of ISaveParameter can be true at the same time? that's my question.
Now if that's true then I'm confused as to why we have a choice of picking preconditions for separate Operations (project -> Process configuration -> Team configuration -> Operation behaviour). Because we can be distinct about what participants/advisors are called for different operations . Are those operations only executed for actions done through their corresponding client (I.e for e.g saving a workItem through the client and not the server(now that's even more confusing because saveWorkItem has "(server)" in brackets next to it))?
you never mentioned that your participant was for a Deliver operation.
if you only handle delivers, then your code is ok. because you won't be called for a workitem save operation
1 vote
My apologies, I will fix that right away. Thanks.
I realize how this would be useful if we're attempting to save some other workItem while saving a workItem.
Yes, the deliver got me as well 8)
As long as you don't trigger another deliver in the operation (I am not even sure that is supported, we tried that once and it blew us out of the water with an error in the transaction) you should be fine.
1 vote