Whitecat
Whitecat

Reputation: 4020

How retrieve a list of attachments JIRA rest api via java?

How do I get the list of attachments using JIRA API with Java? I don't need the attachments I just want to know what attachments are there, and their ID. I followed basics of using a query to get issues and I am getting issues but not their attachments. My code:

[String searchQuery = "(created >= '2015/12/1' ) AND (created < '2016/01/1')" 
JiraAuthentication jiraAuth;
JiraRestClient arc;
// Get JiraAuthentication instance to create basic HTTP authentication
// string
jiraAuth = JiraAuthentication.getInstance();

// Make sure you use a new instance
jiraAuth.initInstance();
jiraAuth = JiraAuthentication.getInstance();

// Get the JIRA Rest Client from the basic HTTP authentication
jrc = jiraAuth.getJrc();

// Receive search results based on query
SearchRestClient searchClient = jrc.getSearchClient();
// limit results to 50
SearchResult result = searchClient.searchJql(searchQuery, 50,0, null);
Iterator<BasicIssue> itIssue = result.getIssues().iterator();

// pull information on individual issues.
while (itIssue.hasNext()) {
   BasicIssue lBasicIssue = (BasicIssue) itIssue.next();
   String lIssueKey = lBasicIssue.getKey();
   Issue issue = jrc.getIssueClient().getIssue(lIssueKey, null);
   //This line should print the list of attachments. but everything is always null.
   System.out.println(issue.getAttachements());
}][1]

One example where I am trying to get information is from HBASE-15062, which has the api link. In the api link there doesn't show any attachments but in the actual link there are 4 attachments.

I know about the Jira api call api/2/issue/{issueIdOrKey}/attachments.

I tried : api/2/issue/12925031/attachments I get the response HTTP Status 405 - Method Not Allowed Does this mean I cannot get attachment list or am I just doing the request wrong?

How can I change my java code to get the attachments? Is getting attachments possible from the APACHE JIRA?

Upvotes: 5

Views: 8149

Answers (4)

Anton Tkachov
Anton Tkachov

Reputation: 751

I added parameter fields=*all to search URL. And the server included attachment and comments fields into every issue.

So result URL must be like that:

http://{host}/rest/api/2/search?jql={jqlQuery}&fields=*all

Jira version: 6.3.13.

Workaround from jannis was not working for me. Attachments were absent from history in the changelog.

Upvotes: 1

Peter Kahn
Peter Kahn

Reputation: 13046

It's easier than you think but unexpected. FYI the following is groovy, so the java would be slightly different.

Make sure Attachment shows on your default screen (it must for Jira-Rest-Java-Client's getIssue to populate the getAttachments() result. Sounds crazy, but when I added it and modified Default Field configuration to show it - the following all worked.

    @Test
void addAttachmentTest() {
    String priority = "Blocker"
    String project = "TESTRELENG"
    String summary = "summary addAttachmentTest@${hostName} - ${now.getTime()}"
    String description = "desc addAttachmentTest@${hostName} - ${now.getTime()}"


    // Create Issue
    def issue = controller.addBug(project, priority, summary, description)

    // Create Attachment File
    File attachment = new File("build/testdata/${name.getMethodName()}/attachment.txt")
    attachment.parentFile.mkdirs()
    def expectedText ="${name.getMethodName()} - ${hostName} - ${now.getTime()}"
    attachment.write(expectedText)

    // add attachment
    controller.addAttachment(issue.getKey(), attachment)
    Issue result = controller.getIssue(issue.key)

    // Verify
    File outputFile = new File(attachment.parentFile, "output.txt")
    controller.downloadAttachment(result.key, attachment.name, outputFile)
    assertEquals(attachment.text, outputFile.text)

    // Clean up
    controller.deleteIssue(issue.getKey())
}

JiraController

class JiraController {
   def user
   def url
   def password
   JiraRestClient client
  ....
JiraRestClient getClient() {
    if (null == client) {
        AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory()
        client = factory.create(url.toURI(), new BasicHttpAuthenticationHandler(user,password))

    }
    return client
}
...
Issue getIssue(String issueKey) {
    Issue issue
    try {
        issue = getClient().getIssueClient().getIssue(issueKey).claim()
    } catch (RestClientException e) {
        throw new JiraControllerException("Cannot access ${issueKey} due to permissions.", e)
    }
    return issue
}
...
/**
 * Get Attachment Info object
 * @param issueKey
 * @param attachmentName
 * @return
 */
public Attachment getAttachmentByName(String issueKey, String attachmentName) {
    Issue issue = getIssue(issueKey)
    Attachment found = issue.attachments.find() { Attachment attachment ->
        attachment.filename == attachmentName
    }
    if (!found) {
        def names = issue.attachments.collect() { Attachment a -> a.filename}
        throw new JiraControllerException("Cannot Locate ${issueKey} Attachment ${attachmentName}.  Options: " + names)
    }
    return found
}

Upvotes: 0

Whitecat
Whitecat

Reputation: 4020

I would like to say jannis answer lead me to the answer for this question.

jannis method that adds the parameter ?expand=changelog is the only way to get attachments. The java call for getIssue() needs to change I found how to add parameters here, the api info is here.

getIssue(String issueKey, ProgressMonitor progressMonitor) was used:

Issue issue = jrc.getIssueClient().getIssue(lIssueKey, null);

Issue getIssue(String issueKey, Iterable<IssueRestClient.Expandos> expand, ProgressMonitor progressMonitor) should be used:

   Issue issue = jrc.getIssueClient().getIssue(lIssueKey, Arrays.asList(IssueRestClient.Expandos.CHANGELOG), null);

With the changed call to getIssue the changelog field should be populated. You can then use this field to look at attachments by iterating through the change log. I did this:

private null findAttachments(Issue issue) {
    String FieldName = "Attachment";
    Iterable<ChangelogGroup> changes = issue.getChangelog();
    StringBuilder attachments = new StringBuilder();
    StringBuilder attachmentsIDs = new StringBuilder();

    for (ChangelogGroup change: changes){
        //Multiple change items per group. 
        for(ChangelogItem item: change.getItems()){
            if(item.getField().equals(FieldName)){
                //Gets attachment name.
                attachments.append((String) item.getToString());
                //Gets attachment ID to download if needed.
                attachmentsIDs.append((String) item.getTo());
            }
        }
    }
    //Do something with attachments here..

}

Upvotes: 2

jannis
jannis

Reputation: 5240

From what I can see there is a ticket in Atlassian JIRA for what you experience: REST issue get no longer shows attachments information. Apache's JIRA case is even mentioned in this comment. Quoting another comment:

Attachments are visible in Issue View webpage, but not visible on REST while the field is hidden from the default screen.

The bug has been resolved, but the users don't seem to like it and demand a proper fix:

The "Resolution" above is not a resolution but a workaround for this bug. A proper resolution is for Atlassian to fix this bug so that attachments are always listed in the JSON. There is no way a GUI setting should affect the REST API JSON output - that's clearly wrong! Please reopen and fix this issue.

I agree with them, but it doesn't change the fact that currently your only option to achieve your goal cleanly is to have the issue acted on by Apache. Anyway I seem to have a workaround.

Workaround

I don't know the client tool you're using, so I'll describe the workaround using the pure REST approach. When an attachment is added to an issue, the event is noted in the ticket's change log:

https://issues.apache.org/jira/rest/api/2/issue/HBASE-15062?expand=changelog

{
   (...),          
   "changelog": {
      "startAt":0,
      "maxResults":8,
      "total":8,
      "histories":[
         (...),
         {                 
            "id":"15174314",
            "author":{...},
            "created":"2015-12-31T15:55:43.318+0000",
            "items":[  
               {  
                  "field":"Attachment",
                  "fieldtype":"jira",
                  "from":null,
                  "fromString":null,
                  "to":"12780132",
                  "toString":"HBASE-15062-v0.patch"
               }
            ]
         },
         {  
            "id":"15174320",
            "author":{...},
            "created":"2015-12-31T16:06:03.165+0000",
            "items":[  
               {  
                  "field":"Attachment",
                  "fieldtype":"jira",
                  "from":null,
                  "fromString":null,
                  "to":"12780133",
                  "toString":"HBASE-15062-v1.patch"
               }
            ]
         },             
         {  
            "id":"15184002",
            "author":{...},
            "created":"2016-01-04T08:04:50.969+0000",
            "items":[  
               {  
                  "field":"Attachment",
                  "fieldtype":"jira",
                  "from":null,
                  "fromString":null,
                  "to":"12780273",
                  "toString":"HBASE-15062-v1.patch"
               }
            ]
         },
         {  
            "id":"15187193",
            "author":{...},
            "created":"2016-01-05T21:30:48.977+0000",
            "items":[  
               {  
                  "field":"Attachment",
                  "fieldtype":"jira",
                  "from":null,
                  "fromString":null,
                  "to":"12780629",
                  "toString":"HBASE-15062-v1.patch"
               }
            ]
         },
         (...)
      ]
   }
}

Let's consider the first attachment in the log with id 12780132. Knowing the id you can query the API for the details of the attachment:

https://issues.apache.org/jira/rest/api/2/attachment/12780132

{  
   "self":"https://issues.apache.org/jira/rest/api/2/attachment/12780132",
   "filename":"HBASE-15062-v0.patch",
   "author":{  
      "self":"https://issues.apache.org/jira/rest/api/2/user?username=asamir",
      "key":"asamir",
      "name":"asamir",
      "avatarUrls":{  
         "48x48":"https://issues.apache.org/jira/secure/useravatar?avatarId=10452",
         "24x24":"https://issues.apache.org/jira/secure/useravatar?size=small&avatarId=10452",
         "16x16":"https://issues.apache.org/jira/secure/useravatar?size=xsmall&avatarId=10452",
         "32x32":"https://issues.apache.org/jira/secure/useravatar?size=medium&avatarId=10452"
      },
      "displayName":"Samir Ahmic",
      "active":true
   },
   "created":"2015-12-31T15:55:43.304+0000",
   "size":2173,
   "mimeType":"text/x-patch",
   "properties":{  

   },
   "content":"https://issues.apache.org/jira/secure/attachment/12780132/HBASE-15062-v0.patch"
}

Now you have all the info to download the attachment:

https://issues.apache.org/jira/secure/attachment/12780132/HBASE-15062-v0.patch.

Hope it helps, take care!

Upvotes: 5

Related Questions