Source:
<code><START> public ReviewResult call() throws EmailException, <END> InvalidChangeOperationException, NoSuchChangeException, OrmException { final ReviewResult result = new ReviewResult(); result.setChangeId(changeId); final ChangeControl control = changeControlFactory.validateFor(changeId); final Change change = db.changes().get(changeId); final PatchSet.Id patchSetId = change.currentPatchSetId(); final PatchSet patch = db.patchSets().get(patchSetId); if (!control.canAbandon()) { result.addError(new ReviewResult.Error( ReviewResult.Error.Type.ABANDON_NOT_PERMITTED)); } else if (patch == null) { throw new NoSuchChangeException(changeId); } else { final ChangeMessage cmsg = new ChangeMessage( new ChangeMessage.Key(changeId, ChangeUtil.messageUUID(db)), currentUser.getAccountId(), patchSetId); final StringBuilder msgBuf = new StringBuilder("Patch Set " + patchSetId.get() + ": Abandoned"); if (changeComment != null && changeComment.length() > 0) { msgBuf.append("\n\n"); msgBuf.append(changeComment); } cmsg.setMessage(msgBuf.toString()); final Change updatedChange = db.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() { @Override public Change update(Change change) { if (change.getStatus().isOpen()) { change.setStatus(Change.Status.ABANDONED); ChangeUtil.updated(change); return change; } else { return null; } } }); if (updatedChange == null) { result.addError(new ReviewResult.Error( ReviewResult.Error.Type.CHANGE_IS_CLOSED)); return result; } ChangeUtil.updatedChange(db, currentUser, updatedChange, cmsg, abandonedSenderFactory); hooks.doChangeAbandonedHook(updatedChange, currentUser.getAccount(), changeComment, db); } return result; }</code><technical_language>InvalidChangeOperationException occur anymore, I nice remove method signature here. If do this, remove InvalidChangeOperationException AbandonChangeHandler.call() method</technical_language>

Target:
public ReviewResult call() throws EmailException, NoSuchChangeException, OrmException { final ReviewResult result = new ReviewResult(); result.setChangeId(changeId); final ChangeControl control = changeControlFactory.validateFor(changeId); final Change change = db.changes().get(changeId); final PatchSet.Id patchSetId = change.currentPatchSetId(); final PatchSet patch = db.patchSets().get(patchSetId); if (!control.canAbandon()) { result.addError(new ReviewResult.Error( ReviewResult.Error.Type.ABANDON_NOT_PERMITTED)); } else if (patch == null) { throw new NoSuchChangeException(changeId); } else { final ChangeMessage cmsg = new ChangeMessage( new ChangeMessage.Key(changeId, ChangeUtil.messageUUID(db)), currentUser.getAccountId(), patchSetId); final StringBuilder msgBuf = new StringBuilder("Patch Set " + patchSetId.get() + ": Abandoned"); if (changeComment != null && changeComment.length() > 0) { msgBuf.append("\n\n"); msgBuf.append(changeComment); } cmsg.setMessage(msgBuf.toString()); final Change updatedChange = db.changes().atomicUpdate(changeId, new AtomicUpdate<Change>() { @Override public Change update(Change change) { if (change.getStatus().isOpen()) { change.setStatus(Change.Status.ABANDONED); ChangeUtil.updated(change); return change; } else { return null; } } }); if (updatedChange == null) { result.addError(new ReviewResult.Error( ReviewResult.Error.Type.CHANGE_IS_CLOSED)); return result; } ChangeUtil.updatedChange(db, currentUser, updatedChange, cmsg, abandonedSenderFactory); hooks.doChangeAbandonedHook(updatedChange, currentUser.getAccount(), changeComment, db); } return result; }