Using Work Item Queries for Automation


A lot of desirable custom automation for Rational Team Concert is for managing work items. Especially as the number of work items grow over time. I found it very useful to be able to run work item queries and use them to feed my automation. This post shows how to do this.

The Wiki Page QueryDevGuide shows more example code and also how to create queries using the API.

Queries are related to Expressions which are content of the posts Using Expressions for Automation and Using an Expression to Synchronize Attributes for Work Items of a Specific Type.

I am working with some fairly big IBM internal projects that have very mature processes and, due to the huge amount of items, desire a lot of automation. The code in this post originates from working with Susan Hanson who came up with the majority of the code. I found it so useful that I use it in several places.

License and how to get started with the RTC API’S

As always, our lawyers reminded me to state that the code in this post is derived from examples from Jazz.net as well as the RTC SDK. The usage of code from that example source code is governed by this license. Therefore this code is governed by this license, which basically means you can use it for internal usage, but not sell. Please also remember, as stated in the disclaimer, that this code comes with the usual lack of promise or guarantee. Enjoy!

If you just get started with extending Rational Team Concert, or create API based automation, start with the post Learning To Fly: Getting Started with the RTC Java API’s and follow the linked resources.

You should be able to use the following code in this environment and get your own automation or extension working.

To keep it simple this example is, as many others in this blog, based on the Jazz Team Wiki entry on Programmatic Work Item Creation and the Plain Java Client Library Snippets. The example in this blog shows RTC Client API.

Find A Query

If trying to use a work item query for automation, it is necessary to find the query first. To find a query there are basically two scenarios to consider. A query can be a personal query of the user that runs the automation, or it can be a shared query that was predefined and shared by a project area or team area. The first code block below shows how to find a personal query for a given query name provided as string.

public static IQueryDescriptor findPersonalQuery(IProjectArea projectArea, 
		String queryName, IProgressMonitor monitor)
		throws TeamRepositoryException {
	// Get the required client libraries
	ITeamRepository teamRepository = (ITeamRepository)projectArea.getOrigin();
	IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(
		IWorkItemClient.class);
	IQueryClient queryClient = workItemClient.getQueryClient();
	// Get the current user.
	IContributor loggedIn = teamRepository.loggedInContributor();
	IQueryDescriptor queryToRun = null;
	// Get all queries of the user in this project area.
	List queries = queryClient.findPersonalQueries(
		projectArea.getProjectArea(), loggedIn,
		QueryTypes.WORK_ITEM_QUERY,
		IQueryDescriptor.FULL_PROFILE, monitor);
	// Find a query with a matching name
	for (Iterator iterator = queries.iterator(); iterator.hasNext();) {
		IQueryDescriptor iQueryDescriptor = (IQueryDescriptor) iterator.next();
		if (iQueryDescriptor.getName().equals(queryName)) {
			queryToRun = iQueryDescriptor;
			break;
		}
	}
	return queryToRun;
}

The code to call the operation for a personal query “All Work Items” would look as below.

IQueryDescriptor query = findPersonalQuery(projectArea, "All Work Items", monitor);

It is also possible to access the shared queries. The code would look as follows.

public static IQueryDescriptor findSharedQuery(	IProjectArea projectArea, 
		List sharingTargets, String queryName,  IProgressMonitor monitor)
		throws TeamRepositoryException {
	// Get the required client libraries
	ITeamRepository teamRepository = (ITeamRepository)projectArea.getOrigin();
	IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
	IQueryClient queryClient = workItemClient.getQueryClient();
	IQueryDescriptor queryToRun = null;
	List queries = queryClient.findSharedQueries(projectArea.getProjectArea(),
		sharingTargets, QueryTypes.WORK_ITEM_QUERY,
	IQueryDescriptor.FULL_PROFILE, monitor);
	// Find a query with a matching name
	for (Iterator iterator = queries.iterator(); iterator.hasNext();) {
		IQueryDescriptor iQueryDescriptor = (IQueryDescriptor) iterator.next();
		if (iQueryDescriptor.getName().equals(queryName)) {
			queryToRun = iQueryDescriptor;
			break;
		}
	}
	return queryToRun;
}

To call the operation it is necessary to provide a list of sharing targets. The sharing targets can be any project area or team areas in the project area. The code to call the operation above would look as below.

List sharingTargets = new ArrayList();
// Add desired sharing targets
sharingTargets.add(projectArea);
IQueryDescriptor sharedQuery = findSharedQuery(projectArea, sharingTargets, "Done Stories", nomitor);

Run A Query

Once the query is found, you can run it and get the result set. There are basically two possible ways to get the query results.

  1. It is possible to get the results unresolved, which basically means you only get an IAuditableHandle in the result and have to resolve the work item from it to get the data.
  2. It is possible to get the results as work items, resolved with a specific load profile.

*Update*

WARNING!

To avoid calamities with many other users screaming at you, because the server is down, please be very careful if using resolved query results. This is especially true when running with a FULL_PROFILE and overriding the query result limit and running queries with huge amounts of work items. In this case it is smarter to use the unresolved results and pay the performance penalty of resolving the work items individually.

The code to get the unresolved results using the IQueryClient looks as follows.

IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
IQueryClient queryClient = workItemClient.getQueryClient();
IQueryResult unresolvedResults = queryClient.getQueryResults(query);

The code to get the resolved results is very similar and presented below. The difference is that it is necessary to provide a load profile to get the results resolved to the load profile.

IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
IQueryClient queryClient = workItemClient.getQueryClient();
// Set the load profile
ItemProfile loadProfile = IWorkItem.SMALL_PROFILE;
IQueryResult<IResolvedResult> resolvedResults = queryClient.getResolvedQueryResults(query, loadProfile);

The load profile basically defines the attributes that are loaded and available in the work item. com.ibm.team.workitem.common.model.IWorkItem defines several profiles.

ItemProfile SMALL_PROFILE
ItemProfile DEFAULT_PROFILE
ItemProfile MEDIUM_PROFILE
ItemProfile LARGE_PROFILE=
/** The full item profile. */
ItemProfile FULL_PROFILE

I usually use SMALL_PROFILE or FULL_PROFILE. The SMALL_PROFILE provides PROJECT_AREA_PROPERTY, ID_PROPERTY, TYPE_PROPERTY, SUMMARY_PROPERTY, OWNER_PROPERTY. It is possible to create a custom load profile using createExtension and providing the attributes/properties required. For example:

IWorkItem.SMALL_PROFILE.createExtension(Arrays.asList(new String[] { STATE_PROPERTY, PRIORITY_PROPERTY, SEVERITY_PROPERTY, CREATOR_PROPERTY, WORKFLOW_SURROGATE_PROPERTY, DESCRIPTION_PROPERTY, }));

To limit the data to read, use a profile with minimal data to load, especially if running on big queries.

Query Result Size Limit

When processing the query result, you need to be aware that the CCM application has a “Maximum Query Result Set Size”, which is typically set to 1000 items. No work item query run by a user through any UI will provide more items than defined by this limit. The reason basically is to prevent the server from being overloaded by massive amounts of database accesses caused by users.


The limit also applies to the API, however, in the API it is possible to get around it to get the full result set. To do that, you have to change the limit of the result set. It is necessary to do that before you do anything else with the result set. The limit can not be changed after you accessed the results.

The code to change the limit for unresolved results looks like below:

((QueryResultIterator) unresolvedResults).setLimit(Integer.MAX_VALUE);

The code to change the limit for a resolved result set is simpler.

resolvedResults.setLimit(Integer.MAX_VALUE);

Processing the Query Result

The following method shows how to process the unresolved results

public static void processUnresolvedResults(IProjectArea projectArea , IQueryResult results,
		ItemProfile profile, IProgressMonitor monitor)
		throws TeamRepositoryException {
	// Get the required client libraries
	ITeamRepository teamRepository = (ITeamRepository)projectArea.getOrigin();
	IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
	IAuditableCommon auditableCommon = (IAuditableCommon) teamRepository.getClientLibrary(IAuditableCommon.class);
	long processed = 0;
	while (results.hasNext(monitor)) {
		IResult result = (IResult) results.next(monitor);
		IWorkItem workItem = auditableCommon.resolveAuditable(
			(IAuditableHandle) result.getItem(), profile, monitor);
		// Do something with the work item here
		processed++;
	}
	System.out.println("Processed results: " + processed);
}

After adding some logic to process the work item, the method can be called like below:

processUnresolvedResults(projectArea, unresolvedResults, loadProfile, monitor);

The following method can be used to process the resolved results.

public static void processResolvedResults(IProjectArea projectArea,IQueryResult<IResolvedResult> resolvedResults,
		 IProgressMonitor monitor)
		throws TeamRepositoryException {
	// Get the required client libraries
	ITeamRepository teamRepository = (ITeamRepository)projectArea.getOrigin();
	IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
	long processed = 0;
	while (resolvedResults.hasNext(monitor)) {
		IResolvedResult result = resolvedResults.next(monitor);
		IWorkItem workItem = result.getItem();
		// do something with the work item
		processed++;
	}
	System.out.println("Processed results: " + processed);
}

After adding some logic to process the work item, the method can be called like this:

processResolvedResults(projectArea, resolvedResults, monitor);

Process Paged Results

It is possible to paginate the resolved results and run on the returned pages. The code below runs some code on pages in parallel.

resolvedPResults.setPageSize(100);
ArrayList jobs = new ArrayList();
while(resolvedPResults.hasNext(null)){
	ResolvedPageJob job = new ResolvedPageJob(teamRepository, workItemClient, resolvedPResults.nextPage(null));
	jobs.add(job);
	job.setUser(true);
	// run as System Job;
	//job.setSystem(true);
	job.schedule();
}
for (ResolvedPageJob resolvedPageJob : jobs) {
	try {
		resolvedPageJob.join();
	} catch (InterruptedException e) {
	// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

The Job class would look like this.

public static class ResolvedPageJob extends Job {
	private List<IResolvedResult> fPage;
	private ITeamRepository fTeamRepository;
	private IWorkItemClient fWorkItemClient;

	public ResolvedPageJob( ITeamRepository teamRepository, IWorkItemClient workitemClient, List<IResolvedResult> results) {
		super("Run Page");
		fTeamRepository=teamRepository;
		fWorkItemClient=workitemClient;
		fPage=results;
	}

	protected IStatus run(IProgressMonitor monitor) {
		try {
			processResolvedResultsPaged(fTeamRepository, fWorkItemClient,fPage);
		} catch (TeamRepositoryException e) {
			System.out.println("Exception: " + e.getLocalizedMessage());
			return new Status(Status.ERROR,"Me","TeamRepositoryException",e);
		}
		return Status.OK_STATUS;
	}
}

And the method to process the paged resolved results would look like below.

public static void processResolvedResultsPaged(ITeamRepository teamRepository,
		IWorkItemClient workItemClient,
		List page)
		throws TeamRepositoryException {
	long processed = 0;
	for (IResolvedResult resolvedResult : page) {
		IWorkItem workItem = resolvedResult.getItem();
		// do something with the work item
		processed++;
	}
	System.out.println("Processed results: " + processed);
}

Some Observations

I optimized the code a bit by reducing the client libraries to be looked up. I basically got the client libraries in a main method and passed them to the methods.

Then I ran the methods against a test system that had 16000 work items, randomly unresolved and resolved. Some observations I made:

  1. Running with resolved query results was typically quicker than running against unresolved result sets. The bigger the number of work items the smaller the difference.
  2. For running parallel jobs I got a mixed bag. Sometimes it was a lot slower and sometimes it was quicker.

My experiments ran against a test system running on the same machine and using Derby as DB.

To avoid calamities with many other users screaming at you, because the production server is down, please be very careful if using resolved query results. This is especially true when running with a FULL_PROFILE and overriding the query result limit and running queries with huge amounts of work items. In this case it is smarter to use the unresolved results and pay the performance penalty of resolving the work items individually.

Summary

Using the API as described above allows you to run automation against work item queries, for example using WorkItemOperation as presented in Uploading Attachments to Work Items. I will describe some scenarios in follow up posts, for example how to “Synchronize Attributes”. I hope that these code examples will help users out there that have a need for more automation.

56 thoughts on “Using Work Item Queries for Automation

  1. Hi Ralph,
    thank you for this great article. I see how to retrieve the data of a query.
    I would be interested in the following: within RTC each query has a defined result layout (displayed columns). Is it possible through the Java API to get the list of these result columns?

    • Hi Donat,

      I am pretty sure that would be possible. The reason: the Eclipse client does it and that uses the same API. I can’t answer the question which API to use for it, because i have never tried. My code is really only about getting at the data. I don’t display it. You could open the query editor and the tab with what you are looking for and try SHIFT+ALT-F1 (plugin spy) on the tab and it will five you the editor class. You can navigate there and try to figure out how the code works. You can do the same on the Eclipse Query view that shows a result. Maybe that provides you with information to start digging.

  2. Hi Ralph, I second Donat’s comments – great article, and I also would like to be able to programattically discover what columns are specified for display of the query results.

    Here is a way to get this information from the queryToRun object (which implements IQueryDescriptor interface) in your example code:

    //downcast Expression to be of type Statement
    Statement stmt = (Statement)queryToRun.getExpression();
    //SelectClause contains the list of attributes
    SelectClause sc = stmt.getSelectClause();
    List colIds = sc.getColumnIdentifiers();
    for (String colId : colIds){
    log.info( “column ” + colId);
    }

    Note: If your query uses the default set of columns, getColumnIdentifiers will return zero attribute names. But if you have one or more custom columns, getColumnIdentifiers returns the full set of attribute names.

    • Hi Bill, thank you so much for providing the example! I was about to Plug-In-Spy the Eclipse query view to find out how it gets the attributes. Now I can focus on blogging some other topics from my backlog.

      • Hi rsjazz, thanks for your reply, i still have some question about:
        When we defined a query, we will specify the order of each display columns, i found with Bill’s method, we can’t print out the defined order of those columns and it seems kind of random.

      • I haven’t tried to read the column specification (well, I did, but couldn’t figure it out back then), so I can’t comment.

      • By using IWorkItem.getValue() there are numerous examples on this blog and it is also described in the main post about how to use the client API.

  3. Pingback: Using Expressions for Automation | rsjazz

  4. Pingback: Using an Expression to Synchronize Attributes for Work Items of a Specific Type | rsjazz

  5. Hi Ralph,

    Greate article, I would like to know whether is there any API to export the query result to CSV file as we did from RTC client or web after runnig the query.

    Thanks in advance.

    Phaneendra G.

    • Hi Phaneendra,

      The officially supported API is the classes listed in the JavaDoc provided with the Plain Java Client Libraries. If you don’t find anything there, it is not part of the API.

      However, et least in the Eclipse Client you can Plug-In Spy (ALT-SHIFT-F1) on the CSV Export Wizard to find its entry class and maybe what that calls. Having that information would allow to use its interface in an Eclipse extension.

      That would be the best way to start. Other than that, it would be relatively simple to iterate the resultset and output to a CSV file. There are free CSV libraries available that would make it even simpler.

      • thanks for your prompt response. I am using CURL commands to export to CSV file.
        Could you please tell me how to create a Full text query using java API.

      • Hi, haven’t done that yet, sorry. I assume you can search for expressions in the SDK and find the one available.

  6. Hi Ralph

    Thanks for this effective article. Do you have any hints for making joins using this API? for example getting all workitems whose children have an attribute equals to some value Thanks!!
    Amaury

    • Hi Amaury,

      as far as I can tell, you can only create the queries that you also could create using the UI. I have not really looked into it, but that is my assumption right now.

      I am aware there some limitations for example there is no real Exists/Not exists or Find elements with attributes and condition (For all relationships of a kind, the relate element conforms to….).

      So I can’t really answer your question right now. It might also be impossible to do it in a query. However it would be possible to qualify the first set of items and then, iterate the results and check if they (or their related artifacts) meet the desired sub condition.

      I hope this helps.

      • Ralph

        Thanks for your prompt answer, right now this is what we are doing, first query the parents and the iterate over the result to filter out non compliance work items, now the main concern is performance, because there can be 200 children for each work item and iterate and resolve over it is a O(n) complexity. Best regards!!

      • I understand your concern. Please be aware there are enhancement requests for this kind of functionality and I would like to encourage you to create one too.

  7. Hi Ralph,

    nice article, it helped me alot.
    But recently, I started to have problems with resolving query resolved results (I use SMALL_PROFILE).

    On line: while (resolvedResults.hasNext(progressMonitor)) {
    I sometimes get exception:

    java.lang.UnsupportedOperationException: This DocumentBuilder, “org.apache.xerces.jaxp.DocumentBuilderImpl”, does not support the reset functionality. Specification “null” version “null”
    at javax.xml.parsers.DocumentBuilder.reset(DocumentBuilder.java:89)
    at com.ibm.team.workitem.common.internal.DocumentBuilderPool.getBuilder(DocumentBuilderPool.java:119)
    at com.ibm.team.workitem.common.internal.expression.XMLExpressionSerializer.deserialize(XMLExpressionSerializer.java:89)
    at com.ibm.team.workitem.common.internal.expression.XMLExpressionSerializer.deserialize(XMLExpressionSerializer.java:51)
    at com.ibm.team.workitem.common.internal.query.impl.QueryDescriptorCustomImpl.getExpression(QueryDescriptorCustomImpl.java:46)
    at com.ibm.team.workitem.common.internal.query.impl.QueryDescriptorCustomImpl.getResolvedExpression(QueryDescriptorCustomImpl.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.ibm.team.repository.common.internal.util.ItemStore$ItemInvocationHandler.invoke(ItemStore.java:597)
    at com.sun.proxy.$Proxy33.getResolvedExpression(Unknown Source)
    at com.ibm.team.workitem.common.internal.query.QueryResultIterator.fetchFirstPage(QueryResultIterator.java:147)
    at com.ibm.team.workitem.common.internal.query.QueryResultIterator.update(QueryResultIterator.java:129)
    at com.ibm.team.workitem.common.internal.query.QueryResultIterator.nextPage(QueryResultIterator.java:104)
    at com.ibm.team.workitem.common.internal.query.ResolvingQueryResultIterator.update(ResolvingQueryResultIterator.java:125)
    at com.ibm.team.workitem.common.internal.query.ResolvingQueryResultIterator.hasNext(ResolvingQueryResultIterator.java:92)

    The most interesting thing is that, running the same code later, with same query and no changes on RTC gives no exception. Not necessary right the second time I run the query, sometimes it takes even 10 tries, but always finnaly I get to run the code without exception.

    Do you have any idea what’s going on?

    • I have no idea what that could be. However, I have seen issues with Xerces and RTC in the past, where you needed to make sure to have the correct version in the path or something like that. I am not sure if Xerces is supposed to be used, but I would search the internet for the specific error. Maybe there is a known problem?

  8. Hi Ralph,

    Greate article, as is often the case. Can we do the same thing (get all work items) with a RTC follow-up action (server side) ?
    My main problem is that I can not get the IteamRepository Object. Is there a workaround solution ?
    Best regards
    Jérémy

    • You don’t need the ItemRepository object on the server. You use services.

      The code below queries on the server.
      It uses the following services:

      // Get the required service interfaces
      fWorkItemServer = getService(IWorkItemServer.class);
      fWorkItemCommon = getService(IWorkItemCommon.class);
      fAuditableCommon = fWorkItemServer.getAuditableCommon();
      fQueryCommon = getService(IQueryCommon.class);

      /**
      * @param operationTargetWorkItem
      * @param itemUUID
      * @param monitor
      * @return
      * @throws TeamRepositoryException
      */
      private IWorkItem queryProxies(IWorkItem operationTargetWorkItem,
      String itemUUID, IProgressMonitor monitor)
      throws TeamRepositoryException {
      IWorkItem foundProxy = null;
      IProjectAreaHandle projectArea = operationTargetWorkItem
      .getProjectArea();

      IQueryableAttribute projectareaAttribute = QueryableAttributes
      .getFactory(IWorkItem.ITEM_TYPE).findAttribute(projectArea,
      IWorkItem.PROJECT_AREA_PROPERTY, fAuditableCommon,
      monitor);
      IQueryableAttribute typeAttribute = QueryableAttributes.getFactory(
      IWorkItem.ITEM_TYPE).findAttribute(projectArea,
      IWorkItem.TYPE_PROPERTY, fAuditableCommon, monitor);
      IQueryableAttribute proxyIDAttribute = QueryableAttributes.getFactory(
      IWorkItem.ITEM_TYPE).findAttribute(projectArea,
      “com.cust.workitem.attribute.tracking”, fAuditableCommon,
      monitor);
      Expression inProjectAreaExpression = new AttributeExpression(
      projectareaAttribute, AttributeOperation.EQUALS, projectArea);
      Expression isTypeExpression = new AttributeExpression(typeAttribute,
      AttributeOperation.EQUALS,
      “com.cust.workitem.type.trackingproxy”);
      Expression proxyIDExpression = new AttributeExpression(
      proxyIDAttribute, AttributeOperation.EQUALS, itemUUID);

      Term term = new Term(Operator.AND);
      term.add(inProjectAreaExpression);
      term.add(isTypeExpression);
      term.add(proxyIDExpression);

      IQueryResult results = fQueryCommon.getExpressionResults(
      projectArea, term);
      while (results.hasNext(monitor)) {
      IResult result = (IResult) results.next(monitor);

      IWorkItemHandle resultHandle = (IWorkItemHandle) result.getItem();
      IWorkItem fullProxy = (IWorkItem) fWorkItemServer
      .getAuditableCommon()
      .resolveAuditable(resultHandle, IWorkItem.FULL_PROFILE,
      monitor).getWorkingCopy();
      return fullProxy;
      }
      return foundProxy;
      }

    • I don’t know. Sorry. I think I have seen something on Jazz.net in the forum, but I can’t find it right now. I would guess you pass the parameter as additional value in the API calls. I have however not done this so far.

    • Luiz, or rsjazz, did you find a solution? I see IQueryDescriptor.setParameterValues() but it’s deprecated. I’m trying to find the ‘new way’ to provide parameters but can’t the info from jazz site documentation or javadoc. I’m using java plain api version 4.0.6.

  9. Ralph ,
    Is it possible to get work item used to checkin a file/Changeset
    For Exaple if file PropertyReader.java has been checked in by a Developer most recently using work item 123456 .. Need to get the work item number..
    Using scm show history command we can get the Change Set details,but not the work item number.

    scm show history -r $URL -u $userId -P $pwd -w $ws –component icdp_core_as /source/common/Adapters/com/bac/icdp/consumer/common
    /PropertyReader.java
    Change sets:
    (1539) —-$ Json “Lenderview_ForwardFits” 03-Feb-2015 07:35 AM
    (1259) —-$ Joshi, issue fix.” 26-Jun-2014 05:17 AM
    (1260) —-$ Dinesh “changed and added new” 16-May-2014 05:24 AM
    There is additional history available before this point.

    Can i get the Work Item used for the Change set using JAVA or SCM?
    (1539) —-$ Json “Code review changes” 03-Feb-2015 07:35 AM

  10. Hello Ralph,

    I have some work item ids to query. Tried all combination in the expression not get success. In UI mode you can pass ids as 212121,23232,31312 and result will be three work item same is not working in API when I am passing String storyIds = “212121,23232,31312”; only first work item is getting

    Expression wiIdExpression = new AttributeExpression(wiIdAttribute, AttributeOperation.EQUALS,storyIDs);

    there is nothing I found to give list of work item ids. Can you please help me on this.

    Thanks

  11. Hi Ralph, I am trying to get some IworkItem as mentioned above by Praveen Patidar by passing WTIDs( List of Integer) in StoryIDs from Expression wiIdExpression = new AttributeExpression(wiIdAttribute, AttributeOperation.EQUALS,storyIDs); and I get the IResolvedResult when I check the size by using getResultSize(monitor).getTotalAvailable() gives proper size but when I iterate through using IResolvedResult.hasNext() shows null

    • Sorry, but I can only provide you with examples. I can’t debug this for you. I have no idea what could have gone wrong.

      The only thing that comes to mind is to use the permission aware API and check if you actually have permission to access the results.

  12. Hi rsjazz, is it possible that retrieve a query result only with its query id or query name? No matter it’s a personal query or shared query? And regard the query result, can we choose to show column value as “Labels” or “Internal value”? Thanks.

    • The IQueryDescriptor is an IAuditable so you should be able to use IAuditableCommon.resolveAuditable to get the query descriptor from the handle, which you can get from the query UUID.

      Once you retrieve the work items it is basically up to you how you display its data.

  13. Hi Ralph,
    I am getting this below error while executing a query. This seems to be an internal error but i dont know why it is coming. Previously I was using Shared query. This error started coming after i moved to Personal query.

    Thanks in advance.

    java.lang.NullPointerException
    at com.ibm.team.workitem.common.internal.query.QueryResultIterator.fetchFirstPage(QueryResultIterator.java:147)
    at com.ibm.team.workitem.common.internal.query.QueryResultIterator.update(QueryResultIterator.java:129)
    at com.ibm.team.workitem.common.internal.query.QueryResultIterator.nextPage(QueryResultIterator.java:104)
    at com.ibm.team.workitem.common.internal.query.ResolvingQueryResultIterator.update(ResolvingQueryResultIterator.java:124)
    at com.ibm.team.workitem.common.internal.query.ResolvingQueryResultIterator.hasNext(ResolvingQueryResultIterator.java:91)

    • Sorry, but I can’t maintain a debug service here. I used this code several times and it worked for me. Make sure to test all the parameters for null. In 99% of the cases where I ran into nullpointer exceptions it was my bad and some class or argument was null.

  14. Hii Ralph,
    Can we get user story ID from work item ID using java api ?
    If possible can u please guide me how to achieve it

      • Sorry, this is not a free interactive help. Consider searching this blog for the API examples. If you would follow section “License and how to get started with the RTC API’S” you would be able to find this here. You can also use the search field or Google to find examples.

  15. Hi Ralph,
    I have used your examples and created query in UI and fetching the results programmatically.
    Can we pass the JRS Query also same way?
    Thanks,
    Chandra

    • This is an RTC API. JRS is its own application and you can not pass JRS Reports using the RTC Java API. I am not aware of a public API for JRS either.

  16. Hi, I wrote a query for all duplicate defects. But in returned resultset/WorkItem, I cannot find data corresponding to “Duplicate Of” column. Do you know if there is a way to use QueryableAttributes.getFactory() method to get “Duplicate Of” attribute?

    • I am not aware of an attribute “Duplicate Of”. As far as I am aware, “Duplicate Of” is modeled as a link type. I have not tried to query for link types, but the UI indicates it is possible.

  17. Hi Ralph,
    I have to fetch all children of a work item, then I have a Collection of result. Can I run the query on this result collection ?
    If I use your example, I need to modify the method processResolvedResults(), and then find results full fill the relation of parent work item. But I think this way is too complex.
    So can you give me any suggestions for this case because I need to fetch all the children of a list work items which full fill the query.

    • I think Ulf Arne provided a reasonable answer. There is some limited capability to query for relationships, but I have not looked at that. Iterating the results and looking up the results that have children is a valid approach too.

  18. Hi Ralph,

    Great article! Related to this, do you know if we can read “Column display” tab configuration for a query (UI). Because on QueryResults are populates with work items fetched using IWorkItem.SMALL_PROFILE (load profile). I would like get the columns which displays when a user configure “Column display” tab for export result to a file with that attributes (which can be changed by the user throught UI). In addition I checked on IQueryDescriptor but not luck.

    Or if there is a method / service such as CSV export button?

    Thank you!

    • Hi Francisco,

      I was curious about that as well, but was never really able to solve this. I decided to write my own exporter for my work item command line.

      If you want to find out how the columns work, I would suggest to look at the SDK code of com.ibm.team.workitem.rcp.ui.internal.explorer.view.WorkItemExplorer2
      and try to figure how that works.

      • Thank you Ralph,

        Finally I used the next REST service which correspond with the “Export” query button:
        “https://:9443/ccm/resource/itemOid/com.ibm.team.workitem.query.QueryDescriptor/?_mediaType=text/csv&nocache=”
        and works like a charm.

        I will take a look to your suggested class too.

        Thank you.

  19. Hi Ralph,

    I was hoping you had some examples / information as to how to create and pass through the monitor during the processing of the information in the second to last step with IProgressMonitors?

    I’ve been searching online and can’t find a whole log of good information in regards to them.

    Your response is appreciated.

    – Stephen

  20. Hi Ralph,
    I need to fetch all the workitems of type Delivery in a project area using client side api. Could you please guide .

    Thanks & Regards,
    Pavithra

    • Sorry, but I am not free service. You can take the code on the post and change it to your desires. There is another one that uses expressions for querying, that you can use as well.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.