Beginning API Discovery (or understanding the RootServices document)


Photo by Felix Mittermeier on Unsplash

Now that we’ve covered some of the basics on what we mean when we say APIs (link to prior post), it’s time to get into the power of ELM thru its API discovery process.

Many of the APIs on a server are exposed thru API calls.  The foundation of this discovery mechanism is the “RootServices” document of the ELM application.  Each ELM application has its own RootServices document. I’ll be focusing on four of the ELM applications, specifically:

  • JTS – Jazz Team Server
  • CCM – Configuration and Change Management – AKA – Engineering Workflow Management
  • QM – Quality Management – AKA – Engineering Test Management
  • RM – Requirements Management – AKA Engineering Requirements Management or DOORS Next

For the purpose of this series of blog posts, I will be using a locally hosted server named https://elmwb.com on port 9443. You will need to replace this server name and port with the server information of your own.

The RootServices API is publicly addressable; it doesn’t require any authentication.  The reason behind this is to ensure that you can discover the services for authentication, and so that servers can query each other regarding what services are available.  Most APIs that are exposed in the RootServices do require authentication.   I will have two separate blog posts which all address authentication, one covering OAuth1.0a and one covering the use of a Bearer token.

RootServices API

The API for accessing the RootServices document is simply:

GET https://<<SERVER>>/<<APPLICATION>>/rootservices

The API also requires you to include at least one of the following headers in order to define the format of the RootServices document:

	accept:application/rdf+xml
	accept:application/json
	accept:text/turtle

If you use CURL the API call would be:

curl --location --request GET ‘https://elmwb.com:9443/rm/rootservices' \
	--header 'accept: application/rdf+xml'

The flexibility of the response body allows you to introspect the contents in an appropriate manner for your specific needs.  One key difference to note in the formats is that both RDF and Turtle formats provide descriptors to simplify the contents; json does not have descriptors.  In RDF, these descriptors are identified with “xmlns” (or xml name space), while in turtle they are identified with @prefix.  Understanding the rest of the differences between these formats is up to you. More information can be found at:

The following images show the beginning of the RootServices document in the above three formats:

application/rdf+xml
application/json
text/turtle

Let’s look at the overall structure and content of the RootServices document and how it will help us for future APIs.  I will be using the rdf+xml format for the rest of this post.

There are three major sections in the RootServices document:

  1. Name Spaces – the name spaces identify the domain and/or process that governs a specific resource.  Each name space is provided with a short identifier which is used as a prefix for defining the full URI which describes a resource.  For example the identifier xmlns:dc describes the “Dublin Core” term as defined at “http://purl.org/dc/terms/“.  This prefix is then used in the definition of resource called <dc:title>.  The full definition of the title can be found at http://purl.org/dc/terms#title .
Dublin Core term example
  • Understanding the details about “Dublin Core” is not critical to the understanding of the RootServices document; it provides a simple way of explaining the name space concept. If you want learn more about “Dublin Core” you can check out their website at https://dublincore.org.
  1. Comments – In the rdf+xml format these lines are identified as <!— —> and are informational only.
  1. Resources – This section describes the name spaces for the server. By placing the service in this RootServices document this can be considered public APIs.  The name space prefix defined earlier in the RootServices document can provide you context about which aspect of the server the specific service addresses.  Some general guidelines include:
  • jd = Jazz Discovery
  • jfs = Jazz Foundation 
  • jdb = Jazz Dashboard
  • ju = Jazz UI elements
  • jp06 = Jazz Process (release 0.6)
  • jp = Jazz Process (release 1.0)
  • oslc = Open Services for Lifecycle Collaboration – this is the Oasis based standard for services across lifecycle based applications.  ELM is both a provider and consumer of OSLC services.  For more information on OSLC and Oasis see: https://open-services.net and https://www.oasis-open.org/ .
  • oslc_XX = OSLC services for a specific application, for example rm = requirements management, cm = change management, etc.
  • rm = Requirements Management, these are DOORS Next specific services
  • trs = Tracked Resource Set version 1.x
  • trs2 = Tracked Resource Set version 2

A detailed (yet somewhat dated) description of the RootServices document can be found on jazz.net at https://jazz.net/wiki/bin/view/Main/RootServicesSpec.

Next, we focus on a few key sections in the RootServices document which will help us discover more APIs as we move forward:

First, after the list of name spaces, we see the Title of the server whose RootServices we are accessing and a detailed description of the server.  They are all in the dc name space, i.e. Dublin Core.

<dc:title xml:lang="en">Doors Next</dc:title>
<dc:description>This application provides the capabilities to create and manage requirements and trace them to modeling, testing, and change and configuration management. You can define, elicit, capture, elaborate, discuss, and review requirements and supporting artifacts.</dc:description>

Second, is a list of common services for the Jazz server and application we are on. Included in this section are those services that are necessary for authentication when using our APIs.

If you are utilizing OAuth1.0a to access the APIs, you should look at the jfs services with include oauth in their name.  On my server, the following services are exposed:

<jfs:oauthDomain>https://elmwb.com:9443/jts,https://elmwb.com:9443/rm</jfs:oauthDomain>
<jfs:oauthRealmName>Jazz</jfs:oauthRealmName>
<jfs:oauthAccessTokenUrl rdf:resource="https://elmwb.com:9443/jts/oauth-access-token" />
<jfs:oauthApprovalModuleUrl rdf:resource="https://elmwb.com:9443/jts/_ajax-modules/com.ibm.team.repository.AuthorizeOAuth" />
<jfs:oauthExpireTokenUrl rdf:resource="https://elmwb.com:9443/jts/oauth-expire-token" />
<jfs:oauthRequestConsumerKeyUrl rdf:resource="https://elmwb.com:9443/jts/oauth-request-consumer" />
<jfs:oauthRequestTokenUrl rdf:resource="https://elmwb.com:9443/jts/oauth-request-token" />
<jfs:oauthUserAuthorizationUrl rdf:resource="https://elmwb.com:9443/jts/oauth-authorize" />

We see three key end points which are necessary for a OAuth1.0a process (which I will cover in detail in another blog post) – oauthAccessTokenUrl, oauthRequestTokenUrl, and oauthUserAuthorizationUrl.  These three URLs are needed to address the three steps that a OAuth authentication that I will cover in another blog post.  

Third, is a list of application specific services.  On our sample server, which is Doors Next application server, we see the following list of services.

<!-- Applications may add any services they provide here -->
<oslc_rm:rmServiceProviders rdf:resource="https://elmwb.com:9443/rm/oslc_rm/catalog" />
    <oslc_rm:majorVersion>7</oslc_rm:majorVersion>
    <oslc_rm:version>7.0.2</oslc_rm:version>
    <oslc_rm:buildVersion>7.0.2</oslc_rm:buildVersion>
    <oslc_config:cmServiceProviders rdf:resource="https://elmwb.com:9443/rm/oslc_config"/>
    <rm:glossaryTermsQuery rdf:resource="https://elmwb.com:9443/rm/glossary/termslookup" />
    <rm:components rdf:resource="https://elmwb.com:9443/rm/cm/component/ldpc" />
    <rm:projectAreas rdf:resource="https://elmwb.com:9443/rm/projects" />
    <rm:cmpProjectAreas rdf:resource="https://elmwb.com:9443/rm/rm-projects" />
    <rm:rrcExtensions>0.1.3-0.1.5</rm:rrcExtensions>
<!-- The admin Web UI service should be uncommented in applications -->
    <jfs:adminWebUI rdf:resource="https://elmwb.com:9443/rm/admin" />
<!-- The registration handler service should be uncommented for application  that do not supply their own -->
    <jd:registration rdf:resource="https://elmwb.com:9443/rm/service/com.ibm.team.repository.service.internal.setup.IRegistrationHandlerService" />
<!--  Process Component Tracked Resource Set 2.0 Provider -->
    <rm:trackedResourceSetProvider>
        <trs2:TrackedResourceSet>
            <trs2:trackedResourceSet rdf:resource="https://elmwb.com:9443/rm/process-trs2" />
            <dc:title>TRS 2.0 for DOORS Next Process Resources</dc:title>
            <dc:description>TRS 2.0 feed for process resources in DOORS Next</dc:description>
            <dc:type     rdf:resource="http://jazz.net/ns/process#" />
            <oslc:domain rdf:resource="http://jazz.net/ns/process#" />
        </trs2:TrackedResourceSet>
    </rm:trackedResourceSetProvider>
<!-- End of application-specific services -->

As you can see this server has OSLC and RM specific services.  We also see that this server is a TRS 2.0 provider. 

Key for our discovery of APIs, we would want to look at the oslc:rmServiceProviders.  A GET to this API will provide us with a catalog of those objects that provide services.  In the case of this server it will be a catalog of the Project areas on our server, along with the services they provide.

Let’s do a quick GET call to the API identified in oslc:rmServiceProviders.  If you are trying this via a browser, you will get prompted for a log in, this tells us that the API needs to be authenticated.  Go ahead and log in and look at the results.  On my server I have setup three Project areas, and it will provide us with the following response:

<rdf:RDF
 xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 xmlns:dcterms="http://purl.org/dc/terms/"
 xmlns:jp="http://jazz.net/xmlns/prod/jazz/process/1.0/"
 xmlns:jazzDisc="http://jazz.net/ns/discovery#"
 xmlns:oslc="http://open-services.net/ns/core#">

 <oslc:ServiceProviderCatalog rdf:about="https://elmwb.com:9443/rm/oslc_rm/catalog">
    <dcterms:title rdf:parseType="Literal">RMCatalog</dcterms:title>
    <dcterms:publisher rdf:resource="https://elmwb.com:9443/rm/application-about" />
    <oslc:domain rdf:resource="http://open-services.net/ns/rm#" />
    <oslc:serviceProvider>
      <oslc:ServiceProvider rdf:about="https://elmwb.com:9443/rm/oslc_rm/_LgdUMIkaEey3TMAARolZjw/services.xml">
         <dcterms:title rdf:parseType="Literal">JKE Banking (Requirements Management)</dcterms:title>
         <jazzDisc:messageReceiver rdf:resource="https://elmwb.com:9443/rm/web/com/ibm/rdm/web/copyReceiver/CopyHandler.html"/>
         <jp:consumerRegistry rdf:resource="https://elmwb.com:9443/rm/process/project-areas/_LgdUMIkaEey3TMAARolZjw/links"/>
         <oslc:details rdf:resource="https://elmwb.com:9443/rm/process/project-areas/_LgdUMIkaEey3TMAARolZjw"/>
      </oslc:ServiceProvider>
    </oslc:serviceProvider>
    <oslc:serviceProvider>
      <oslc:ServiceProvider rdf:about="https://elmwb.com:9443/rm/oslc_rm/_VoWUwIkbEey3TMAARolZjw/services.xml">
         <dcterms:title rdf:parseType="Literal">Sample Project 1 (Requirements)</dcterms:title>
         <jazzDisc:messageReceiver rdf:resource="https://elmwb.com:9443/rm/web/com/ibm/rdm/web/copyReceiver/CopyHandler.html"/>
         <jp:consumerRegistry rdf:resource="https://elmwb.com:9443/rm/process/project-areas/_VoWUwIkbEey3TMAARolZjw/links"/>
         <oslc:details rdf:resource="https://elmwb.com:9443/rm/process/project-areas/_VoWUwIkbEey3TMAARolZjw"/>
       </oslc:ServiceProvider>
    </oslc:serviceProvider>
    <oslc:serviceProvider>
    <oslc:ServiceProvider rdf:about="https://elmwb.com:9443/rm/oslc_rm/_BVnHAImtEeyjbIIiaev_dg/services.xml">
       <dcterms:title rdf:parseType="Literal">Title test</dcterms:title>
       <jazzDisc:messageReceiver rdf:resource="https://elmwb.com:9443/rm/web/com/ibm/rdm/web/copyReceiver/CopyHandler.html"/>
       <jp:consumerRegistry rdf:resource="https://elmwb.com:9443/rm/process/project-areas/_BVnHAImtEeyjbIIiaev_dg/links"/>
       <oslc:details rdf:resource="https://elmwb.com:9443/rm/process/project-areas/_BVnHAImtEeyjbIIiaev_dg"/>
    </oslc:ServiceProvider>
  </oslc:serviceProvider>
</oslc:ServiceProviderCatalog>
</rdf:RDF>

I am not going to go through all the details right now, but just realize we have a list of all the project areas (or Service Providers) on this server.  We can actually execute a GET against a specific project area to get a list of supported services for that Project area.  This can be found in the <oslc:ServiceProvider > section.  But that’s for another blog post.

1 thought on “Beginning API Discovery (or understanding the RootServices document)

  1. Pingback: API Authentication Method in ELM – Oauth 1.0a | Random Thoughts

Comments are closed.