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();
}
}
}
Accepted answer
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.
One other answer
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);
}
}