Eclipse or SUNrise...

Eclipse or SUNrise...
...JAVA for sure

Monday, March 28, 2011

Integrating with Rational Team Concert

In this post I'll show you an example of automation of tasks with Rational Team Concert using Java. Couple of days ago I was asked to "somehow" automate a process of generating and publishing a bunch of reports to RTC. The process contained couple of steps - first a cron job which fired a PL/SQL procedure which generated a proper report, then it had to be processed, zipped and uploaded to an existing RTC custom item called report (similar to a task).

So lets focus on the interesting part - integration with RTC. Because RTC gives an JAZZ API I decided to upload the files using a simple, JAVA SE application. Unfortunately as I found out on the JAZZ official pages there was very little information about the API. Yes, there were couple of examples, but no real documentation or at least a proper Javadoc... I found some helpful info on the Internet but again, it still is not a rich source of documentation for this.

Oh, and to gain access to this so called documentation you have to register on JAZZ pages. Although you won't find a complete and proper documentation there, you will have an access to a few handy examples and a forum. At the end of this article, you can see a list of useful links.

To run the application, you'll need the client libraries to be able to connect to the RTC. I downloaded a JazzPlainJavaClient-2.0 package. It is more then 20MB of jars, but you don't require all of them to create your application. You can download it here. Look for 'Plain Java Client Libraries'. There is a lot more to download, but if you plan to develop something small don't really bother with anything else.

Now when you have your copy of libraries wire them to your project and you can run my code.

The following code is just a main body, which initialize the libraries and executes the real logic of the program - the run() function passing it all the attributes. You will find a very similar code on the examples on jazz pages.


public static void main(String[] args) {

boolean result;
TeamPlatform.startup();
try {
result = run(args);
} catch (TeamRepositoryException x) {
x.printStackTrace();
result = false;
} finally {
TeamPlatform.shutdown();
}

if (!result)
System.exit(1);

}


The run() function simply parse the arguments - there should be 6 of them and one of them should be integer. Of course you can improve the parsing, my is just as good as it have to be. Then, if they are are ok, the program authenticates provided user in the RTC repository (so be sure you gave a proper user with a valid password).

Then it looks for a project area to connect to (it will be needed to upload the attachment, note also that your user must have access there). If the program will find it, it searches for a given item (for which it will upload the report).

Now the interesting part - using WorkItemWorkingCopy object to get the item data - the one that we really want is the the item reference, which we pass later to upload the attachment (itemCopy.getReferences()). Generally we can use it also to update the task itself - for example to add additional comment or change the priority.

Now we invoke the addAttachment() function passing it the stream to a file that we want to upload, its name visible in RTC, RTC item reference to which we will attach the file, the client binding that we will use to persist the attachment and finally the RTC project area.


private static boolean run(String[] args) throws TeamRepositoryException {

if (args.length != 6) {
System.out
.println("Usage: UpdateWorkItem ");
return false;
}

int rtcDocumentId = -1; // 6666

if (args[0] != null && args[0].length() > 0) {

try {
rtcDocumentId = Integer.valueOf(args[0]);
} catch (NumberFormatException nfe) {
System.out.println("The workitem id have to be a valid number");
return false;
}
}

SimpleDateFormat dateFormat = new SimpleDateFormat("M/dd/yyyy hh:mm");
System.out.println("Starting program at " + dateFormat.format(new Date(System.currentTimeMillis())));

final String repositoryURI = args[1];
final String userId = args[2];
final String password = args[3];
final String projectAreaName = args[4];
final String fileName = args[5];

// loging in to the RTC
ITeamRepository teamRepository = TeamPlatform.getTeamRepositoryService().getTeamRepository(repositoryURI);
teamRepository.registerLoginHandler(new LoginHandler(userId, password));
teamRepository.login(null);

URI uri = URI.create(projectAreaName.replaceAll(" ", "%20"));
IProcessClientService processClient = (IProcessClientService) teamRepository
.getClientLibrary(IProcessClientService.class);
IProjectArea projectArea = (IProjectArea) processClient.findProcessArea(uri, null, null);
if (projectArea == null) {
System.out.println("Project area not found, check if you gave the right name");
return false;
}

System.out.println("Querying workitems with id " + rtcDocumentId);

IWorkItemClient workItemClient = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
IWorkItemWorkingCopyManager copyManager = workItemClient.getWorkItemWorkingCopyManager();
IWorkItemHandle handle = workItemClient.findWorkItemById(rtcDocumentId, IWorkItem.FULL_PROFILE, null);
try {
copyManager.connect(handle, IWorkItem.FULL_PROFILE, null);
WorkItemWorkingCopy itemCopy = copyManager.getWorkingCopy(handle);
IWorkItem item = itemCopy.getWorkItem();

System.out.println("Found work item: " + item.getHTMLSummary());
System.out.println("Adding new attachment...");

InputStream fileInputStream = null;
try {
if (fileName != null)
fileInputStream = new FileInputStream(fileName);

InputStream inputStream = fileInputStream != null ? fileInputStream : System.in;

addAttachment(inputStream, fileName, itemCopy.getReferences(), workItemClient, projectArea);

} catch (FileNotFoundException e) {
System.out.println("###\n Error accured, file " + fileName + " not found\n###");
return false;
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
System.out.println("Couldn't close the fileInputStream, probably you can skip this error :-) ");
}
}
}

System.out.println("Commiting the new attachment to RTC workitem..");
itemCopy.save(null);
System.out.println("Attachement added succesfully!");

} finally {
copyManager.disconnect(handle);
}

System.out.println("Disconnecting from RTC...");
teamRepository.logout();
System.out.println("Disconnected! Finishing the program. Thanks for using!");

return true;
}


Finally the addAttachment function - it simply creates a new attachment and saves it. Notice that I used a text "UTF-8" as the coding for this file. Unfortunately, I haven't found much about this interface and with other parameter values it didn't worked - so I left it with UTF-8, maybe it isn't the best option, but it works pretty well. Again, more documentation would be nice...


private static void addAttachment(InputStream inputStream, String fileName, IWorkItemReferences workItemReferences,
IWorkItemClient workItemClient, IProjectArea projectArea) throws TeamRepositoryException {
try {

IAttachment newAttachment = workItemClient.createAttachment(projectArea, fileName, "", "text", "UTF-8",
inputStream, null);

newAttachment = (IAttachment) newAttachment.getWorkingCopy();
newAttachment = workItemClient.saveAttachment(newAttachment, null);
IItemReference reference = WorkItemLinkTypes.createAttachmentReference(newAttachment);
workItemReferences.add(WorkItemEndPoints.ATTACHMENT, reference);

} catch (Exception e) {
System.out.println("Exception while adding attachement: " + e.getMessage());
throw new TeamRepositoryException(e);
}
}


Now the last thing to do is to run the program - remember to pass it a proper set of arguments and link it with the client libraries. You can use the following command to run it:


java -Djava.ext.dirs="/usr/lib/JazzPlainJavaClient-2.0:/usr/jre1.6.0_24/lib/ext" -jar UpdateWorkItem.jar 6666 https://10.10.10.10:9443/jazz account@account.com password "MyProject" "/home/xxx/report_2011_03_20.zip" >> sendReportToRTC.log


And that's just enough to start playing with RTC. I just regret that they won't supply more documentation...

Here couple of handy links that I used:

https://jazz.net/wiki/bin/view/Main/QueryDevGuide
https://jazz.net/wiki/bin/view/Main/ProgrammaticWorkItemCreation
https://jazz.net/wiki/bin/view/Main/WorkItemExampleSource

2 comments:

Pugazhenthi samidurai said...

hi ,

i want to add workitem type attribute Like attachment or summary.

How to add this attribute value.

Sebastian Kapciak said...

I think this article about Work Item Customization will help you:

https://jazz.net/library/article/129