It's all about the answers!

Ask a question

Uploading attachment to RTC Work Item results in 'Save Work Item' failed error when using custom participant


Adam Wereszczynski (9181832) | asked Mar 09 '17, 7:43 a.m.
edited Mar 09 '17, 8:55 a.m.

I have completed the IBM Rational Team Concert (RTC) Extensions Workshop and deployed the "Build on stage change" participant on the server or created my own work item save advisor or participant.

In some special scenarios, uploading attachments to work items in the Web UI fails with the following error message:

'Save Work Item' failed
The following error message is printed to the ccm.log:
(...)
java.lang.ClassCastException: com.ibm.team.workitem.common.internal.model.impl.AttachmentImpl incompatible with com.ibm.team.workitem.common.model.IWorkItem
(...)
at net.jazz.rtcext.workitem.extensions.service.BuildOnStateChangeParticipant.run(BuildOnStateChangeParticipant.java:114)

How can I resolve the problem and upload attachments to work items?

Accepted answer


permanent link
Adam Wereszczynski (9181832) | answered Mar 09 '17, 8:05 a.m.
edited Mar 09 '17, 8:59 a.m. by Ralph Schoon (54.9k23642)
As an extension it is your responsibility to make sure the data you get is the data you want and not to fail.

When the extensions workshop was developed, the issue never came up and thus was not handled.

To resolve the problem you should, in general in all custom extensions, validate every data received from the extension point against it not being null and against it to be providing the expected class or interface. 


For example in a work item save extension check the save parameter is not null, then validate the class returned by the saveParameter.getNewState() method in BuildOnStateChangeParticipant.java is not null and of the correct interface. Do the same with other data such as the old state. 

For example, you can use the following code to check if the old and new Work Item states are instances of IWorkItem and that at least the new state is not null:
/
 * First check that the operation data is work item save data.
 /
Object data = operation.getOperationData();
ISaveParameter saveParameter = null;
/
 * If there is no data or the data is not of the required type or 
 * If the state id has not changed, do not build.
 /
if (data != null && data instanceof ISaveParameter) {
    saveParameter = (ISaveParameter) data; // Get the data
    if (!(saveParameter.getNewState() != null && saveParameter.getNewState() instanceof IWorkItem)) {
        return; // This is not a new work item state to check against e.g. save attachment in the Web UI
    }
    Identifier<istate> oldStateId = null; // New work item check.
    if (saveParameter.getOldState()!= null && saveParameter.getOldState() instanceof IWorkItem) {
        IWorkItem oldState = (IWorkItem) saveParameter.getOldState(); // The old state is a work item
        oldStateId = oldState.getState2(); // Get the old state
    }
    IWorkItem newState = (IWorkItem) saveParameter.getNewState();
    Identifier<istate> newStateId = newState.getState2();
    if ((newStateId != null) && !(newStateId.equals(oldStateId))) {
        /
         * If the work item is not of the proper type, do not build.
         * Note that the work item type and state are hard coded, as is
         * the build definition id. We will change that later. That is
         * when we will start using the participantConfig parameter.
         /
        String newType = newState.getWorkItemType();
        if (newType.equals("com.ibm.team.apt.workItemType.story")) {
            /
             * Finally, if the new state is the target state, build.
             /
            if (newState.getState2().getStringIdentifier().equals(
                    "com.ibm.team.apt.story.tested")) {
                build("our.integration.build");
            }
        }
    }
}
</istate></istate>

    </pre>
    <br>
</div>
Ralph Schoon selected this answer as the correct answer

Your answer


Register or to post your answer.