It's all about the answers!

Ask a question

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


1
1
Van Lepthien (1313) | asked May 12 '14, 6:49 p.m.
 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();
            }
        }
    }

Accepted answer


permanent link
Ralph Schoon (63.1k33645) | answered May 13 '14, 4:11 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER
edited May 13 '14, 4:12 a.m.
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

Comments
Van Lepthien commented May 21 '14, 4:45 p.m.

Thanks, Ralph.


Implementation is in the next post. 

One other answer



permanent link
Van Lepthien (1313) | answered May 13 '14, 3:58 p.m.
edited May 13 '14, 4:06 p.m.
 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);
        }
    }


Comments
Ralph Schoon commented May 22 '14, 2:23 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

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 to post your answer.