Using RTC Work Item Attributes to Display RTC Components and other Item Data

The RTC Work Item shall guide the user to the component, where the fix needs to be done. Is it possible to implement this requirement in RTC?

This was basically a requirement that I was asked for how to implement this with RTC. I also remember it being asked in the Jazz.net forum some time ago. I remember this, because my immediate thought was, this is only going to work using customization or extending RTC. I was quite surprised when a colleague monitoring the forum came up with a simple solution. I tried it out and it is really simple. However, it is quite hard to spot how this can be done. Therefore this post summarizes how you can easily do this yourself.

If you are just starting with customizing RTC Work Items, have a look at Process Enactment Workshop for the Rational solution for Collaborative Lifecycle Management 2012 especially Lab 3-5.

This was done with RTC 4.0.5 but it should work with earlier versions of RTC 4.x.

Create a New Attribute of Type Item

First you need to create a new attribute that will contain the information you want. There are a lot of attribute types you can choose from. There are special types that allow to select RTC Data such as users, team areas and the like. All these are for data related to the work item model. There is a special type for RTC data that is not work Item data from the RTC process model. It is easy to overlook. The type can be used as single selection or as a list. When creating the Attribute use

  • Item
  • ItemList

dependent upon your needs to select one or multiple elements.

Attribute Type Item
Attribute Type Item

If you select a ItemList, the work item UI supports selecting multiple items.

Configure the Editor Presentation

Once you have added the attribute, you need to configure the editor presentations to show the attribute as usual. You select

  • The Attribute
  • The Kind of the presentation

The available presentation kinds depend on the attribute type you selected. For the type ItemList, select Item List as kind.

Configure Editor PresentationFinally you can select which kinds of items the user can select. There are several choices that match types where RTC also provides a specialized attribute type, such as WorkItem or TeamArea.

The type Item or ItemList is more flexible and allows you to select any of these kinds and additional types that are not available in special attribute types such as SCM Component.

In the ItemList, you could have various objects that are interesting in this context. For example if you want to express what is affected by a work item.

You can select

  • Let the user choose
  • A specific item type

for the item type type be selectable in the presentation.

Save your changes, to make them available in the process.

Create a Work Item

Now you can create a new work item of the type you modified and select the new attribute. The presentation allows you to choose or add an element. The Select Component Dialog provides you with search and filter mechanisms to find what you need.

Select a ComponentSummary

You can use RTC work items to express relationships of a work item to other objects using special attribute types.

You can then use these new attributes and their values to drive new automation, e.g. check if a change set is actually for the component the related work item claims it to be. I shall see, if I can publish an article about such an advisor soon.

Advertisement

Delivering Change Sets and Baselines to a Stream Using the Plain Java Client Libraries

How does delivering change sets from a repository workspace work and how can I create baselines and deliver them?

This post shows some of the Client API used to do this kind of operations.

As described in the articles

  1. Deploying Templates and Creating Projects using the Plain Java Clients Library
  2. Managing Workspaces, Streams and Components using the Plain Java Client Libraries
  3. This post
  4. Extracting an Archive Into Jazz SCM Using the Plain Java Client Libraries

I want to automatically set up a project, manage the streams and components and seed the SCM system with SCM data.

The last posts show how to create and manage the project area and how to manage the components, streams and repository workspaces. What is left is to extract some kind of archive file and share the files with a component in a repository workspace using Jazz SCM. Then it is necessary to do some SCM operations on the repository workspace.

This post explains how the SCM operations on the repository workspace and stream work. Specifically, how to

  1. Deliver outgoing change sets from a repository workspace to a stream
  2. Baseline the state of a component, in the repository workspace
  3. Deliver the baseline to the stream
  4. Set a component of the repository workspace to a specific baseline

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.

Deliver Change Sets and Baselines

Continuing in the run method of Deploying Templates and Creating Projects using the Plain Java Clients Library we now want to extract some data from an archive file, add the code Jazz SCM and manage the changes and baselines.

This happens in the code below. The code only shows changes to one component. The same mechanism can be used for other components however and we grab the component we want from the map components we created in the last post.

As you can see the code below basically delegates the work to another method exctractToComponentBaseline(). For the first step it remembers the baseline that was created. It uses this baseline at the end, to set the current baseline for the component in the repository workspace to the first baseline created. This allows the user to load the repository workspace and begin with the first version of the projects. Later the user can accept incoming baselines, that are already delivered to the stream, to discover the code changes made for the next labs.

public static void main(String[] args) throws Exception {
.
.
.
.

	IBaselineConnection lab2Baseline = exctractToComponentBaseline(
			teamRepository, workspace, extensionStream,
			components.get("Component 2"),
			"./LabCode/Lab2Code.zip", "Share Projects - Lab 2 Code",
			"Lab 2 Code", "Lab 2 Code", monitor);

	exctractToComponentBaseline(teamRepository, workspace, extensionStream,
			components.get("Component 2"),
			"./LabCode/Lab3Code.zip", "Share Projects - Lab 3 Code",
			"Lab 3 Code", "Lab 3 Code", monitor);

	exctractToComponentBaseline(teamRepository, workspace, extensionStream,
			components.get("Component 2"), 
			"./LabCode/Lab4Code.zip", "Share Projects - Lab 4 Code",
			"Lab 4 Code", "Lab 4 Code", monitor);

	exctractToComponentBaseline(teamRepository, workspace, extensionStream,
			components.get("Component 2"),
			"./LabCode/Lab5Code.zip", "Share Projects - Lab 5 Code",
			"Lab 5 Code", "Lab 5 Code", monitor);

	setActiveBaseline(workspace,
			components.get("Component 2"),
			lab2Baseline, monitor);
	return result;
}

The interesting code is used in exctractToComponentBaseline() below. The first step is to extract an archive file into a component in the repository workspace. The extraction process creates a change set with all the folder and file creations and changes. How that works is going to be discussed in the final post of this series to keep the tension up, and because it is quite a lot of code.

The next lines of code look quite innocent, but I had a lot of trouble to get to the point that it was working for me.

In the first step after extracting the archive, the code uses the IWorkspaceConnection.compareTo() API to compare the repository workspace to the target stream. It uses the flag WorkspaceComparisonFlags.CHANGE_SET_COMPARISON_ONLY to only compare the change stets. The 3rd parameter could be used to exclude components on the workspace from the compare operation. This is not used in this example and an Collections.EMPTY_LIST is passed instead. The effort to create the exclusion list would increase the code complexity but does not really save that much time in this example. If this is used with a lot of components with a lot of files, it would be worth spending the effort.

The result of the compare operation is a IChangeHistorySyncReport which is used in the next step to deliver the change sets.

To deliver the changes the code uses the IWorkspaceConnection.deliver() API of the repository workspace. The call provides the deliver target stream, the IChangeHistorySyncReport from the compare, an empty list of baselines and the outgoing change sets from the IChangeHistorySyncReport.

This operation also adds the target stream (workspace connection) as a flow target. You can access the flow targets using IWorkspaceConnection.getFlowTable() and use this information to get a target in other scenarios.

The next step is to create a new baseline on the repository workspace. This is done using the IWorkspaceConnection.createBaseline() API call. This call can be used with exactly on component, which is what we want in this example. The name of the baseline and a comment for the baseline are also provided in the call.

If we wanted to create a snapshot IWorkspaceConnection.createBaselineSet() would have been the AI of our choice. This creates a baseline set across several components (and can exclude components).

The next steps are similar to the delivery of the change sets. First, do a compare() of the repository connection and the target, then do a deliver() with the change set sync report and the outgoing baselines and change sets from the sync report.

It would have been possible to do the baseline creation and the deliver in one step, in our case. I choose to keep it separate, because it shows that you have to provide outgoing change sets as well as outgoing baselines from the sync report to be able to deliver a baseline. I contemplated over many IllegalArgumentExceptions to get to this insight.

private IBaselineConnection exctractToComponentBaseline(
		ITeamRepository teamRepository, 
		IWorkspaceConnection repoWorkspace,
		IWorkspaceConnection targetStream,
		IComponentHandle component, 
		String archiveFileName,
		String changeSetComment, 
		String baselineName,
		String baselineComment, 
		IProgressMonitor monitor) throws Exception, TeamRepositoryException {

	// Extract the archive file to the component in the repository workspace
	System.out.println("Extracting...");
	ArchiveToSCMExtractor extract = new ArchiveToSCMExtractor();
	extract.extractFileToComponent(archiveFileName, teamRepository, 
			repoWorkspace, component, changeSetComment, monitor);

	// Compare the repository workspace with the stream to find the changes
	// Deliver the change sets
	System.out.println("Comparing Change Sets...");
	IChangeHistorySyncReport changeSetSync = repoWorkspace.compareTo(
			targetStream,
			WorkspaceComparisonFlags.CHANGE_SET_COMPARISON_ONLY,
			Collections.EMPTY_LIST, monitor);
	System.out.println("Deliver Change Sets...");
	repoWorkspace.deliver(targetStream, changeSetSync,
				Collections.EMPTY_LIST,
				changeSetSync.outgoingChangeSets(component), monitor);

	// Create a baseline and compare the repository workspace with the
	// stream to find the changes and deliver the baselines
	System.out.println("Create Baseline...");
	IBaselineConnection baseline = repoWorkspace.createBaseline(
			component, baselineName, baselineComment, monitor);
	System.out.println("Comparing Baselines...");
	IChangeHistorySyncReport baselineSync = repoWorkspace.compareTo(
			targetStream,
			WorkspaceComparisonFlags.INCLUDE_BASELINE_INFO,
			Collections.EMPTY_LIST, monitor);

	// Deliver the baselines
	System.out.println("Deliver Baselines...");
	repoWorkspace.deliver(targetStream, baselineSync,
			baselineSync.outgoingBaselines(component),
			baselineSync.outgoingChangeSets(component), monitor);
	System.out.println("Extracting successful...");

	return baseline;
}

After extracting, sharing, creating baselines and delivering to setup the scenario right, the repository workspace needs to be set to a specific older baseline. This is done in setActiveBaseline().

The interesting part here is that it is necessary to provide a list of component operations (implementing IComponentOp). The component operations can be created using the IFlowNodeConnection.componentOpFactory() API which is inherited by IWorkspaceConnection.

The code replaces the baseline by an older one, created earlier in the process. The replaceComponent() operation takes the component, the baseline connection and a parameter that allows to calculate detailed item update reports. We don’t need this, because we don’t want to actually do anything with the baseline in our case.

private void setActiveBaseline(IWorkspaceConnection workspace,
		IComponentHandle component, IBaselineConnection lab2Baseline,
		IProgressMonitor monitor) throws TeamRepositoryException {
	workspace.applyComponentOperations(Collections.singletonList(workspace
			.componentOpFactory().replaceComponent(component, 
					lab2Baseline, false)), monitor);
}

Summary

The code in this post basically shows how to work with change sets and baselines, to manage workspace connections, deliver change sets and baselines and to replace a component with a specific baseline.

The last step needed is to understand how it is possible to extract an archive (or any other data source) into Jazz SCM. This is described in the post Extracting an Archive Into Jazz SCM Using the Plain Java Client Libraries.

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.

Managing Workspaces, Streams and Components Using the Plain Java Client Libraries

How can I manage the streams, repository workspaces and components in a RTC project area using the Plain Java Clients Library?

As described in the last post I want to automatically set up a project, manage the streams and components and seed the SCM system with SCM data. The last post shows how to create and manage the project area.

This post will talk about managing the components and the stream and repository workspaces.

The related posts are:

  1. Deploying Templates and Creating Projects using the Plain Java Clients Library
  2. This post
  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.

Managing Components, Streams and Workspaces

Continuing in the run method of Deploying Templates and Creating Projects using the Plain Java Clients Library we now want to create some required components and then set up the stream and repository workspace with these components.

The requirement is to have three components and to have them on the repository workspace and the stream. If there is a default component, we want to rename it to what we need.

The code below coordinates that. First it creates a list of components we want. the method manageComponents() takes care of renaming or creating the required components and provides with a map we can use later to get the one we want. Then, the code tries to find and rename or create a stream that will later be used, and add the required components.

The method manageWorkspaces() does the same for a repository workspace. After this has been performed the whole SCM structure is set up.

.
public static void main(String[] args) throws Exception {
.
.
.
.	List<String> requiredComponents = new ArrayList<String>();
	requiredComponents.add("Component 1");
	requiredComponents.add("Component 2");
	requiredComponents.add("Component 3");
	HashMap<String, IComponentHandle> components = manageComponents(
			teamRepository, area, requiredComponents, monitor);

	IWorkspaceConnection myStream = manageStream(teamRepository,
			area, "Stream Name", "Stream Description", components, monitor);
	if (extensionStream == null) {
		System.out.println("Could not create or retrieve a stream.");
		return false;
	}
	IWorkspaceConnection workspace = manageWorkspace(teamRepository, area,
			myStream, "Workspace name", "Workspace Description", components,
			monitor);
	if (workspace == null) {
		System.out.println("Could not create or retrieve a workspace.");
		return false;
	}
.
.
.
.
.
}

Manage Components

The method manageComponents() creates a map with the components that exist in the project area. Using the list of required components, it looks if there is a component with the correct name already. If there isn’t it tries to find any component that is already available and rename it. If there is no component for reuse, a new component is created.

private HashMap<String, IComponentHandle> manageComponents(
		ITeamRepository teamRepository, IProjectArea area, List requiredComponents,
		IProgressMonitor monitor) throws TeamRepositoryException {

	IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
	HashMap<String, IComponentHandle< allComponents = getComponentMap(wm, monitor);

	HashMap<String, IComponentHandle> components = new HashMap<String, IComponentHandle>();
	// process all required components.
	// Look up if we have the component already.
	// If not, grab an existing component we have found and reuse it by
	// renaming.
	// If there is none, create a new component.
	Set componentsRemaining = allComponents.keySet();
	Iterator remainingComponentsIterator = componentsRemaining
			.iterator();
	for (String requiredComponent : requiredComponents) {
		IComponentHandle required = allComponents.get(requiredComponent);
		if (required != null) {
			// Reuse Component
			components.put(requiredComponent, required);
		} else {
			// We don't have it yet.
			if (remainingComponentsIterator.hasNext()) {
				String compName = remainingComponentsIterator.next();
				IComponentHandle renameMe = allComponents.get(compName);
				// Create Component
				IComponentHandle component = renameOrCreateComponent(
						teamRepository, wm, area, renameMe,
						requiredComponent, monitor);
				extComponents.put(requiredComponent, component);
			} else {
				// Create Component
				IComponentHandle component = renameOrCreateComponent(
						teamRepository, wm, area, null, requiredComponent,
						monitor);
				components.put(requiredComponent, component);
			}
		}
	}
	return components;
}

The method getComponentMap() that gets all available components and places the handles into a map looks as below. It uses the IWorkspaceManager to get all component names. Then it uses IComponentSearchCriteria with the retrieved names to look up the handle for each component. Currently the situation that components have the same name is ignored, only a warning is issued. It would be possible to rename components with the same name.

Both name and handle are stored in a map for later usage and the map is returned.

private HashMap<String, IComponentHandle> getComponentMap(
		IWorkspaceManager wm, IProgressMonitor monitor)
		throws TeamRepositoryException {
	HashMap<String, IComponentHandle> allComponents = new HashMap<String, IComponentHandle>();
	// These are the components I need

	// Try to find all components
	Set<String> components = wm.findAllComponentNames(monitor);
	for (String compName : components) {
		IComponentSearchCriteria criteria = IComponentSearchCriteria.FACTORY
				.newInstance();
		criteria.setExactName(compName);
		List<IComponentHandle> found = wm.findComponents(criteria,
				Integer.MAX_VALUE, monitor);

		if (found.size() > 1) {
			System.out.println("Ambiguous Component Names");
		}

		for (IComponentHandle iComponentHandle : found) {
			allComponents.put(compName, iComponentHandle);
		}
	}
	return allComponents;
}

The code for renameOrCreateComponent() to create or rename a component is shown below. Again IWorkspaceManager is used to do the work.

If the component handle passed is not null , then there is an existing component, and the name of this component is changed.

If the parameter for the component handle is null a new component is created and named as desired. For learning purposes the component is created as private component of the automation user first.

In any case the ownership of the component is set to the project area.

private IComponentHandle renameOrCreateComponent(
		ITeamRepository teamRepository, IWorkspaceManager wm,
		IProjectArea area, IComponentHandle componentHandle,
		String componentName, IProgressMonitor monitor)
		throws TeamRepositoryException {
	if (componentHandle == null) {
		// Rename component
		componentHandle = wm.createComponent(componentName,
				teamRepository.loggedInContributor(), monitor);
		wm.setComponentOwner(componentHandle, area, monitor);
	} else {
		// Rename component
		wm.renameComponent(componentHandle, componentName, monitor);
		wm.setComponentOwner(componentHandle, area, monitor);
	}
	return componentHandle;
}

Now we have the components that we need and they are returned in a convenient way in a map for easier access.

Manage Streams

We have the components that we need. Now we need a stream and the stream should have the components. This is managed in the method manageStream().

The method tries to find or create a IWorkspaceConnection (a Stream in this case). The IWorkspaceConnection is the abstraction of a repository workspace or a stream.

The code uses the method findAndRenameConnection() which is explained later. The code tries to fist find a WorkspaceConnection (a stream or workspace) by name. If that does not work it tries to find any workspace.  If there is one found, it gets renamed, otherwise a new one is created.

This method also removes all components from the IWorkspcaceConnection and adds the required components.

private IWorkspaceConnection manageStream(ITeamRepository teamRepository,
		IProjectArea area, String streamName, String description,
		HashMap<String, IComponentHandle>components,
		IProgressMonitor monitor) throws TeamRepositoryException {
	IWorkspaceConnection connection = findAndRenameConnection(
			teamRepository, IWorkspaceSearchCriteria.STREAMS, streamName,
			description, monitor);
	if (connection == null) {
		IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
		connection = wm.createStream(area, streamName, description, monitor);
	}
	// Remove all components
	removeAllCompoentsFormWorkspaceConnection(connection, monitor);
	addCompoentsToWorkspaceConnection(connection, components, monitor);
	return connection;
}

The method findAndRenameConnection() as shown below finds a workspace or stream, selectable by kind with a certain name if given. Again, the IWorkspaceManager is the main interface used. The method tries to find the connection by name and kind first. If that does not succeed. It uses findConnectionByName() to find a connection by name and kind,if it already exists.

The code could be enhanced to delete any additional workspaces that are not needed.

private IWorkspaceConnection findAndRenameConnection(
		ITeamRepository teamRepository, int kind, String name,
		String description, IProgressMonitor monitor)
		throws TeamRepositoryException {
	IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
	// Find the exact name if available use that.
	List<IWorkspaceHandle> workspaces = findConnectionByName(teamRepository,
			name, kind, monitor);
	IWorkspaceHandle firstFound = null;
	IWorkspaceConnection connection = null;
	if (!workspaces.isEmpty()) {
		firstFound = workspaces.get(0);
		connection = wm.getWorkspaceConnection(firstFound, monitor);
	} else {
		// Find an existing stream or workspace (providing a null name) and rename it
		workspaces = findConnectionByName(teamRepository, null, kind,
				monitor);
		for (IWorkspaceHandle workspaceHandle : workspaces) {
			IWorkspace ws = (IWorkspace) teamRepository.itemManager()
					.fetchCompleteItem(workspaceHandle,
					IItemManager.DEFAULT, monitor);
			if (firstFound == null) {
				firstFound = workspaceHandle;
			} else {
				// wm.deleteWorkspace(workspaceHandle, monitor);
				System.out.println("Should be deleted.... ");
			}
		}
		if (firstFound != null) {
			connection = wm.getWorkspaceConnection(firstFound, monitor);
			System.out.println("Renaming: " + connection.getName());
			connection.setName(name, monitor);
			connection.setDescription(description, monitor);
		}
	}
	return connection;
}

The method findConnectionByName() finds a workspace or stream, selectable by kind with a certain name. If the name is not specified, it just look for any object of the kind. The method uses IWorkspaceSearchCriteria to create the criteria to search for.

private List findConnectionByName(
		ITeamRepository teamRepository, String name, int kind,
		IProgressMonitor monitor) throws TeamRepositoryException {
	IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
	IWorkspaceSearchCriteria criteria = IWorkspaceSearchCriteria.FACTORY
			.newInstance().setKind(kind);
	if (name != null) {
		criteria.setExactName(name);
	}
	List<IWorkspaceHandle>workspaces= wm.findWorkspaces(criteria,
			Integer.MAX_VALUE, monitor);
	return workspaces;
}

The code that is missing is to remove and add components to the stream.

The code of the method removeAllCompoentsFormWorkspaceConnection() below removes all components from a workspace connection, which can be a stream or repository workspace. It uses an IComponentOp retrieved from the IComponentOpFactory to remove the components. Please note, that the Plain Java Client Library snippets currently refer to the deprecated API IWorkspaceConnection.addComponent(). The code below is the way the API works since 4.x.

private void removeAllCompoentsFormWorkspaceConnection(
		IWorkspaceConnection workspaceConnection, IProgressMonitor monitor)
		throws TeamRepositoryException {
	// Remove all components
	List wsComponents = workspaceConnection.getComponents();
	for (Object comp : wsComponents) {
		IComponentHandle cHandle = (IComponentHandle) comp;
		workspaceConnection.applyComponentOperations(Collections
				.singletonList(workspaceConnection.componentOpFactory()
						.removeComponent(cHandle, false)), true, monitor);
	}
}

The code below shows the method addCompoentsToWorkspaceConnection() which adds the components from our component map to the workspace connection. Again, an IComponentOp retrieved from the IComponentOpFactory is used.

private IWorkspaceConnection addCompoentsToWorkspaceConnection(
		IWorkspaceConnection workspaceConnection,
		HashMap<String, IComponentHandle> extComponents,
		IProgressMonitor monitor) throws TeamRepositoryException {

	// Add new components
	Collection components = extComponents.values();
	for (Object comp : components) {
		IComponentHandle cHandle = (IComponentHandle) comp;
		workspaceConnection.applyComponentOperations(Collections
				.singletonList(workspaceConnection.componentOpFactory()
						.addComponent(cHandle, false)), true, monitor);
	}
	return workspaceConnection;
}

Manage Workspaces

The last method to describe is manageWorkspace(). This method does exactly what manageStream() does for a stream, but only for a repository workspace. It tries to find a repository workspace. If it finds one it renames it. Otherwise it creates a new workspace. Then it makes sure the correct components are in the workspace. It uses the same helper methods described above to do its task.

private IWorkspaceConnection manageWorkspace(
		ITeamRepository teamRepository, IProjectArea area,
		IWorkspaceConnection extensionStream, String workspaceName, String description,
		HashMap<String, IComponentHandle> extComponents,
		IProgressMonitor monitor) throws TeamRepositoryException {
	IWorkspaceConnection connection = findAndRenameConnection(
			teamRepository, IWorkspaceSearchCriteria.WORKSPACES,
			workspaceName, description,
			monitor);
	if (connection == null) {
		IWorkspaceManager wm = SCMPlatform.getWorkspaceManager(teamRepository);
		connection = wm.createWorkspace(
				teamRepository.loggedInContributor(), workspaceName,
				description, monitor);	
	}
	removeAllCompoentsFormWorkspaceConnection(connection, monitor);
	addCompoentsToWorkspaceConnection(connection, extComponents, monitor);
	return connection;
}

Summary

The code in this post basically shows how to manage connections, streams and workspaces to prepare Jazz SCM for later usage. Please be aware that, so far, there is no connection between the workspace and the stream. The Flow Target will be set later, once we begin delivering from the workspace to the stream.

Please note, there might be other ways of dealing with this, especially getting components from a stream and the methods used here might not apply for all use case, especially reusing components,streams and workspaces. You can always pick the parts you need.

Now that the project is prepared with the required SCM, the next post will show how it is possible to upload code from compressed files into the components, share and baseline the code.

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.