Showing posts with label Rally WS API. Show all posts
Showing posts with label Rally WS API. Show all posts

Monday, April 13, 2009

Using Rally Java Web Service API

 There are a number of developer tools that can be used from Rally ranging from integrating Rally to a different application(s) or just plainly extracting data from Rally. This link https://rally1-wiki.rallydev.com/display/Word/Developer+Tools provides necessary rally developer documentation.

Web Service API

Since Rally supports several implementation of their WS API this will mainly focus on SOAP in Java. You can find on this link https://rally1.rallydev.com/slm/doc/webservice/ the other implementations. The only thing I don't like about this API implementation is that you always have to pass the object reference through the wire to get the values of the object. The WS calls are so fine-grained that the number of objects queried is directly proportional to the number of round-trip calls. The sample usage of the SOAP in Java implementation is shown below in sequence.

Assuming our target of interest is to extract a Story from Rally. The Story in Rally is actually map to a SOAP object called HierarchicalRequirement. Always remember to use the read() method of RallyService? object to grab the physical object from Rally.

  1. Grab the WSDL from the current version of your Rally application which might have the form https://rallyx.rallydev.com/slm/webservice/x.xx/meta/34343483/rally.wsdl.
  2. Generate the Java code from the given wsdl file. Their will be 3 packages generated - com.rallydev.webservice.domain and com.rallydev.webservice.service.
    • com.rallydev.webservice.domain contains all SOAP objects that represent the data in Rally.
    • com.rallydev.webservice.service contains the web service interface.
  3.  Acquire connection from the web service endpoint and grab available Workspaces.
     URL url = new URL("https://rally1.rallydev.com/slm/webservice/1.10/RallyService");
    RallyService service = (new RallyServiceServiceLocator()).getRallyService(url);

    Stub stub = (Stub)service;
    stub.setUsername(rally_username);
    stub.setPassword(rally_password);
    stub.setMaintainSession(true);
    Subscription subscription = (Subscription)service.getCurrentSubscription();
    Workspace[] workspaces = subscription.getWorkspaces();
    if(workspaces==null || workspaces.length==0){
    errorBuf.append("The login credentials doesn't have any subscription or there are " +
    "no Workspaces configured from Rally.");
    writeToFile(serviceBean, errorBuf.toString());
    return null;
    }
  4. If the target workspace is "IT: the next generation" then loop through the workspaces that matches that workspace.
    Workspace workspace = null;
    for(int i=0; i<workspaces.length;i++){
    WSObject wsObject = (WSObject)service.read(workspaces[i]);
    workspace = (Workspace)wsObject;
    String workspaceName = workspace.getName();
    if(workspaceName.equalsIgnoreCase("IT: the next generation" )){
    break;
    }
    }
  5. Submit query and get results (DomainObject?[]). The serviceBean.getQuery() is a name/value pair which might be of the form Release.Name= "Test Release For TWiki" AND ScheduleState? = "Completed". Process each DomainObject?.
    QueryResult queryResult = service.query(workspace, "HierarchicalRequirement", serviceBean.getQuery(), "", false, 1, 100);
    if(queryResult.getErrors().length>0){
    for(int i=0; i<queryResult.getErrors().length;i++){
    errorBuf.append("ERROR: ");
    errorBuf.append(queryResult.getErrors()[i]);
    errorBuf.append("\n");
    }
    writeToFile(serviceBean, errorBuf.toString());
    return null;
    }
    DomainObject[] domainObjects = queryResult.getResults();
    if(domainObjects!=null && domainObjects.length>0){
    List releaseNotesBeanList = new ArrayList();
    TwikiBean twikiBean = new TwikiBean();
    Map packageStoryMap = new HashMap();
       for(int i=0;i<domainObjects.length;i++){
    HierarchicalRequirement story = (HierarchicalRequirement)service.read(domainObjects[i]);
    Release release = (Release)service.read(story.getRelease());
    DateFormat dateFormat = DateFormat.getInstance();
    String releaseDate = dateFormat.format(release.getReleaseDate().getTime());
          if(story.getAttachments()==null || story.getAttachments().length==0){
    errorBuf.append(NO_ATTACHMENT).append("\n");
    }
    if(story.get_package()==null || story.get_package().equals("")){
    errorBuf.append(NO_PACKAGE_NAME).append("\n");
    }
    if(release==null || release.getName()==null
    || release.getName().equals("")){
    errorBuf.append(NO_RELEASE_NAME).append("\n");
    }
          if(errorBuf.length()>0){
    errorBuf.insert(0, "ERROR: User Story ID: " + story.getFormattedID() + "\n");
    writeToFile(serviceBean, errorBuf.toString());
    continue;
    }
          ReleaseNotesBean releaseNotesBean = new ReleaseNotesBean();
    releaseNotesBean.setPackageName(story.get_package());
    releaseNotesBean.setUserStoryId(story.getFormattedID());
    releaseNotesBean.setUserStoryName(story.getName());
    releaseNotesBean.setReleaseDate(releaseDate);
    releaseNotesBean.setReleaseName(release.getName());
          Attachment[] attachments = story.getAttachments();
    Attachment attachment = attachments[0];
    attachment = (Attachment)service.read(attachment);
          AttachmentContent attachmentContent = (AttachmentContent)service.read(attachment.getContent());
    byte[] content = attachmentContent.getContent();
          String twikiTopic = new String(content);
    releaseNotesBean.setTwikiTopic(twikiTopic);
          releaseNotesBeanList.add(releaseNotesBean);
    prepareTopics(releaseNotesBean, packageStoryMap);
    }
       twikiBean.setPackageStoryMap(packageStoryMap);
    twikiBean.setReleaseNotesBeanList(releaseNotesBeanList);
    return twikiBean;
    }