Jazz Forum Welcome to the Jazz Community Forum Connect and collaborate with IBM Engineering experts and users

How do I add attachments with the plain java API without user updates causing MultiStaleDataException?

 I have a Plain Java API program that uploads attachment for workitems on the server. It runs fine by itself, but if a user modifies a workitem through the web interface while the upload is running, the upload fails with a MultiStaleDataException.

Is there some way to 
a)  get the update to complete, even if there is an update?
or (less desirable)
b) lock the issue so that the users cannot update the issue while the upload is executing?

Thanks,

Van

My code looks like:

    private static void loadSingleFile(File file, IWorkItem workItem,
            IProgressMonitor monitor) throws FileNotFoundException,
            TeamRepositoryException {
        IWorkItemWorkingCopyManager wcManager = wiClient.getWorkItemWorkingCopyManager();
        wcManager.connect(workItem, WorkItem.FULL_PROFILE, monitor);
        WorkItemWorkingCopy wiWC = wcManager.getWorkingCopy(workItem);
        IWorkItem wi = wiWC.getWorkItem();
        String fileName = file.getName();
        System.out.println("   Issue "+wi.getId()+" uploading " + fileName);
        InputStream is = new BufferedInputStream(new FileInputStream(file));
        WIAttachmentUpload upload = new WIAttachmentUpload(fileName, is,
                IContent.ENCODING_UTF_8);
        upload.run(wi, monitor);
        wcManager.disconnect(workItem);
    }

    private static class WIAttachmentUpload extends WorkItemOperation {

        private static void attachStream(WorkItemWorkingCopy workingCopy,
                String name, InputStream inputStream, String encoding,
                IProgressMonitor monitor) throws TeamRepositoryException,
                IOException {

            String contentType = null;
            try {
                contentType = URLConnection
                        .guessContentTypeFromStream(inputStream);
            } catch (IOException e) {
            }
            if (contentType == null) {
                contentType = IContent.CONTENT_TYPE_UNKNOWN;
            }

            IWorkItem workItem = workingCopy.getWorkItem();
            IWorkItemClient workItemClient = (IWorkItemClient) ((ITeamRepository) workItem
                    .getOrigin()).getClientLibrary(IWorkItemClient.class);

            System.err.println("Uploading file '" + name + "' for WorkItem "
                    + workItem.getId());

            monitor.worked(1);

            try {
                IAttachment newAttachment = workItemClient.createAttachment(
                        workItem.getProjectArea(), name, "", contentType,
                        encoding, inputStream, monitor);

                newAttachment = (IAttachment) newAttachment.getWorkingCopy();
                newAttachment = workItemClient.saveAttachment(newAttachment,
                        monitor);
                IItemReference reference = WorkItemLinkTypes
                        .createAttachmentReference(newAttachment);
                workingCopy.getReferences().add(WorkItemEndPoints.ATTACHMENT,
                        reference);
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
            }
        }

        private String fFileName;
        private String fEncoding;
        private InputStream fStream;

        public WIAttachmentUpload(String fileName, InputStream fileStream,
                String encoding) {
            super("Initializing Work Item", IWorkItem.FULL_PROFILE);
            fFileName = fileName;
            fStream = fileStream;
            fEncoding = encoding;
        }

        @Override
        protected void execute(WorkItemWorkingCopy workingCopy,
                IProgressMonitor monitor) throws TeamRepositoryException {
            try {
                attachStream(workingCopy, fFileName, fStream, fEncoding,
                        monitor);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

1

1 vote


Accepted answer

Permanent link
I use this code in Plain Java Client API automation. I think all you can try is to resolve the work item again after uploading the attachment again, directly before you attach. If it fails, you could resolve it again. After so many tries, fail.
Van Lepthien selected this answer as the correct answer

0 votes

Comments

Thanks, Ralph.


Implementation is in the next post. 


One other answer

Permanent link
 I fixed this by removing the attachment creation from the WorkItemOperation extension. 

The attachment is created separately and the WorkItemOperation extension now only adds the attachment to the work item's references. 

The new code:

    private static IWorkItemClient wiClient;

    private static void loadSingleFile(File file, IWorkItem workItem,
            IProgressMonitor monitor) throws FileNotFoundException,
            TeamRepositoryException {
        String fileName = file.getName();
        System.out.println("   Issue " + workItem.getId() + " uploading " + fileName);
        InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
        String contentType = null;
        try {
            contentType = URLConnection.guessContentTypeFromStream(inputStream);
        } catch (IOException e) {
        }
        if (contentType == null) {
            contentType = IContent.CONTENT_TYPE_UNKNOWN;
        }
        IAttachment newAttachment = wiClient.createAttachment(
                workItem.getProjectArea(), fileName, "", contentType,
                IContent.ENCODING_UTF_8, inputStream, monitor);
        newAttachment = (IAttachment) newAttachment.getWorkingCopy();
        newAttachment = wiClient.saveAttachment(newAttachment, monitor);
        IItemReference reference = WorkItemLinkTypes.createAttachmentReference(newAttachment);
        WIAttachmentUpload upload = new WIAttachmentUpload(reference);
        IWorkItem wi = wiClient.findWorkItemById(workItem.getId(), IWorkItem.FULL_PROFILE, monitor);
        upload.run(wi, monitor);
    }

    private static class WIAttachmentUpload extends WorkItemOperation {
        private IItemReference attrReference;

        public WIAttachmentUpload(IItemReference reference) {
            super("Add Work Item Attributes", IWorkItem.FULL_PROFILE);
            attrReference = reference;
        }

        @Override
        protected void execute(WorkItemWorkingCopy workingCopy,
                IProgressMonitor monitor) throws TeamRepositoryException {
            try {
                addReference(workingCopy, monitor);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void addReference(WorkItemWorkingCopy workingCopy,
                IProgressMonitor monitor) {
            workingCopy.getReferences().add(WorkItemEndPoints.ATTACHMENT,
                    attrReference);
        }
    }

0 votes

Comments

Thanks for providing your code. I linked your answer to the blog post describing what you saw and how to solve this.

Your answer

Register or log in to post your answer.

Dashboards and work items are no longer publicly available, so some links may be invalid. We now provide similar information through other means. Learn more here.

Search context
Follow this question

By Email: 

Once you sign in you will be able to subscribe for any updates here.

By RSS:

Answers
Answers and Comments
Question details
× 169
× 26
× 1

Question asked: May 12 '14, 6:49 p.m.

Question was seen: 6,170 times

Last updated: May 22 '14, 2:23 a.m.

Confirmation Cancel Confirm