It's all about the answers!

Ask a question

What is the best way to process results using plain Java API?


Andy Jewell (24236174) | asked Jan 06 '14, 1:45 p.m.
edited Jan 06 '14, 1:50 p.m.
I'm embarrassed to ask this since @rschoon has done such a great job describing how to run a query using the plain Java API.  Where he iterates the results and says to 'do something with the workitem', I am using this method:

	public static void processResolvedResults(IProjectArea projectArea,IQueryResult<IResolvedResult<IWorkItem>> resolvedResults,
WorkitemResultProcessor processor)
throws TeamRepositoryException {
 // Get the required client libraries
 ITeamRepository repo = (ITeamRepository)projectArea.getOrigin();
 IWorkItemClient wiclient = (IWorkItemClient) repo.getClientLibrary(IWorkItemClient.class);
 IWorkItemWorkingCopyManager cm = wiclient.getWorkItemWorkingCopyManager();
 long processed = 0;
 while (resolvedResults.hasNext(processor.getMonitor())) {
IResolvedResult<IWorkItem> result = resolvedResults.next(processor.getMonitor());
IWorkItem work_item = (IWorkItem) result.getItem();
log.trace("Processing result {} - {}",work_item.getId(),work_item.getHTMLSummary());
WorkItemWorkingCopy wc = cm.getWorkingCopy(work_item);
processor.execute(wc, processor.getMonitor());
cm.disconnect(work_item);
processed++;
 }
 System.out.println("Processed results: " + processed);
}
My WorkitemResultProcessor is an interface, in this case, it's not even making it to that point.  My debugging output does show that I have a valid result (i.e., at least it shows the ID and summary).

I am getting an assertion error in WorkItemWorkingCopyRegistry.getWorkingCopy while making the working copy:

org.eclipse.core.runtime.AssertionFailedException: null argument:
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:85)
at org.eclipse.core.runtime.Assert.isNotNull(Assert.java:73)
at com.ibm.team.workitem.client.internal.WorkItemWorkingCopyRegistry.getWorkingCopy(WorkItemWorkingCopyRegistry.java:754)
at com.ibm.team.workitem.client.internal.WorkItemWorkingCopyManager.getWorkingCopy(WorkItemWorkingCopyManager.java:98)
at org.kp.rtc.UpdateableDeploymentItems.processResolvedResults(UpdateableDeploymentItems.java:197)
at org.kp.rtc.TestUpdateableDeploymentItems.testRunUnresolvedQuery(TestUpdateableDeploymentItems.java:66)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


The work item in question was also created via the plain Java API and I noticed while debugging that some of the fields that I assumed would be set automatically (e.g., create date and owner) were null.  They appear just fine in the UI but maybe one of these (or one of several others) is causing this failure?

Does anyone have any ideas what might be causing this?  Perhaps some fields are not required for creating the workitem but required for creating a working copy of it??

- Andy

Comments
sam detweiler commented Jan 06 '14, 2:19 p.m.

 see my workitng sample here

dumps out all details of workitems returned in a predefined query


Andy Jewell commented Jan 06 '14, 2:41 p.m.

Thanks, Sam - do you have an example that creates a working copy?  Reason being, I need to create a working copy in order to use a sub-class of WorkItemOperation.  I am extracting the work item from the query with no problem and I think I could iterate the attributes.  Basically, what I'm trying to do is create a type of action-query where I pass in an object that will run an update operation on each row of the query results.  But I'm having a problem creating a working copy.

2 answers



permanent link
Andy Jewell (24236174) | answered Jan 07 '14, 11:02 a.m.
edited Jan 07 '14, 11:05 a.m.
 Updated code - once I realized that the WorkItemOperation execute method could be passed a WorkItem and not a workitem copy, then Ralph's original article (referenced above) makes a lot more sense.

Processing results from a query:

	public static void processResolvedResults(IProjectArea projectArea,IQueryResult<IResolvedResult<IWorkItem>> resolvedResults,WorkitemResultProcessor processor) throws TeamRepositoryException, RtcException {
while (resolvedResults.hasNext(processor.getMonitor())) {
IResolvedResult<IWorkItem> result = resolvedResults.next(processor.getMonitor());
IWorkItem work_item = (IWorkItem) result.getItem();
log.trace("Processing result {} - {}",work_item.getId(),work_item.getHTMLSummary());
processor.execute(work_item);
}
}

This is my convenience wrapper/interface.  I use it to help in other parts of my particular implementation but included here to better follow the code above.

WorkitemResultProcessor.java:

public interface WorkitemResultProcessor {
public void execute(IWorkItemHandle workingCopy) throws RtcException;
public IProgressMonitor getMonitor(); }
As Ralph suggests in the article, my updater uses an inner class to set up the WorkItemOperation:

UpdateWorkItemStatus.java:

public class UpdateWorkItemStatus implements WorkitemResultProcessor {
String newaction ="";
IProgressMonitor monitor = null;
public UpdateWorkItemStatus(String statusaction,IProgressMonitor mon){
monitor = mon;
newaction = statusaction;
mon.subTask("Preparing to update");
}

public IProgressMonitor getMonitor() {
return monitor;
}
public String getNewaction() {
return newaction;
}

public void execute(IWorkItemHandle wh) throws RtcException {
StatusAssign chgstatus = new StatusAssign(newaction);
try {
chgstatus.run(wh,monitor);
} catch (TeamRepositoryException e) {
throw new RtcException("Problem setting status to '"+getNewaction()+"': "+e.getMessage());
}
}

class StatusAssign extends WorkItemOperation {
String newstatus_action = "";
public StatusAssign(String action) {
super("Updating workitem...", IWorkItem.FULL_PROFILE);
newstatus_action = action;
}
public StatusAssign(String name, ItemProfile profile) {
super(name, profile);
}
@Override
protected void execute(WorkItemWorkingCopy workingCopy,IProgressMonitor monitor) throws TeamRepositoryException {
String msg = String.format("Updating workitem %s: setting status to '%s'",workingCopy.getWorkItem().getId(),newstatus_action);
monitor.subTask(msg);
workingCopy.setWorkflowAction(newstatus_action);
}
}
}


permanent link
Andy Jewell (24236174) | answered Jan 06 '14, 5:18 p.m.
edited Jan 06 '14, 5:19 p.m.
Ok, I RTFM'ed and discovered that you can't use getWorkingCopy unless you already have a connection:

WorkItemWorkingCopy getWorkingCopy(IWorkItemHandle handle)
	Returns the working copy corresponding to the given handle. The working copy must have been connected to before.
		

(Emphasis added).  So I changed the update method to this:

public static void processResolvedResults(IProjectArea projectArea,IQueryResult<IResolvedResult<IWorkItem>> resolvedResults,
WorkitemResultProcessor processor)
throws TeamRepositoryException {
// Get the required client libraries
ITeamRepository repo = (ITeamRepository)projectArea.getOrigin();
IWorkItemClient wiclient = (IWorkItemClient) repo.getClientLibrary(IWorkItemClient.class);
IWorkItemWorkingCopyManager cm = wiclient.getWorkItemWorkingCopyManager();
long processed = 0;
while (resolvedResults.hasNext(processor.getMonitor())) {
IResolvedResult<IWorkItem> result = resolvedResults.next(processor.getMonitor());
IWorkItem work_item = (IWorkItem) result.getItem();
log.trace("Processing result {} - {}",work_item.getId(),work_item.getHTMLSummary());
try {
cm.connect((IWorkItemHandle)work_item.getItemHandle(),IWorkItem.FULL_PROFILE,processor.getMonitor());
WorkItemWorkingCopy wc = cm.getWorkingCopy(work_item);
processor.execute(wc, processor.getMonitor());
} catch(Exception e) {

} finally {
cm.disconnect(work_item);
}
processed++;
}
System.out.println("Processed results: " + processed);
}

And it works.

Comments
sam detweiler commented Jan 06 '14, 8:17 p.m.

Sorry, what is the value of this mechanism? 


Andy Jewell commented Jan 07 '14, 10:52 a.m.

Actually, the working copy isn't required after all (when using WorkItemOperation).  I was confused because the WorkItemOperation execute takes a WorkItemWorkingCopy argument which I thought meant that I had to create a working copy.  But this is actually an interface which is satisfied by a WorkItem as well.  So the value is that you can iterate the (resolved) results list of a query without creating a new WorkItem copy for every result.  I will post the updated code.

Your answer


Register or to post your answer.