Attempting to copy attachment yields java.io.FileNotFoundException Error

Illi Eisner February 16, 2016

Hello,

I am running JIRA version 6.3.15 with ScriptRunner version 3.0.16 and am trying to implement a groovy script that automatically copies file attachments of an issue when it is cloned.  For example, suppose Issue B is a clone of Issue A, where Issue A has the attachments I want to copy.  The link relationship between the two issues is defined as "Issue B clones Issue A."  This script is meant to copy the attachments from Issue A into Issue B.  

Unfortunately, the script repeatedly fails with the following error every time it attempts to create and write the copied attachment to disk:

It seems that everything works fine up to the point of writing the copied attachment to disk.  Attachments are successfully added to the database and are even listed in the Issue View as 0KB attachments with the correct filename.  I am running using the ScriptRunner Console, though I tried triggering this script on a workflow transition, which yielded the same results.  Here is a copy of the groovy script I am running:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.util.PathUtils
import com.atlassian.jira.issue.attachment.Attachment
import com.atlassian.jira.issue.link.IssueLink
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.attachment.CreateAttachmentParamsBean

// ********   FOR TESTING ONLY: Reference a Test Issue Object    ********
IssueManager im = ComponentAccessor.getIssueManager()
MutableIssue issue = im.getIssueObject("TEST-1150")
// ************************************************************************

// Instantiate the PathUtils library to get the paths associated with the attachments
pathUtils = new PathUtils();
// Instantiate Issue Link Manager required to iterate through linked JIRA's for a given issue
def linkManager = ComponentAccessor.getIssueLinkManager()
//Instantiate Attachment Manager required to iterate through and issue's attachments
def attachmentManager = ComponentAccessor.getAttachmentManager()
//Instantiate Path Manager required for copying attachments to new JIRA
def pathManager = ComponentAccessor.getAttachmentPathManager()
// Get the user object for the current user
def user = ComponentAccessor.getJiraAuthenticationContext()?.getUser()
// Specify the link-type we wish to iterate for attachments
def linkType = "Cloners"
// Iterate through each ["Cloners"] linked issue
for (IssueLink link in linkManager.getOutwardLinks(issue.id)) {
    if (linkType.contains(link.issueLinkType.name)) {
    
        linkedIssue = link.getDestinationObject()
		// If linked issue contains attachments, iterate through and copy over each attachment
        for(Attachment attachment in linkedIssue.getAttachments()) {
			
            // Define path to which attachment is to be written (i.e. copied)
            filePath = pathUtils.joinPaths(pathManager.attachmentPath, linkedIssue.projectObject.key, issue.key, attachment.id.toString())
            File newFile = new File(filePath)
     
            // Define and build Attachment bean
            def bean = new CreateAttachmentParamsBean.Builder()
                .file(newFile)
                .filename(attachment.getFilename().toString())
                .contentType(attachment.getMimetype().toString())
                .author(attachment.getAuthorObject())
                .issue(issue)
                .zip (false)
                .thumbnailable(true)
                .createdTime(attachment.getCreated())
                .copySourceFile(true)
                .build()
            attachmentManager.createAttachment (bean)
        }
    }
}

I went through several troubleshooting steps I found elsewhere on Atlassian Answers, most which dealt with folder permissions.   I went through the steps and am pretty certain that the folder permissions are correct:

JIRA Home Folder Permissions:

JIRA_HOME_FOLDER_PERMISSIONS.png

JIRA Install Folder Permissions:

 JIRA_INSTALL_FOLDER_PERMISSIONS.png

I also checked to ensure that our JIRA instance was run by the correct user (i.e. jira):

JIRA Process Details:
USER       PID %CPU %MEM    VSZ   RSS 	TTY    STAT START   TIME COMMAND
jira     30995  3.6 35.0 5298644 2686144 ?     Sl   Feb01 105:35 /opt/atlassian/jira/jre//bin/java -Djava

At this point I am pretty much stuck.  I tried implementing the code with and without beans (i.e. deprecated methods) to no avail.  I confirmed folder permissions, file permissions, host user permissions, my own JIRA user permissions and found nothing to explain this issue.  Any help or insight you could offer would be very much appreciated.  Thanks!

2 answers

0 votes
Adam Barylak
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 20, 2016

I just ran into this today, and it is actually because the attachment did NOT exist at the location I was building with the PathUtils function.  This is because JIRA has modified the attachment location and added a numbered folder between the Project Key and the Issue Key in the path.  I assume that this folder may change in time, and I don't know of a way to determine that number dynamically.

However, I did find 2 new functions in the AttachmentManger which will simplify this process and worked successfully for me. https://docs.atlassian.com/jira/7.0.0/com/atlassian/jira/issue/AttachmentManager.html

You can look each of those up yourself for the details, but i used the second one which will copy ALL attachments from one issue to another.  This makes it very simple and no loops or checking for a valid path is needed.

Hope this helps you as it did for my use case.

 

Eric Smith January 11, 2017

Any chance you can provide a copy of the complete post function code? Im trying to write a post function to copy an attachment from an issue to its linked issue, and im running into a fair amount of issues.

Adam Barylak
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 16, 2017

With all the information in the original question and the information i provided, this should be more than enough to modify any existing code to use the new functions.  For further information, please refer to the api documentation linked above as well as all ScriptRunner documentation provided by Adaptavist.  Thanks.

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 22, 2016

Not sure what you're doing wrong there, probably nothing. Can you try with a simple script from the console, to rule out problems with permissions:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.CreateAttachmentParamsBean
def attachmentManager = ComponentAccessor.getAttachmentManager()

def issueManager = ComponentAccessor.getIssueManager()
def issue = issueManager.getIssueObject("JRA-45")
def bean = new CreateAttachmentParamsBean.Builder()
    .file(new File("/var/tmp/timeline.PNG"))
    .filename("timeline.PNG")
    .issue(issue)
    .zip (false)
    .thumbnailable(true)
    .createdTime(new Date())
    .copySourceFile(true)
    .build()
attachmentManager.createAttachment (bean)

I think you most likely have your link directions or your paths confused. Zero byte files suggest you're copying from the same file to the same file or something.

Can you add some logging for both issue keys and the file paths?

Suggest an answer

Log in or Sign up to answer