The RTC Work Item Command Line on Bluemix

I was talking to a customer recently. They are using the WorkItem Command Line for some automation purposes. Since this can trigger e-mail notifications to a huge amount of users they wanted to use the new Skip Mail save WorkItem Parameter introduced in RTC 6.0 iFix3.

I had the time and went ahead implementing it. The resulting source code is available on IBM Bluemix DevOps Services in the project Jazz In Flight

ibm-bluemix-devops-services-2016-10-24_17-55-35

Access the Source Code

License

The post contains published code, so 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. I found a section relevant to source code at the and of the license. Please also remember, as stated in the disclaimer, that this code comes with the usual lack of promise or guarantee. Enjoy!

RTC SCM Access

In the project you can access the source code of several extensions and automation I have created over the years. If you click Edit Code and you are not yet member of the project, you have to request access which I will allow.

The project contains a Stream called RTC Extensions with several components. One of the components is Work Item Command Line.

configure-eclipse-request-access-2016-10-24_18-13-14

To configure your RTC Eclipse client follow the instructions in the Configure eclipse client link. You can then create yourself a repository workspace and download the code. Please use the tracking and planning section (work items) if you want to do any changes to coordinate with me.

Changes

The current version uploaded there contains the capabilities described in A RTC WorkItem Command Line Version 3.0 plus a variety of bug fixes and a new switch /skipEmailNotification to disable work item update notification for the commands that modify work items such as

  • update
  • importworkitems
  • migrateattribute

The feature to suppress work item update notification is implemented in RTC 6.0 iFix3 where a new Skip Mail save WorkItem Parameter was introduced in RTC. When this additional save parameter is provided, the work item change does not trigger a work item change notification mail.The adoption in the WorkItem Command Line is done in a way that the implementation does not break the older API.  It introduces the additional save parameter value into the work item command line source code as new String constant instead of referencing the constant in the API. This way the WCL can be compiled with RTC Plain Java Client Library versions of RTC prior to 6.0 iFix3. If the WCL is run with versions earlier than 6.0 iFix3, e-mail notification is not suppressed. The behavior does not change in such versions of RTC and the additional save parameter is simply ignored.

Additional Download

You can also download the latest version 3.4 here:

Please note, there might be restrictions to access Dropbox and therefore the code in your company or download location.

Usage and install

Please see the posts A RTC WorkItem Command Line Version 3.0.

For the general setup follow the description in A RTC WorkItem Command Line Version 2.

For usage follow the description in A RTC WorkItem Command Line Version 2 and in A RTC WorkItem Command Line Version 2.1. Check the README.txt which is included in the downloads.

Summary

The work item command line is now available on IBM Bluemix Dev Ops Services and can be accessed and worked on there.

Advertisement

Work Item Command Line Client to Add a Comment

Yesterday I was asked to help a project that is incrementally migrating to Rational Team Concert with a small command line tool allowing to add comments to a work item. The team has switched to work items already and this tool is supposed to be used in some automation and called from another tool that is not yet replaced by RTC.

I had not yet worked with work item comments that much, except printing them and was interested in understanding how hard it would be to find the API involved. I made some nice experience doing so, which I would like to share.

Just Starting With Extending RTC?

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. The example shows client API.

License

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.

Operation to Add a Comment

As usual I decided to go with a WorkItemOperation to add the comment and update the work item. To do that, I created an inner class WorkItemAddComment extending WorkItemOperation. Well, to tell the truth, I grabbed the whole initial code from another example like published in Upload Attachments To Work Items.

Then I looked into implementing the execute method, that is called when the operation is performed. Since I did not have code other than printing comments, I first used IComments comments = workItem.getComments() to get the comments.

Now I needed to find the API to create an IComment. So I used search for references as described here to look at references where IComment was created. Surprisingly I found the interface IComments provides the createComment() method.I could have found it right away if I had looked. But the learning here is, if you set up your environment as described here and here, and follow the tips to search, you can easily find it. Not much brainpower needed here.

The createComment() method needs an IContributor object for the person that is named as creator of the comment and an XMLString for the comment itself. I decided to change the constructor of the operation to pass an IContributor and a String and store them in fields, to have them available in the execute() method.

Finally it is necessary to add the new comment to the comments retrieved from the work item. All the save and update mechanism is handled in the WorkItemOperation.

To be able to update the work item in the execute() method, the constructor also needs to pass a load profile to the superclass. I started with using the full profile but optimized it later to load with a custom load profile based on the small profile with the Comments property as extension.

The resulting code is shown below.

	private static class WorkItemAddComment extends WorkItemOperation {

		private String fComment;
		private IContributorHandle fCommenter;

		public WorkItemAddComment(IContributorHandle commenter, String comment) {
			super("Add Comment to Work Item", IWorkItem.SMALL_PROFILE.createExtension(Arrays.asList(new String[] { IWorkItem.COMMENTS_PROPERTY })));
			fComment = comment;
			fCommenter = commenter;
		}

		@Override
		protected void execute(WorkItemWorkingCopy workingCopy,
				IProgressMonitor monitor) throws TeamRepositoryException {
			IWorkItem workItem = workingCopy.getWorkItem();

			IComments comments = workItem.getComments();
			IComment newComment = comments.createComment(fCommenter,
					XMLString.createFromPlainText(fComment));
			comments.append(newComment);
		}
	}

Call the new Operation

The new operation takes two parameters in the constructor.

  • The IContributorHandle of the user to show as creator of the comment
  • A string that is the text in the comment

The operation gets called and executed like below.

	WorkItemAddComment operation = new WorkItemAddComment(commentUser,commentText);
	operation.run(workItem, monitor);
	System.out.println("Modified work item " + workItem.getId() + ".");

Get The Required Data

To call the code above, we need to get the user creating the comment and the work item to update. My final direction was, that I wanted to be able to just provide the repositoryURI, the credentials to log in, a work item ID and a comment string to be able to create the comment. In this scenario the user that runs the command line tool would be creator of the comment. As an enhancement I wanted to be able to pass the user ID of the creator of the comment.

The run method finally looks like this code:

private static boolean run(String[] args) throws TeamRepositoryException {
	boolean result = false;
	if (args.length  6) {
		System.out
				.println("Usage: AddComment      []");
		return result;
	}

	String repositoryURI = args[0];
	String userId = args[1];
	String password = args[2];
	String idString = args[3];
	String commentText = args[4];
	String commenterID = null;
	if (args.length == 6) {
		commenterID = args[5];
	}

	IProgressMonitor monitor = new NullProgressMonitor();
	ITeamRepository teamRepository = TeamPlatform
			.getTeamRepositoryService().getTeamRepository(repositoryURI);
	teamRepository.registerLoginHandler(new LoginHandler(userId, password));
	teamRepository.login(monitor);

	IContributor commentUser = null;
	if (null != commenterID) {
		try {
			commentUser = teamRepository.contributorManager().fetchContributorByUserId(
					commenterID, monitor);
		} catch (ItemNotFoundException e) {
		}
	}
	if (commentUser == null) {
		commentUser = teamRepository.loggedInContributor();
	}

	// Use IWorkItemClient or IWorkItemCommon
	IWorkItemCommon workItemCommon = (IWorkItemCommon) teamRepository
			.getClientLibrary(IWorkItemCommon.class);
	int id = new Integer(idString).intValue();
	IWorkItem workItem = workItemCommon.findWorkItemById(id,
			IWorkItem.SMALL_PROFILE, monitor);

	if(null!=workItem){
		WorkItemAddComment operation = new WorkItemAddComment(commentUser,
				commentText);
		operation.run(workItem, monitor);
		System.out.println("Modified work item " + workItem.getId() + ".");
		result=true;
			
	} else{
		System.out.println("Can not find work Item " + idString + ".");
	}
	teamRepository.logout();
	return result;
}

What it does, is checking and getting the parameters first.

The code then logs into the repository. If a second user ID is available for the commenter, the code tries to get the related contributor. If this fails the code falls back to the automation user ID by getting the IContributor logged in.

Then the code gets the IWorkItemCommon client library to find the work item by the ID passed in the call. If all succeeds the operation is called to update the work item and we are done.

The Rest of The Code

You can grab the rest of the code from Upload Attachments To Work Items. The code is also available in the Jazz In Flight project at JazzHub in the project com.ibm.js.team.workitem.automation.examples in the Extension Development Stream in the RTC PlainJava Automation component.  Once you have access you can get the code. You can also request to join the project and provide your own solutions there.

Calling The Code From The Command Line

The code can be called like below from the command line, provided JAVA_HOME is set and the Plain Java Client Libraries are installed in the second location and the code is compiled. The code below can be placed in a batch file which is called in the root of the eclipse project.

Set JAVA_HOME="C:\IBM\ibm-jdk\"
%JAVA_HOME%/jre/bin/java -Djava.ext.dirs=%JAVA_HOME%/jre/lib/ext;C:/RTC403Dev/installs/PlainJavaAPI -cp ./bin/ com.ibm.js.team.workitem.automation.examples.ModifyWorkItemAddCommentOperation "https://clm.example.com:9443/ccm" "ralph" "ralph" "54" "Add a comment"

See the README.TXT in the snippets folder of the Plain java Client Libraries for instructions for UNIX like operations systems.

Please Note: I had to explicitly point to the JRE, if the JDK did not provide an lib/ext folder.

Summary

As always I hope this code is useful to anyone. I also hope that the tips on searching the API helps others to explore the API as well. Please keep in mind, the code is not thoroughly tested and might need some polishing if you want to use it.