Deploying Templates and Creating Projects Using the Plain Java Clients Library


How can the Rational Team Concert Extensions workshop be changed to be easier to use with newer versions of Rational Team Concert?

This is a question that I was contemplating about since I picked up the maintenance of the workshop. The issue with the workshop is the requirement to import database content using the repotools.

Why is that step required? The main reason is, that the workshop provides a project with SCM data that you use to perform the various labs. It also provides the Launch files needed for launching the Jetty server and the Eclipse clients.  This avoids a lot of work in typing source code and importing projects.

However, it causes a lot of issues.

  •  This used to work with various versions of RTC in the past but since 4.0 it seems to be tied to the version that was used to export the databases. So in order to run the workshop with a newer versions, it is neccessary to set it up with the RTC version it was created with and then upgrade the repository to the desired version.
  • By importing the repository, the public URI is set.
  • When setting the repository up, it is necessary to decide which applications to set up and register. If using a different install method and not installing all applications the JTS will show broken application registrations.
  • It is necessary to run a custom setup, due to the usage of the user ID ADMIN

There are some other issues with this approach that add unnecessary complexity to a workshop that is already challenging enough (for example the usage of user ADMIN and how to provide that user with a license). These can hopefully be addressed somehow.

Solution Approach

The only feasible approach that I could come up with was to provide some automation to perform the steps I have to do to set up the repository to export it for a new workshop version. The automation would run against a RTC Server that has a finalized set up of any kind (Express or Custom) with or without existing projects, create and provide the required data.

The minimal set of steps required would be to:

  1. Deploy the required Template for a Project Area, if it is not already deployed.
  2. Create the required Project Area for the Extension Workshop.
  3. Set the required User Membership and Roles for the Project Area.
  4. Set up the required Stream, Components and the Repository workspace
  5. Share the SCM Data to the Components, deliver it to the Stream and create the required Baselines. This needs to be done multiple times for the workshop code adding new files and modifying files that already exist.
  6. Set the repository workspace components to the baselines needed to start the workshop.

Recently I found some time to explore how this can be achieved. I made considerable process and I think there is a solution to this challenge that I might be able to publish. While I will try to find time to finalize the work and get approval to publish the results, I wanted to publish some of the lessons learned from trying to create the solution.

The solution is described in:

  1. This post
  2. Managing Workspaces, Streams and Components using the Plain Java Client Libraries
  3. Delivering Change Sets and Baselines to a Stream Using the Plain Java Client Libraries
  4. Extracting an Archive Into Jazz SCM Using the Plain Java Client Libraries

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.

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.

Preparing the Project

This post will show how the required project can be created. Some of the code used here is from Snippet 3 of the plain Java Client Libraries and from code already published in this blog. The code that follows is wrapped into the code I usually use for my Plain Java Client Library examples, derived from the Programmatic Work Item Creation Wiki entry and the Plain Java Client Libraries Snippets.

The main() method starts the Team Platform, creates the new class object and passes the arguments on to perform the work. I have discussed what this code does so often in other posts, please refer to them if you have questions.

public static void main(String[] args) throws Exception {
	boolean result;
	System.out.println("Starting Team Platform");
	if (!TeamPlatform.isStarted())
		TeamPlatform.startup();
	try {
		System.out.println("Team Platform started");
		ServerSetup setupExtDevServer = new ServerSetup();
		result = setupExtDevServer.run(args);
	} catch (TeamRepositoryException x) {
		x.printStackTrace();
		result = false;
	} finally {
		TeamPlatform.shutdown();
	}
	if (!result)
		System.exit(1);
}

In the run() method the work to do is coordinated and performed. The method checks if the required parameters are available. Then it logs into the repository with the given user name and password. This code is presented at the end of this post, as it is just refactored out and is simply the code I am always using in this blog. The user has to have the JazzAdmin repository role.

In the next step the automation deploys the required process template. It then tries to find if the project area exists and creates a new one if not. It adds the required user with role to the project area. The following steps will be explained in later posts.

private boolean run(String[] args) throws Exception {
	if (args.length != 3) {
		System.out.println("Usage: ServerSetup repositoryURI userId password");
		return false;
	}

	String repositoryURI = args[0];
	String userId = args[1];
	String password = args[2];

	IProgressMonitor monitor = new NullProgressMonitor();
	ITeamRepository teamRepository = logIntoTeamRepository(repositoryURI,
				userId, password, monitor);

	IProcessDefinition scrumProcess = findOrDeployTemplate(teamRepository,
				"scrum2.process.ibm.com", monitor);
	IProjectArea area = findOrCreateProjectArea(teamRepository,
				"RTC Extension Workshop", scrumProcess, monitor);
	addUsersAndRoles(teamRepository, area, monitor);
.
.
.
.
.

In the deployTempate() method the automation tries to find the required process template and tries to deploy it, if it was not already deployed.

private IProcessDefinition findOrDeployTemplate(ITeamRepository teamRepository,
		String processID, IProgressMonitor monitor)
		throws TeamRepositoryException {
	System.out.println("Trying to find or deploy template: " + processID);
	IProcessItemService service = (IProcessItemService) teamRepository
				.getClientLibrary(IProcessItemService.class);
	IProcessDefinition[] definitions = null;
	// Find the process definition
	IProcessDefinition processDefinition = processItemService
			.findProcessDefinition(processID, null, monitor);
	if (processDefinition == null) {
		// Create the definition if it does not exist.
		definitions = processItemService
				.deployPredefinedProcessDefinitions(
						new String[] { processID }, monitor);
		System.out.println("Template deployed...");
		if (definitions.length != 0) {
			processDefinition = definitions[0];
		} else {
			throw new TeamRepositoryException("Process template "
					+ processID + " does not exist.");
		}
	}
	System.out.println("Template found...");
	return processDefinition;
}

The main task is now to find the project area if it exists and to create a new project area in case it is not available.

private IProjectArea findOrCreateProjectArea(
		ITeamRepository teamRepository, String projectName,
		IProcessDefinition processDefinition, IProgressMonitor monitor)
		throws TeamRepositoryException {

	// Create Project Area based on Scrum
	System.out.println("Trying to find or create Project Area: " + projectName);

	IProcessItemService service = (IProcessItemService) teamRepository
				.getClientLibrary(IProcessItemService.class);
	IProjectArea area = null;
	List areas = service.findAllProjectAreas(
			IProcessClientService.ALL_PROPERTIES, monitor);
	for (Object anArea : areas) {
		if (anArea instanceof IProjectArea) {
			IProjectArea foundArea = (IProjectArea) anArea;
			if (foundArea.getName().equals(projectName)) {
				area = foundArea;
				System.out.println("Project Area found: " + projectName);
				return area;
			}
		}
	}

	// Could not find the the project area, create one
	if (area == null) {
		System.out.println("Trying to create Project Area: " + projectName);
		area = service.createProjectArea();
		area.setName(projectName);
		area.setProcessDefinition(processDefinition);
		IDescription description = area.getDescription();
		description.setSummary("Project to be used running the RTC Extension Workshop");
		area = (IProjectArea) service.save(area, monitor);
		area = (IProjectArea) service.getMutableCopy(area);
		service.initialize(area, monitor);
		System.out.println("Created and initialized Project Area: " + projectName);
	}
	return area;
}

Now that the project area is available make sure to add the required user with role ID “ScrumMaster”. The method addUsersAndRoles() does this.It first tries to find the role. Once found it adds the currently logged in user, the user that runs this automation, to the administrators section of the project and to the members section with the role obtained.

private IProjectArea addUsersAndRoles(ITeamRepository teamRepository,
		IProjectArea area, IProgressMonitor monitor)
		throws TeamRepositoryException {

	IProcessItemService service = (IProcessItemService) teamRepository
				.getClientLibrary(IProcessItemService.class);
	area = (IProjectArea) service.getMutableCopy(area);
	System.out.println("Trying to add members with roles: "
			+ "ScrumMaster" + " to Project Area" + area.getName());

	// IProjectArea wArea = (IProjectArea)service.getMutableCopy(area);
	IContributor member = teamRepository.loggedInContributor();

	IRole role = getRole(area, "ScrumMaster", monitor);
	area.addAdministrator(member);
	area.addMember(member);
	area.addRoleAssignments(member, new IRole[] { role });
	IProcessItem[] items = service.save(new IProcessItem[] { area },
				monitor);
	System.out.println("Users with Roles added to " + area.getName());
	return area;
}

To get the role the getRole() method tries to discover the roles in the process that have a matching ID and returns it, if it was found. Please note that IRole objects have no access to the role name. they have just the ID. If you need the role name you need to get the IRole2 interface from the IRole object. The code that does this is commented out below.

	private IRole getRole(IProcessArea area, String roleID,
			IProgressMonitor monitor) throws TeamRepositoryException {
		ITeamRepository repo = (ITeamRepository) area.getOrigin();
		IProcessItemService service = (IProcessItemService) repo
				.getClientLibrary(IProcessItemService.class);
		IClientProcess clientProcess = service.getClientProcess(area, monitor);
		IRole[] availableRoles = clientProcess.getRoles(area, monitor);
		for (int i = 0; i < availableRoles.length; i++) {
			IRole role = availableRoles[i];
			// IRole2 role2 = (IRole2)role;
			// role2.getRoleName();
			if (role.getId().equalsIgnoreCase(roleID))
				return role;
		}
		throw new IllegalArgumentException("Couldn't find roles");
	}

The code left out is for logging into the repository, for completeness it is presented below.

private ITeamRepository logIntoTeamRepository(String repositoryURI,
		String userId, String password, IProgressMonitor monitor)
		throws TeamRepositoryException {
	System.out.println("Trying to log into repository: " + repositoryURI);
	ITeamRepository teamRepository = TeamPlatform
		.getTeamRepositoryService().getTeamRepository(repositoryURI);
	teamRepository.registerLoginHandler(new LoginHandler(userId, password));
	teamRepository.login(monitor);
	System.out.println("Login succeeded.");
	return teamRepository;
}

/**
 * Login Handler implementation
 *
 */
private static class LoginHandler implements ILoginHandler, ILoginInfo {

	private String fUserId;
	private String fPassword;

	private LoginHandler(String userId, String password) {
		fUserId = userId;
		fPassword = password;
	}

	public String getUserId() {
		return fUserId;
	}

	public String getPassword() {
		return fPassword;
	}

	public ILoginInfo challenge(ITeamRepository repository) {
		return this;
	}
}

Summary

The code in this post basically shows how to prepare a project for later usage. It does the steps requires such as deploying a process template in case it is not yet available. It finds or creates the project area and it makes sure to add the user required as administrator and member with the required role.

Now that the project is prepared, the next steps will be all the required preparation in the Projects SCM to be able to upload the code. This is going to be presented in a later post.

As always, I hope that sharing this code helps users out there, with a need to use the API’s to do their work more efficient.

Advertisements

About rsjazz

Hi, my name is Ralph. I work for IBM and help colleagues and customers with adopting the Jazz technologies.
This entry was posted in Jazz, RTC, RTC Automation, RTC Process Customization and tagged , , , , . Bookmark the permalink.

13 Responses to Deploying Templates and Creating Projects Using the Plain Java Clients Library

  1. Surender says:

    Hi Ralph,

    I`m Surender , working as a software engineer.
    I`m Developing a RTC plugin which needs to set the current iteration for the work item.
    I know we can do this when we are saving the work item for the first time but my requiremnt is to populate that field with current iteration at the time the user opens the new work item creation dialog. please let me know if this is possible.

    sorry if this was not the right thread to post this question.

    Thanks
    Surender

    • rsjazz says:

      You can set the iteration and there are several posts on this blog that you can look into for more information. you can use the search field on the top right. https://rsjazz.wordpress.com/2012/10/05/handling-iterations-automation-for-the-planned-for-attribute/ is one of them.

      You would have to identify the iteration as current, which I have no code for right now. And you will have to use the ‘Planned For’ attribute. You might have to set the filed against also.

      It is not clear to me what you try to achieve.

      • Surender says:

        Thanks for quick reply , My question is

        When I click on new work item and select a Story and click on ok then it takes us to a new window where we provide appropriate values and then we save the work item. I have an attribute “Iteration planned” for which I want to set the current iteration before saving or creating the work item.

        Thanks
        Surender

      • rsjazz says:

        You still explain what you think the implementation should look like, not what you want to achieve and why.

        I am not sure how you could extend that menu actions. Also, on what basis would you choose the current iteration? The work item first needs a category (filed against) and the current iteration would have to be set for the iteration in the timeline the team is selected by the category. You could use a calculated value provider, may be, if you can find rules for the calculation of the iteration. But calculated value attributes should be read only. Search for ‘provider’ to find the article about provider.

        I think I would use a side follow up action to set the iteration, just because that would work with all UI’s and only needs to be installed in the server.

        You can not set any values before creating the work item.

  2. Surender says:

    Is this possible Ralph,
    if so could you please guide the right way to do it.
    Basically Im confused with API I mean which code needs to be reffered and in the link you mentined above it seems like astandalone application.

    Thanks
    Surender

  3. Hi Ralph,
    I would need to create ~2000 project areas but in RQM. Do you know if this API also works for RQM?

  4. geetha says:

    Hi,
    When we tried to deploy an existing template with existing project area, update of process template was not happened.
    Does deployTempate() does not deploy to the Project Area which is already created with other process template.

  5. Nishant says:

    Hi,
    How to create project using the process configuration from another project area in plain java code.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s