Working with Work Item Attributes


When I started with customizing RTC, the biggest challenge was how to get started on work item attributes. Since getting work item attributes is also one of the most popular search terms on this blog, I think a small summary would be useful for new users of the RTC Java API’s.

*Update* The RTC Work Item Command Line is open source and contains downloadable code that performs most of the activities required for reading and modifying work items, their attributes, and all kinds of links. This includes reading and writing work item attribute of all kinds, including list attribute types. The interesting code can be found in the com.ibm.js.team.workitem.commandline.helper package in the class WorkItemHelper. For reading values look at the class ExportWorkItemsCommand and look at ExportWorkItemsCommand.getStringRepresentation(IWorkItem, ParameterValue) and the subsequently called methods. All techniques described below are used there. You can familiarize yourself with the concepts in this post and then look into that project for how it is used.

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.

Download Example Code

Download Examples from Dropbox here. Please note, that Dropbox might be blocked and unavailable in some companies.

Update: the The RTC Work Item Command Line has example code for an almost complete set of attribute types.

To keep it simple this example is again based on the Jazz Team Wiki entry on Programmatic Work Item Creation. If you are just starting with extending Rational Team Concert, start reading this and the linked posts to get some guidance on how to set up your environment.

Which API?

If you look at the examples below, you will note that the code below uses the interfaces

com.ibm.team.workitem.common.IWorkItemCommon

or

com.ibm.team.workitem.client.IWorkItemClient

to access work item data. Always look at the interface com.ibm.team.workitem.common.IWorkItemCommon first and use it if the method you need is available. The common API is usable in the client and the server API and is the preferred API to use. Only use specific client or server API if the common API does not have this API(the namespace is like com.ibm.*.domain.client for client API or  com.ibm.*.domain.server for server API).

Most of the usage of the methods available on IWorkItemClient are inherited from IWorkItemCommon and it is better to replace usage of IWorkItemClient with usage of IWorkItemCommon whereever possible.

Why did I use IWorkItemClient? I was inexperienced and found the client API first in examples and It only later occurred to me that it is better to search the common API first.

Getting the Work Item’s Attribute ID’s in the UI

You can find the work item attributes and their ID’s in the project area administration Web UI in the section Work Items, subsection Types and Attributes. Select the work item type you are interested in. The attribute IDs for the built in and the custom attributes for the selected work item type can be found in the ID column.

AttributeIDs

RTC Web Administration UI shows valid attribute ID’s

Please note, do not use the attribute ID’s you find in the project area administration in the RTC Eclipse client. The RTC Eclipse client shows attribute ID’s with a prefix com.ibm.team.workitem.attribute such as such as com.ibm.team.workitem.attribute.category. This attribute ID is not the one that works with the work item API. I am not sure what they really do, but they don’t work to get attribute values. See the Enhancement Request 219100 RTC Eclipse Client shows wrong IDs for internal Work Item Attributes for Java API for details.

WrongAttributeID's

RTC Eclipse Client shows wrong attribute ID’s for internal attributes

Getting the Work Item’s Attributes in the API

You can also find the attribute ID’s in the API. The Work Item Command Line uses this for the command printtypeattributes.

If you have a work item, an object of type IWorkItem in the API, you will realize that you have only a very limited set of getters and setters to access information for the work item. You have access to the Summary, Owner, and some other built in attributes of the work item. If you look at a RTC work item, you realize there is much more information in it. The question is how to access this information?

The RTC data meta-model provides a special interface that is used to access arbitrary attributes of a work item. The interface is com.ibm.team.workitem.common.model.IAttribute. To access an arbitrary Attribute at a work item, you need to get the IAttribute first.

There are several ways how this can be done. Please note that most of the functionality used below is available in the interface com.ibm.team.workitem.common.IWorkItemCommon. This interface can be used in both the client and the server API. In the client API com.ibm.team.workitem.client.IWorkItemClient inherits the IWorkItemCommon interface. in the server API com.ibm.team.workitem.service.IWorkItemServer also inherits the IWorkItemCommon interface. Use IWorkItemCommon where possible.

If you have the Attribute ID available as a string, you can use this code to get the attribute.

IWorkItemClient workItemClient = (IWorkItemClient) fTeamRepository.getClientLibrary(IWorkItemClient.class);
IAttribute someAttribute= workItemClient.findAttribute(fProjectArea, "some_attribute_ID", monitor);

Another example if you know the work item ID, it is possible to find the work item form the string value.

IWorkItemCommon workItemCommon = (IWorkItemCommon ) fTeamRepository.getClientLibrary(IWorkItemCommon.class);
IAttribute attribute = workItemCommon.findAttribute(projectArea, attributeID,
				getMonitor());
if(attribute != null){
	// Do something with it.
}

RTC defines some built-in attributes that are typical for all kinds of work items. You can get the ID’s for these attributes using the interface com.ibm.team.workitem.common.model.IWorkItem. The interface defines several properties containing the ID’s for built-in the work item attributes.

This code for example gets the attribute for the built-in duration.

IAttribute built_in_duration = workItemCommon.findAttribute(fProjectArea, IWorkItem.DURATION_PROPERTY, monitor);

If this is not feasible, because you do some automation and don’t want to hard code it, the code below gets all the built in attributes of a project area.

List builtInAttributeHandles = workItemCommon.findBuiltInAttributes(fProjectArea, monitor);

If you are looking for all attributes, this method below retrieves the list.

List allAttributeHandles = workItemCommon.findAttributes(fProjectArea, monitor);

There is no method that returns only the custom attributes from the project area. You can however get the custom attributes directly from a work item using the code below:

List custAttributeHandles = workItem.getCustomAttributes();

The code to get the attributes, returns only a handle. You have to resolve the handle to the full object. The code below shows how that can be done.

for (Iterator iterator = builtInAttributeHandles .iterator(); iterator.hasNext();) {
    IAttributeHandle iAttributeHandle = (IAttributeHandle) iterator.next();
    IAttribute iAttribute = (IAttribute) fTeamRepository
        .itemManager().fetchCompleteItem(
        iAttributeHandle, IItemManager.DEFAULT ,monitor);
}

This code uses the permission aware API instead, to get the built in attributes.

List builtInAttributeHandles = workItemClient.findBuiltInAttributes(fProjectArea, monitor);
IFetchResult builtIn = getTeamRepository().itemManager().fetchCompleteItemsPermissionAware(built_in_attribs,
    IItemManager.DEFAULT, monitor);

Get a Work Item Attribute

Once you have the IAttribute, you can get the value of the attribute using the method IWorkItem.getValue(). However, as described in the post Using an Expression to Synchronize Attributes for Work Items of a Specific Type, work items do not necessarily have all attributes already. This especially holds true for custom attributes. You either need to check for a null value, or you can check if the work item actually has the attribute using code like below.

if (workItem.hasAttribute(iAttribute)) {
	Object value = workItem.getValue(iAttribute);
}

The call returns a plain object. You have to cast the returned value to the expected type, to use it. Examples for basic objects are String, Integer, Boolean. You can use these to access the data. The API has many more attribute types that you can also use to cast and access the data.

Here an example how to access a attribute of type String:

if (workItem.hasCustomAttribute(customString)){
	Object value = workItem.getValue(customString);
	if (value instanceof String) {
		String attributeValue = (String) value;
		// do something with the value
	}
}

It is necessary to understand the type that is returned. The information is can easily be picked up during debugging.

Typical Attribute Types

The available attribute types can be found in the process configuration in the Web UI (or the Eclipse UI). To get the valid information for built in and custom attributes, the Web UI works best. The Type column shows the type, the ID column shows the ID of the attribute. Note, the Eclipse Client shows an external ID for built in attributes, that does not work.

AttributeTypes_2017-05-15_10-40-15

Please find below some examples how to access work item attributes of different types. The examples are taken from the Work Item Command Line which has examples for almost every attribute type. You can download the code from here. All the examples expect the object returned by calling

Object value = workItem.getValue(customString);

where customstring is the IAttribute. Work items have some additional attributes where the IWorkItem interface provides direct access to the data e.g. getSummary().

For a complete list of attribute values and their conversion to text see the WorkItem Command Line and the class ExportWorkItemsCommand and look at ExportWorkItemsCommand.getStringRepresentation(IWorkItem, ParameterValue) and the subsequently called methods to convert the attributes to strings.

The most important attribute types are shown below.

Category

The attribute “Filed Against” returns a category. The conversion to user readable text looks like this:

/**
 * Compute the string representation for a category
 * 
 * @param value
 * @return
 * @throws TeamRepositoryException
 */
private String calculateCategoryAsString(Object value)
		throws TeamRepositoryException {
	if (value != null) {
		if (value instanceof ICategoryHandle) {
			return getWorkItemCommon().resolveHierarchicalName(
				(ICategoryHandle) value, getMonitor());
		}
		throw new WorkItemCommandLineException(
				"Convert Category - Incompatible Type Exception: "
						+ value.toString());
	}
	return CONSTANT_NO_VALUE;
}

Number Types

There are several number types supported. Here the conversion to text values.

/**
 * Compute the string representation for a number
 * 
 * @param value
 * @param format
 * @return
 */
private String calculateNumberAsString(Object value, String format) {
	if (value == null) {
		return CONSTANT_NO_VALUE;
	}
	if (value instanceof Integer) {
		return ((Integer) value).toString();
	}
	if (value instanceof Long) {
		return ((Long) value).toString();
	}
	if (value instanceof Float) {
		return ((Float) value).toString();
	}
	if (value instanceof BigDecimal) {
		return ((BigDecimal) value).toString();
	}
	throw new WorkItemCommandLineException(
			"Calculate number - Incompatible Type Exception: "
					+ value.toString());
}

Enumeration Type Attributes

Typical custom attribute types are enumerations. This code shows how to access the values. Also see the post Manipulating Work Item Enumeration Values.

/**
 * Compute a string representation for one enumeration literal
 * 
 * @param value
 * @param attribute
 * @return
 * @throws TeamRepositoryException
 */
private String calculateEnumerationLiteralAsString(Object value,
		IAttribute attribute) throws TeamRepositoryException {
	if (value == null) {
		return CONSTANT_NO_VALUE;
	}
	if (!(value instanceof Identifier)) {
		return "Value not an enumeration literal";
	}
	IEnumeration enumeration = getWorkItemCommon()
			.resolveEnumeration(attribute, getMonitor());
	@SuppressWarnings("unchecked")
	Identifier currentIdentifier = (Identifier) value;
	ILiteral literal = enumeration
			.findEnumerationLiteral(currentIdentifier);
	return literal.getName();
}

Comments

Comments are not an attribute, but a collection that can be accessed. Here an example how to get at the information.

IComments comments = workItem.getComments();
IComment[] theComments = comments.getContents();
List commentText = new ArrayList(theComments.length);
int i = 1;
for (IComment aComment : theComments) {
	if (i > 1) {
		commentText.add("\r");
	}
	commentText.add(i + ". " + aComment.getHTMLContent().getPlainText());
	i++;
}

Contributor Type Attributes

User references are stored as com.ibm.team.repository.common.IContributorHandle as handles for IContributors. To access the contributor information it is necessary to get the handle and resolve the contributor. This is shown below.

/**
 * Compute the string representation for a contributor/user
 * 
 * @param value
 * @return
 * @throws TeamRepositoryException
 */
private String calculateContributorAsString(Object value)
		throws TeamRepositoryException {
	if (value == null) {
		return CONSTANT_NO_VALUE;
	}
	if ((value instanceof IContributorHandle)) {
		IContributor contributor = (IContributor) getTeamRepository()
				.itemManager().fetchCompleteItem(
						(IContributorHandle) value, IItemManager.DEFAULT,
						getMonitor());
		return contributor.getName();
	}
	throw new WorkItemCommandLineException(
			"Convert Contributor - Incompatible Type Exception: "
					+ value.toString());
}

Timestamps

Timestamps  are stored as java.sql.Timestamp. The code below shows how to get the data.

/**
 * Compute the string representation for a timestamp
 * 
 * 
 * @param value
 * @return
 */
private String calculateTimestampAsString(Object value) {
	if (value != null) {
		if (value instanceof Timestamp) {
			Timestamp timestamp = (Timestamp) value;
			return SimpleDateFormatUtil.getDate(timestamp,
					getSimpleDateTimeFormatPattern());
		}
		throw new WorkItemCommandLineException(
				"Convert timestamp - Incompatible Type Exception: "
						+ value.toString());
	}
	return CONSTANT_NO_VALUE;
}

The class com.ibm.js.team.workitem.commandline.utils.SimpleDateFormatUtil is part of the WorkItem Command Line and uses java.text.SimpleDateFormat to convert the value to a string.

Durations

Durations such as “Time Spent” are stored as long. The code below converts the value.

/**
 * Compute the string representation for a duration
 * 
 * @param value
 * @param attribType
 * @return
 */
private String calculateDurationAsString(Object value, String attribType) {
	if (value != null) {
		if (value instanceof Long) {
			Long milliseconds = (Long) value;
			return SimpleDateFormatUtil.convertToTimeSpent(milliseconds);
		}
		throw new WorkItemCommandLineException(
				"Calculate Duration - Incompatible Type Exception: "
						+ value.toString());
	}
	return CONSTANT_NO_VALUE;
}

The class com.ibm.js.team.workitem.commandline.utils.SimpleDateFormatUtil is part of the WorkItem Command Line and uses java.text.SimpleDateFormat to convert the value to a string.

Iterations

Iterations are returned as IIterations. To resolve the iteration see the code below. The WorkItem Command Line contains the class com.ibm.js.team.workitem.commandline.helper.DevelopmentLineHelper to convert Iterations and Timelines to user readable text.

/**
 * Get the IIteration object from a handle
 * 
 * @param handle
 * @return
 * @throws TeamRepositoryException
 */
public IIteration resolveIteration(IIterationHandle handle)
		throws TeamRepositoryException {
	if (handle instanceof IIteration) {
		return (IIteration) handle;
	}
	IIteration iteration = (IIteration) fTeamRepository.itemManager()
			.fetchCompleteItem((IIterationHandle) handle,
					IItemManager.DEFAULT, fMonitor);
	return iteration;
}

Work Item State

To get the work item state see the code blow.

/**
 * Convert a work item state to a string
 * 
 * @param workItem
 * @return
 * @throws TeamRepositoryException
 */
private String calculateStateAsString(IWorkItem workItem)
		throws TeamRepositoryException {
	Identifier state = workItem.getState2();
	IWorkflowInfo wfInfo = getWorkItemCommon().findWorkflowInfo(workItem,getMonitor());
	String stateName = wfInfo.getStateName(state);
	if (stateName == null) {
		return "";
	}
	return stateName;
}

Subscriptions

Subscriptions is another pseudo attribute that really is a collection.

ISubscriptions subscriptions = workItem.getSubscriptions();
IContributorHandle[] contributors = subscriptions.getContents();
List subscribers = Arrays.asList(contributors);

Compute the contributors from the list as shown above. Also see Subscribing To a Work Item Using the Java API.

Approvals

Approvals is also a pseudo attribute and is accessed using a collection. The conversion is quite sophisticated as the approval information is composed of several descriptors and approval records. Please see the WorkItem Command Line and the ExportWorkItemsCommand.calculateApprovalsAsString(IWorkItem) for the code.

Also see Adding Approvals to Work Items Using the Plain Java Client Libraries.

Deliverable

The work item attribute “Found In” requires a so called deliverable

com.ibm.team.workitem.common.model.IDeliverableHandle
com.ibm.team.workitem.common.model.IDeliverable

Methods to find and create deliverables can be found using the common library

com.ibm.team.workitem.common.IWorkItemCommon

See the Workitem Command Line especially the WorkItemUpdateHelper and the WorkItemExportHelper for methods containing Deliverables.

Other Attribute Types or Pseudo Attributes

Please see the WorkItem Command Line especially the class ExportWorkItemsCommand for how to access the values. Also see

List Attributes

Work Item Attributes have a type for example smallString, mediumString, myCustomEnumeration and many more. Since RTC 4.x it is possible to have attributes defined that can contain a list of attribute values. The attributes are defined by picking the attribute type with the post-fix list in the attribute type selection for example string list, myCustomEnumeration list, Work Item list, Team Area list etc.

Basically the returned object for attribute types is a list object an instance of:

List

to get at the contained values, cast to a list. Then iterate the list and work on the returned object.

/**
 * Compute the string representation for a string list object
 * 
 * @param value
 * @return
 */
private String calculateStringListAsString(Object value) {
	if (value == null) {
		return CONSTANT_NO_VALUE;
	}
	List resultList = new ArrayList();
	if (value instanceof List) {
		List items = (List) value;
		for (Object object : items) {
			resultList.add(calculateString(object));
		}
	}
	return StringUtil.listToString(resultList, SEPERATOR_NEWLINE);
}

For the objects returned cast them to the correct instance and then use the values as fits. Her an example for a string type.

/**
 * Compute the string representation for a string object
 * 
 * @param value
 * @return
 */
private String calculateString(Object value) {
	if (value != null) {
		if (value instanceof String) {
			return (String) value;
		}
		throw new WorkItemCommandLineException(
				"Convert string - Incompatible Type Exception: "
						+ value.toString());
	}
	return CONSTANT_NO_VALUE;
}

See the WorkItem Command Line and ExportWorkItemsCommand.getStringRepresentation(IWorkItem, ParameterValue) for how to analyze the attribute types and call the conversions.

Set the Work Item Attribute

Very similar to getting the work item Attribute, you can set the value of an attribute. You need to have a WorkItemWorkingCopy of the work item to be able to set an work item attribute value. See the Jazz Team Wiki or for example this post for how to retrieve a working copy. This post shows some of the code for the server. The code below shows this for a custom integer attribute. First it checks if the work item attribute is available and then sets the value. The IWorkItem.setValue() method assumes it is able to cast the value in order to be able to set it. You need to provide a value of a matching type to set the attribute.

IWorkItem workItem = IWorkItem workItem = workingCopy.getWorkItem();
Integer value = new Integer("4");
if (workItem.hasCustomAttribute(customInteger))
	workItem.setValue(customInteger, value);
}

The various types that can be set are explained above. The data has to be provided as retrieved above. Typical types are String, Integer, Long, BigDecimal, enumerations, Timestamps.

For List attributes you have to construct a list of attributes and set the list. e.g. A very simple example would be for a custom enumeration. Construct a list of attribute values (e.g. the Identifier for the enumeration literal) and use the list to set the values:

List values = new ArrayList();
values.add(getLiteralEqualsString("foo", customEnumerationList));
values.add(getLiteralEqualsString("bar", customEnumerationList));
workItem.setValue(customEnumerationList,values);

With getLiteralEqualsString returning the enumeration value identifier as explained in Manipulating Work Item Enumeration Values.

private static Identifier getLiteralEqualsString(String name, IAttributeHandle ia) throws TeamRepositoryException {
.
.
.
}

See the work item commandline especially the WorkItemUpdateHelper for methods ending with List for example:

com.ibm.js.team.workitem.commandline.helper.WorkItemUpdateHelper.calculateEnumerationLiteralList(ParameterValue, List)

ClassCast Exceptions

Regardless whether you read a value or write a value, you usually can’t just use the value. As described in Understanding and Using the RTC Java Client API you need to cast the object you get to something you can use. A String, an Int, an enumeration literal, or for more complex itens to an ItemHandle and resolve the handle to be able to access the data.If you want to set a value, you have to make sure that the Object you pass conforms to the attribute type as well.If your data does not conform to the value that is returned or expected, your code will throw a ClassCastException.My experience so far is, that such exceptions usually were my fault and not the fault of the API. So in case of exceptions first look at your code before posting the API is broken in the forum.

Examples for setting work item attributes

The Work Item Command Line has examples for a complete set of work item attribute types. The class   com.ibm.js.team.workitem.commandline.helper.WorkItemUpdateHelper provides examples for how to find the work item attributes from an ID, get the attribute type and set a value from a string representation. The entry points are

  • com.ibm.js.team.workitem.commandline.helper.WorkItemUpdateHelper.updateProperty() – the method tries to find the attribute and calculate the attribute type
  • com.ibm.js.team.workitem.commandline.helper.WorkItemUpdateHelper.getRepresentation() – the method takes the calculated attribute type IAttribute and the string representation and tries to get an object that represents the value in the repository; the code tries to find a contributor from the ID, tries to find an iteration or a category from a text description.

Various methods with the prefix calculate, find, get, create, update are provided that do the work to convert or lookup the data.

Related posts for setting attributes

Saving the work item

As described in Understanding and Using the RTC Java Client API you can not just do a setValue() and expect the work item to change. You need a WorkItemWorkingCopy to actually change the value. The best way to do this in the client API is described in Understanding and Using the RTC Java Client API. Use a WorkItemOperation to wrap your code. This post has examples for how to work in the server API.

Summary

This is a short overview about the basics you need to know to access and modify work item attribute values. Other posts in this blog and several other examples on Jazz.net and IBM Developerworks provide more information on the API.

Related Posts

43 thoughts on “Working with Work Item Attributes

  1. what about if I need to add a comment at “Discussion”? … I couldn’t find it at the retrieved attributes list !

  2. When I tried to set the new comment,everything goes right
    However,when I open my work item to find the updates,nothing is added!
    Any ideas !!

    IComments comments=workItem.getWorkItem().getComments();
    IAttribute commentsAttr = service.findAttribute(projectArea, “internalComments”, monitor);
    List commentList=new ArrayList();
    commentList.add(comments.getContents()[0]);//POC commentList.add(comments.getContents()[0]);
    workItem.getWorkItem().setValue(commentsAttr, commentList);

    • Jayesh,

      I think the would be a better place to ask this question.
      I have looked and I don’t see the team area as an attribute that can be displayed in the Web UI. You can only display the category which selects that team. You might want to consider to open an enhancement request.

  3. Hi Ralph,
    Thanks for all these interesting and useful articles.
    I am working around an issue that I can not understand/fiox over Custom attributes:
    * I created new attribute from RTC Web interface, into Work Items > Types and Attributes and I can see it (I added it to different Work Item Types) in attribute list as a Custom Attribute
    * From Java API, I can not get/set any value for this attribute: workitem.getCustomAttributes() returns an empty List. Then I can not reach this attribute from workItem (false returned by hasAttribute/hasCustomAttribute).
    * But, still from Java API, if I list the attributes available in my project Area, I can see it.
    Did I miss something?
    Thanks for your help

    • Hi Cris, I can only guess that you have not yet synchronized the attribute. A custom attribute is not automatically available on work items, that have been created before the attribute was there. You have to synchronize the attributes.

      I suspect if you create a new work item and run against that you can get the attribute and
      if (workItem.hasAttribute(iAttribute)) {
      Object value = workItem.getValue(iAttribute);
      }
      or
      if (workItem.hasCustomAttribute(customInteger))
      workItem.getValue(customInteger, value);
      }
      would reach the getValue.

      https://rsjazz.wordpress.com/2012/11/19/using-an-expression-to-synchronize-attributes-for-work-items-of-a-specific-type/ has some pointers how you can synchronize the attributes.

      If you can find the IAttribute for your custom attribute, you can also use

      workItem.addCustomAttribute(customString);

      to add the attribute. However, I think you should synchronize your attributes.

  4. Hi Ralph,
    can you help me to develope a script to Read-Only Attributes For Condition like attributes as Summary,Type,Priority should be read only when I update the Attribute responsibility to value ‘customer’

    • Hi Jerome, please see https://jazz.net/library/article/1093 Lab 5 (and Lab3,4) for how to do this. Also see https://jazz.net/library/article/997.

      This should be easy enough to do and it does not require the Java API at all. Just JavaScript. If you read the Process Enactment Workshop, Lab 5, you should have what is needed. All you need to do is read the value of the ‘responsibility’ attribute (workItem.getValue(“the.attribute.id”)) and return true if the value matches the ID of the enumeration for ‘customer’, false otherwise.

      • Hi Ralph,
        I’m developming a follow-up action (Operation Participant) to be plugged in into RTC, how do I set an attribute to read-only using Java API? The idea is: my follow-up action will check for conditions, set read-only & then perform actions. Since I’ve already had my development using Java API, I don’t want to configure/develop another script for that.

      • Hi Minh,

        unfortunately I was not able to figure out how to do this.

        As far as I know all this information is stored in the process configuration and it appears you have to change that and save it.

        There does not seem to be a dedicated Java API for this.

      • Hi Ralph,

        After a while, I figured out that I’ll only need to change the presentation properties of my attribute so that the user will not able to edit the value of the attribute in the specific presentation. Is there Java API for editing workitem editor presentation? If yes, it would be perfect if you can provide me some sample code. Thanks.

      • I am not aware of a Java API for that purpose. I would naively assume this is done in the process XML. I have no examples for this. Sorry.

  5. Hi,
    I tried using the custom profile as you have mentioned, below is my same code line for loadProfile
    ItemProfile loadProfile = IWorkItem.SMALL_PROFILE.createExtension(Arrays.asList(new String[] {IWorkItem.CUSTOM_ATTRIBUTES_PROPERTY}));
    But still I am getting NULL value for the customer Attribute Appliance ID
    IAttribute someAttribute= workItemClient.findAttribute(iProjectArea, “sdi.workitem.attribute.ApplianceID”, monitor);
    Object value = “”;
    if(iWorkItem.hasAttribute(someAttribute)){
    value=iWorkItem.getValue(someAttribute);
    }

    • The way that property is used in the code look like:

      ItemProfile CUSTOM_ATTRIBUTE_PROFILE= ItemProfile.createProfile(IWorkItem.ITEM_TYPE, IWorkItem.CUSTOM_ATTRIBUTE_PROPERTIES);

      It is a good idea to search the SDK to find out how specific parts are used.

      • By the way, I think IWorkItem.CUSTOM_ATTRIBUTES_PROPERTY is supposed to load all custom properties. If you just want one specific, I’d try to provide the ID as string.

  6. Hi Ralph,

    Thank you very much for this article and many others.

    I’m working on an application with Support RTC Staging Area. I’ve got few attributes that I needed. I’m looking to find PMR & related fields for each RTC ticket. Is there a data definition document or link that shows where each attribute is and the handle that’s needed to access it?

  7. Hi Ralph,

    Can you teach me how I can add a subscriber with his UserID or his Name? (I can do this with the itemid of the Contribuitor, but I can’t do it with the UserID). Obviously with a participant extension

    • The pattern is always the same and has been explained several times here. You basically need to get the IContributorHandle. This can be done with the IContributorManager. If you have the ID as string you can look up the handle using fetchContributorByUserId. Examples how to get the ContributorManager in the client API can be found in https://rsjazz.wordpress.com/2012/08/02/subscribing-to-a-work-item-using-the-java-api/ that also talks about how to subscribe them. It also talks about getting the IContributorService, which is the server side API for the contributor management.

      I don’t have code to look up the users by their name.

  8. Hi Ralph, my application can successfully read the category attribute. But after I renamed the category I still get the old value in the API from the getValue() method. It looks as if the primary name is used as a key and is kept forever. How can I retrieve the new value as the web ui can do?

  9. Hi Ralph,

    i am working with WorkItem extensions. And when i traverse with particular ID, i am able to get the value of the ID, type of the work Item and also creationDate. But have issues getting the contents of the comments, ModifiedBy, owner –> These are returning objects rather than value.

    System.out.println(projectArea.getName() + ” getComments –>”+workitem.getComments());

    IComments commentsValue = workitem.getComments();
    System.out.println(projectArea.getName() + “IComments commentsValue –>”+commentsValue);

    For eg: In above code both returns below

    getComments –>com.ibm.team.workitem.common.internal.model.Comments@3302035b
    IComments commentsValue –>com.ibm.team.workitem.common.internal.model.Comments@3302035b

    But i need the value. How could i get this?

    • As mentioned in the post, you always get an object back. For simple objects such as Integer or String, you get the value easily. You basically cast to the object type and can use that.

      For more complex types you get a handle that you need to resolve.

      For a pretty complete set of examples see the Work Item Command Line code (download here) https://rsjazz.wordpress.com/2016/10/25/the-rtc-work-item-command-line-on-bluemix/

      and look at the classes com.ibm.js.team.workitem.commandline.helper.WorkItemHelper

      /com.ibm.js.team.workitem.commandline/src/com/ibm/js/team/workitem/commandline/commands/ExportWorkItemsCommand.java and /com.ibm.js.team.workitem.commandline/src/com/ibm/js/team/workitem/commandline/commands/ImportWorkItemsCommand.java

  10. Hello Ralph,
    I have added some custom attributes to a workitem type like:
    1. Country : A drop down with some country code (USA, AUS etc a long list of countries )
    2. System: A drop down ( Test, Production)
    and I am able to iterate over them using the below code:

    List custAttribs = workitem.getCustomAttributes();
    for (Iterator iterator = custAttribs.iterator(); iterator.hasNext();) {
    IAttributeHandle iAttributeHandle = iterator.next();
    IAttribute iAttribute = (IAttribute) teamRepository.itemManager().fetchCompleteItem(iAttributeHandle, IItemManager.DEFAULT, null);
    if (workitem.hasCustomAttribute(iAttribute)) {
    Object value = workitem.getValue(iAttribute);
    if (value != null && value instanceof String) {
    String sValue = (String) value;
    System.out.print(“\tValue: ” + sValue);
    }
    }

    The problem which I am facing is how to get the values which are selected by the user like for Country if someone saves AUS, then the code can fetch me a string with AUS,

    Thanks

  11. Hello,

    Currently I use the following snippet to get the IAttribute of a particular attribute.

    List customAttributes = workitem.getCustomAttributes();
    for (IAttributeHandle attributeHandle : customAttributes)
    {
    IAttribute attribute = (IAttribute) repository.itemManager()
    .fetchCompleteItem(attributeHandle, IItemManager.DEFAULT, monitor);
    if (attribute.getIdentifier().equalsIgnoreCase(Constants.SUBJECTS))
    {
    //Actual logic
    }
    }

    Isn’t there a way where I can pass the id of the custom attribute and get the attribute handle or attribute directly instead of having to iterate through the entire list of custom attributes and comparing against the attribute id?

    • As explained in this post in section Getting the Work Item’s Attributes in the API, you can use IWorkItemCommon.findAttribute() to look up the attribute based on its ID.

Leave a reply to rsjazz Cancel reply

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