Programmatic authentication and certificate handling for Rational Team Concert 2.0.

Getting started with the Resource-Oriented Work Item API

Learn how to use the Resource-Oriented Work Item API that is included in IBM® Rational Team Concert™ 2.0, using the Apache HTTP client while maintaining an authenticated session with the server. This article explains how to programmatically accept self-signed certificates and how to authenticate by using either form-based or basic authentication. You will then be able to quickly take advantage of the Work Item API without spending too much time on complicated authentication issues.

Colin Kennedy (kennedyc@ie.ibm.com), Software Developer, IBM Ireland

photo of Colin KennedyColin Kennedy is a Sun Certified Java Programmer who has worked as a software developer for IBM for three years. He currently works on industry templates for WebSphere Portal.



Ileana Belfiore (belfilie@ie.ibm.com), Software Developer, IBM Ireland

photo of Ileana BelfioreIleana Belfiore joined IBM in 2006. She works as a software engineer on the LotusLive Meetings team. Ileana's writing experience within IBM includes three publications on IP.com.



05 October 2010

Also available in Chinese

Introduction

IBM® Rational Team Concert™ Version 2.0 provides an API to interact with work items and other resources stored on the server. This API can be easily exploited by using a Java™ client. This article describes how to get started with the Resource-Oriented Work Item API, using the Apache HTTP client as a base for your code. It covers how to overcome common problems, such as certificate handling and authentication. Finally, the article explains how to leverage the API for several actions, such as running queries against Rational Team Concert and returning a set of work items.

The diagram in Figure 1 illustrates the architecture.

Figure 1. Architecture
Diagram, from Apache HTTP client to the API

Resource-Oriented Work Item API

Rational Team Concert 2.0 work items and other associated resources are exposed through the Resource-Oriented Work Item API. The API adheres to the Open Services Lifecycle Collaboration's Change Management Specification (OSLC CM), the intention of which is to define the set of HTTP-based RESTful interfaces in terms of HTTP methods, HTTP response codes, mime type handling and resource formats.

By using the Resource-Oriented Work Item API, you can get, create, modify, delete, and query work items, as well as other resources stored on the Rational Team Concert server by using the standard HTTP methods. These are some of the actions that can be performed through the API:

  • Retrieve work items at different levels of granularity (formats supported are JavaScript Object Notation, or JSON, XML, Atom, and HTML)
  • Update work items (by modifying the JSON or XML representation and posting it back to the server)
  • Create work items (by either obtaining an HTML creation dialog module or by posting the JSON or XML representation to a factory URL)
  • Add or remove links
  • Query work items (by either obtaining an HTML picker module or by creating full-text and structured queries)

The API can be leveraged in many ways and in many languages. This article focuses on how to interact with the API by using an Apache HTTP Java client.

Apache HTTP client

The core Java package provides basic methods for working with HTTP, but it does not provide the flexibility and functionality required by many applications. The Apache HTTP client (HttpClient) adds extra functionality by providing a feature-rich and fully functional Java package for accessing resources through HTTP.

The Apache HTTP client package is designed to be extended, while also giving support for the base HTTP protocol. The HttpClient component can be of great use to anyone building client applications such as web browsers or REST clients.

This package is an obvious choice to use as the base for building a Java client to interact with the Rational Team Concert server. The Get and Post methods of the client can be used to easily send requests to the Rational Team Concert Server REST API. The HttpClient also has built-in functions to store cookies and handle certificates, which you will use in the examples in the following sections.


Certificate handling

Rational Team Concert includes a self-signed certificate, which is used by default when the server is configured to use a Secure Sockets Layer (SSL). This can cause an SSLPeerUnverifiedException to be thrown by your Java client. This is the same warning you would get if you visited the site using your browser.

How to programmatically accept self-signed certificates

The role of the TrustManager interface is to validate the SSL certificate that is sent by a peer. This includes checking the expiration date of the certificate, verifying the signature, and deciding whether credentials presented by the peer should be accepted.

  1. To accept self-signed certificates, create a new TrustManager array containing one TrustManager instance that implements the X509 trust manager interface.
  2. When implementing an interface, your method must override all methods of the interface. In the case of the X509TrustManager interface, override the three methods as code Listing 1 shows.
Listing 1. TrustManager methods override
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
       public X509Certificate[] getAcceptedIssuers() {
           return null;
       }
	 
	public void checkclientTrusted(X509Certificate[] certs, String authType) {
	   // Leave blank to trust every client
	}
	 
	public void checkServerTrusted(X509Certificate[] certs, String authType) {
	   // Leave blank to trust every server
	}
    }
};
  1. To ensure that the new TrustManager is used by the Java client, create a new SSLContext instance:
mySSLContext = SSLContext.getInstance("SSL");
  1. Next, initialize the SSLContext instance with the new TrustManager:
mySSLContext.init(null, trustAllCerts, new java.security.SecureRandom());
  1. Finally you must override the default SSLSocketFactory of the HttpsURLConnection, which is used by the Apache HTTP client when making requests:
HttpsURLConnection.setDefaultSSLSocketFactory(mySSLContext.getSocketFactory());

If this action is performed before the first request is sent, all certificates are then accepted for the remainder of the session.

Important:
This implementation will automatically accept any certificate that it encounters. This might cause some security concerns in certain scenarios, so use it with caution.


Authentication

By default, Rational Team Concert is installed on the Apache Tomcat server, but it can also be installed on an IBM® WebSphere® Application Server. The authentication mechanism supported will depend on which web server is used to host Rational Team Concert. The Apache Tomcat server uses basic authentication; whereas, WebSphere Application Server supports both basic authentication and form-based authentication.

The HTTP client

  1. First, set up an HTTP client by using the Apache HttpClient (4.0.1) library.
  2. Create an instance of the DefaultHttpclient class:
DefaultHttpclient httpclient = new DefaultHttpclient();

You will use this client to interact with the Rational Team Concert server.

Basic authentication

After you have created an instance of the HttpClient, the next step is to provide the credentials required to authenticate with the Rational Team Concert server.

  1. Specify the credentials by creating a CredentialsProvider instance:
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(new AuthScope(
  "host", AuthScope.ANY_PORT), new UsernamePasswordCredentials("username", "password"));

The setCredentials method accepts an instance of the AuthScope class as its first parameter and an instance of the UsernamePasswordCredentials class as its second parameter. The host name and port of the Rational Team Concert server that you want to connect to must be defined in the AuthScope instance. The UsernamePasswordCredentials instance will encapsulate a user name and password that are required to authenticate with the Rational Team Concert server.

  1. Finally, bind the CredentialProvider to the client:
httpclient.setCredentialsProvider(credsProvider);

Form-based authentication

  1. Using the DefaultHttpClient initialized earlier, create a connection to the server to retrieve the WebSphere Application Server request URL.
  2. To store the WebSphere Application Server request URL, set up a cookie store and a local HttpContext instance:
Httpclient httpclient = new DefaultHttpclient();
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
  1. Next, bind the cookie store to the HttpContext:
localContext.setAttribute(clientContext.COOKIE_STORE,cookieStore);
  1. Now, construct an HttpGet method, and pass in a URL to the constructor. This URL consists of the host name and port number of the Rational Team Concert server that you want to connect to, followed by the path /jazz/authenticated/identity:
HttpGet httpGetID = new HttpGet("https://myRtcServer:9443/jazz/authenticated/identity");
  1. To retrieve the WebSphere Application Server request URL as a cookie, execute the Get method. To do this, call the Http client's execute method, and pass the Get method and the local HttpContext instance as parameters.
  2. Because the response is not used at this point, the connection must be closed:
httpclient.execute(httpGetID, localContext);
httpGetID.abort();
  1. To check if the URL has been stored in the cookie store, use the following code to print out each cookie in the store:
List<Cookie> cookies1 = cookieStore.getCookies();
for (Cookie cookie : cookies1) {
   logger.info("\t"+cookie.getName()+" : "+cookie.getValue());
}
  1. The next step is to construct a form to pass to the WebSphere Application Server j_security_check. To do this, use the Name Value Pair classes of the Apache HttpClient:
List<NameValuePair> authFormParams = new ArrayList<NameValuePair>();
authFormParams.add(new BasicNameValuePair("j_username", "myUsername"));
authFormParams.add(new BasicNameValuePair("j_password", "myPassword"));
  1. Now, construct a URLEncodedFormEntity. This entity is composed of a list of URL-encoded pairs. Here, you use it to pass the user name and password to the Rational Team Concert server in an HTTP Post request:
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(authFormParams, "UTF-8");
HttpPost httpPostAuth = new HttpPost(
  "https://myRtcServer:9443/jazz/authenticated/j_security_check");
httpPostAuth.setEntity(entity);
  1. Finally, execute the Post method to retrieve the Lightweight Third-Party Authentication (LTPA) tokens from the WebSphere Application Server. Pass the local context to the execute method so that the LTPA tokens are stored in the custom cookie store.
httpclient.execute(httpPostAuth, localContext);
  1. To check whether the LTPA tokens are stored correctly, use the following code:
List<Cookie> cookies2 = cookieStore.getCookies();
for (Cookie cookie : cookies2) {
   logger.info("\t"+cookie.getName()+" : "+cookie.getValue());
}
  1. To maintain an authenticated session, pass the local HttpContext instance to every httpclient.execute method you call in your code.

Interacting with the Work Item API

After the HttpClient is configured to use the appropriate authentication protocol for the Rational Team Concert server instance, you can leverage the work item API.

  1. Change the HttpContext instance if necessary:
    • If you are using basic authentication, you must create an HttpContext instance:
HttpContext localContext = new BasicHttpContext();
  • If you are using form-based authentication, use the local HttpContext instance that you created earlier.
  1. Now, set up a Get request to your Rational Team Concert server and specify the Accept header. In this example we are accessing the root services document:
HttpGet httpget = new HttpGet("https://myRtcServer:9443/jazz/rootservices");
httpget.setHeader("Accept", "text/xml");

The Accept request header is used to specify which media types are appropriate for the response.

The Get request is then executed by the client:

HttpResponse response = httpclient.execute(httpget, localContext);

The response is read into an HttpEntity instance, and its content is read into an IO stream:

HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();

QNames

It is important to understand the structure of QNames. They are formed by a Prefix (mapped to a Namespace URI) and by a Local Name (or Local Part).
QNames define a valid identifier for Elements and Attributes.

As the stream is read, the XML needs to be parsed to identify and extract the relevant resource URIs. The URI references are represented by Qualified Names, or QNames.

For each resource to be extracted, you must know the Namespace URI and Local Name for both the element and the attribute.

Consider, for example:

<oslc_cm:cmServiceProviders
  rdf:resource="https://myRtcServer:9443/jazz/oslc/workitems/catalog"/>

In that example:

  • QName oslc_cm:cmServiceProviders is the element.
  • QName rdf:resource is an attribute.
  • oslc_cm and rdf are prefixes.
  • cmServiceProviders and resource are Local Names.

Prefixes are used as a shorthand notation.

QNames map Namespace URIs to prefixes, which enable the abbreviation of URIs. They provide a more convenient way to write XML documents, because URI references can be long and might contain prohibited characters for element or attribute naming.

Prefixes are defined at the beginning of an XML document. For example, the oslc_cm prefix is defined as:

xmlns:oslc_cm="http://open-services.net/xmlns/cm/1.0/"

This means that oslc_cm:cmServiceProviders is just a shorthand notation for:

http://open-services.net/xmlns/cm/1.0/cmServiceProviders

Listing 2 reads the InputStream into an XMLInputStreamReader. It looks for the start element and, if it matches the element Namespace URI and Local Name, it then reads the attributes, looking for a match. When the attribute is found (in this case, the resource URI), it is returned. The URI can then be fed into the HttpClient as its next Get request.

Listing 2. Sample code to parse the response
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLStreamReader reader = inputFactory.createXMLStreamReader(stream);

Integer eventType;
String resource = null;

while(reader.hasNext()){

   eventType = reader.next();

   if(eventType.equals(XMLEvent.START_ELEMENT)) {
      if(reader.getNamespaceURI().equals(element_namespaceUri) 
            && reader.getLocalName().equals(element_localname)) {
         for(int i = 0; i < reader.getAttributeCount(); i++){
            if(reader.getAttributeNamespace(i).equals(attribute_namespaceUri)
		&& reader.getAttributeLocalName(i).equals(attribute_localname))
            {
               resource = reader.getAttributeValue(i);
		return resource;
            }
         }
      }
   }
}
stream.close();
reader.close();
return resource;

Tip:
Notice that element_namespaceUri, element_localname, attribute_namespaceUri, and attribute_localname are string objects that have been previously defined in a property file.

Using the discovery chain method

Rational Team Concert offers a mechanism to expose its resources and functionality without relying on specific URLs. This mechanism is called a discovery chain. It is the preferred method of accessing the Rational Team Concert services.

In Rational Team Concert, the root document is exposed at https://<server>:<port>/<app>/rootservicesand does not require authentication to retrieve the ServiceProvider elements contained within it.

When a request is sent to the root services URL, the response returned is a Resource Description Framework (RDF) document.

  1. From the root services document, you can retrieve the Change Management Catalog URI.
  2. The document behind this URI contains a list of ServiceProvider elements that point to the documents that contain the actual service descriptions. You can parse the root services document, identify the oslc_cm:cmServiceProviders element, and extract the value of the rdf:resource attribute:
<oslc_cm:cmServiceProviders
  rdf:resource="https://myRtcServer:9443/jazz/oslc/workitems/catalog"/>
  1. A request can be sent to this URI to fetch the document behind it.
    Authentication is required to access the catalog document, which is in XML format.
  2. To extract the services URL, you can parse the document returned to find the value of the oslc_disc:services element's rdf:resource attribute:
<oslc_disc:services rdf:resource=
  "https://myRtcServer:9443/jazz/oslc/contexts/<genId>/workitems/services.xml"/>
  1. Finally, a third request can be issued to this URI to fetch the services document. This document contains links to the dialog modules, to the factory URL to create new work items, and to the work item collection URL that enables you to query work items.

Figure 2 shows the discovery chain from the root services document to the service descriptors, via the Service Providers Catalog.

Figure 2. Discovery chain process flow
Discovery chain flow chart

Creating custom queries

Each work space in your Rational Team Concert server has a Simple Query URL, which can be used to create custom queries. This URL can be retrieved from the services discovery document by using the discovery chain method.

  1. To create a custom query, append the parameter ?oslc_cm.query=[query] to the Simple Query URL. A list of attributes that can be queried is available in the Jazz.net forum.
  2. To create a custom query in a Java client, construct a new URI by using the Simple Query URL as the base. Then use a list of name value pairs to construct the query string:
URI baseURI = new URI("https://myRtcServer:9443/jazz/oslc/contexts/<genID>/workitems);
List<BasicNameValuePair> qparams = new ArrayList<BasicNameValuePair>();
  1. Next, add a search parameter to the list of query parameters. In this example, the query will return all work items that contain the abbreviation "RTC."
qparams.add(new BasicNameValuePair("oslc_cm.query", "oslc_cm:searchTerms=\"RTC\""));
  1. Next, reconstruct the URI with the new query string:
queryURI = URIUtils.createURI(
  baseURI.getScheme(), baseURI.getHost(), baseURI.getPort(), baseURI.getPath(), 
  URLEncodedUtils.format(qparams, "UTF-8"), null);
  1. Now, construct an HttpGet method using the query URI:
HttpGet httpGetMethod = new HttpGet(queryURI);
  1. The content can be retrieved in different formats that are supported by the Resource-Oriented Work Item API. In this example, we retrieve the data in OSLC Change Request XML format by setting an Accept header:
httpGetMethod.addHeader("Accept", "application/x-oslc-cm-change-request+xml");
  1. Remember to pass in the local HttpContext instance to authenticate with the server:
HttpResponse response = null;
// Pass local context as a parameter
try {
  response = httpclient.execute(httpGetMethod, httpContext);
} catch (clientProtocolException e1) {
  e1.printStackTrace();
} catch (IOException e1) {
  e1.printStackTrace();
}

Because the response is in XML, it can now be parsed or manipulated in any way that you want.

Retrieving stored query results

In Rational Team Concert, queries created in the Query Editor are not yet exposed through the discovery chain. However the functionality exists outside of the scope of the OSLC CM specification.

Stored queries results can be accessed by an HTTP client using GET requests. The Stored Query Collection is exposed at the following address:

https://myRtcServer:9443/jazz/oslc/queries.xml

The query results can be returned in JSON, ATOM, XML, and XHTML. You can specify the format by appending the extension to the request URI.

If you know the item ID, you can access queries directly by using the following URI:

https://myRtcServer:9443/jazz/oslc/queries/<itemId>

As before, you can specify the format in the URI by appending the extension. For example, if you want to specify XML, use this request:

https://myRtcServer:9443/jazz/oslc/queries/<itemId>.xml

To view the result set of the query, use this request URL:

https://myRtcServer:9443/jazz/oslc/queries/<itemId>/rtc_cm:results

Similarly, you can specify that you want to view the results in XML format by appending the extension to the URI:

https://myRtcServer:9443/jazz/oslc/queries/<itemId>/rtc_cm:results.xml

It is also possible to specify which properties are to be displayed within the result set.

For example, to display only the Creation Date and Type properties of the work items returned by the query, this would be the URI:

https://myRtcServer:9443/jazz/oslc/queries
  /<itemId>/rtc_cm:results.xml?oslc_cm.properties=dc:created,dc:type

The response will return a collection of work items, and only the properties that you specified will be displayed.

For a list of all available work item attributes for which, in turn, properties can be specified in the request, see Appendix B of the Resource-Oriented Work Item API documentation. (A Jazz.net user id and password is required to view Appendix B. Registration is free.)

For some properties, the value will be a URL. In this example, you can see that the resource type property is a URL:

<oslc_cm:ChangeRequest 
rdf:resource="https://myRtcServer:9443/jazz/resource/itemOid/WorkItem/<genID>">
     <dc:type rdf:resource="https://myRtcServer:9443 /jazz/oslc/types/<genID>/defect"/>
</oslc_cm:ChangeRequest>

To resolve location URLs, the media type can be specified to be text or XML. For example:

https://myRtcServer:9443/jazz/resource/itemOid/Category/<genID>?_mediaType=text/xml

Connectivity troubleshooting tip

Wire logging can be very helpful while troubleshooting connectivity issues with the Rational Team Concert server. You can enable wire logging by specifying the following virtual machine arguments in the integrated development environment (IDE):

-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
-Dorg.apache.commons.logging.simplelog.showdatetime=true
-Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG
-Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=ERROR
-Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.conn=DEBUG
-Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.client=DEBUG
-Dorg.apache.commons.logging.simplelog.log.org.apache.http.client=DEBUG

Summary

This article described how to handle self-signed certificates from a Rational Team Concert 2.0 server, outlined how to authenticate by using both basic and form-based protocols, and gave an overview of how to get started interacting with the Resource-Oriented Work Item API. We hope this helps you overcome the initial hurdle of authenticating and connecting to Rational Team Concert so that you can productively interact with the Rational Team Concert resources.


Acknowledgements

The authors thank Brian Parle for introducing them to the topic, Ronan Dalton for encouraging and motivating them in writing this article, and both Patrick Streule and Jerh O'Connor for their time and help in reviewing this article.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Rational software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational, DevOps
ArticleID=548948
ArticleTitle=Programmatic authentication and certificate handling for Rational Team Concert 2.0.
publish-date=10052010