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

Auto create a snapshot after Deliver occurs Error

Hello!

I'm writing an operation(com.ibm.team.scm.server.deliver) participant that auto creates a snapshot for a stream after deliver change sets to it. To finish that I'm using the following code(only list the key code) :
IScmService scm = getService(IScmService.class);   
WorkspaceItemListResult result = scm.createBaselineSet(destWorkspace, new IComponentHandle[0], 
now.toString(), now.toString() + "SnapShot", true, 
null, null, null);

The code running without exception in my  operation participant but an error occurs in Eclipse which show in following picture:

I think the reason why this error occurs is I have modified stream(create snapshot) before the change sets really delivered to it, but I have no idea how to fix or avoid it.

Is there any solution? I will be very appreciate!

0 votes

Comments

Are you sure you have written a participant (that runs after the operation)? The behavior would be understandable if you have an Advisor (that runs before the operation is performed). Is this a client or a server extension?

 Well, I'm sure I have written a participant that runs after the deliver operation and the behavior is really strange. My extension is server-side and the server is RTC 3.0.1.3.


Anyway, I'am going to post all my code here. The following code is my  follow-up action(participant): 
public class AutoTakeSnapshotParticipant extends AbstractService implements IOperationParticipant {

public void run(AdvisableOperation operation,
IProcessConfigurationElement participantConfig,
IParticipantInfoCollector collector, IProgressMonitor monitor)
throws TeamRepositoryException {
try {
//Check if is necessary to create snapshot
Object operationData = operation.getOperationData();
boolean isCheck = false;
DeliverOperationData data = null;
IScmDeltaSource deltaSrc = null;
if(operationData instanceof DeliverOperationData )
{
data = (DeliverOperationData) operationData;
isCheck = true;
} else if( operationData instanceof IScmDeltaSource ) {
deltaSrc = (IScmDeltaSource) operationData;
isCheck = true;
}
if (!isCheck) {
return;
}
//Get Service I need
IRepositoryItemService repoService = getService(IRepositoryItemService.class);
IScmService scm = getService(IScmService.class);   
if (data != null) {
System.out.println(data.getSourceWorkspace().getName());
System.out.println(data.getDestWorkspace().getName());
IWorkspace destWs = data.getDestWorkspace();
if (destWs.isStream()) {
System.out.println(destWs.isImmutable());
}
Date now = new Date(System.currentTimeMillis());
WorkspaceItemListResult result = scm.createBaselineSet(destWs, new IComponentHandle[0], 
now.toString(), now.toString() + "SnapShot", true, 
null, null, null);
// WorkspaceRefreshParameter wrp = IScmService.DELTA_PER_INVOCATION;
//scm.refreshWorkspaces(new WorkspaceRefreshParameter[] {wrp}, null);
System.out.println(result.getItems().size());
if (!result.getItems().isEmpty()) { 
IBaselineSet baselineSet = (IBaselineSet) result.getItems().get(0);
System.out.println(baselineSet);
}
}
if (deltaSrc != null) {
IWorkspace ws = null;
Map<UUID,IComponentHandle> components = new HashMap<UUID, IComponentHandle>();
for (IChangeHistoryOperandDelta delta : deltaSrc.getDeltas(IChangeHistoryOperandDelta.class)) {
if( ws == null )
ws = (IWorkspace) repoService.fetchItem(delta.getTargetWorkspace(),null);
for( IComponentHandle ch : delta.getComponents() )
components.put(ch.getItemId(), ch);
}
System.out.println("2:" + ws.getName());
}
} catch (Exception e) {
e.printStackTrace();
collector.addInfo(collector.createExceptionInfo("Exception Occurs in follow-up action: " + e.getMessage(), e));
}
}
}

And the following xml I have configure in plugin.xml(plz ignore the chinese part which is name or description): 
<operationParticipant
            class="net.oppo.rtcext.workitem.extensions.service.AutoTakeSnapshotParticipant"
            id="net.oppo.rtcext.workitem.extensions.service.autoTakeSnapshot"
            name="交付变更集后创建快照"
            operationId="com.ibm.team.scm.server.deliver">
         <description>
            在每个变更集交付之后为流创建一个快照
         </description>
         <extensionService
               componentId="net.oppo.rtcext.workitem.extensions.service.autoTakeSnapshot"
               implementationClass="net.oppo.rtcext.workitem.extensions.service.AutoTakeSnapshotParticipant">
            <prerequisites>
              <requiredService interface="com.ibm.team.repository.service.IRepositoryItemService" />
              <requiredService interface="com.ibm.team.scm.common.IScmService"/>
            </prerequisites>
         </extensionService>
      </operationParticipant>

By the way, although I don't want to spread the attention in this question but I had written a follow-up action to modify a workitem after it has been saved and I got the same error.

I have forwarded this question to people who know more than I do. You could look at https://jazz.net/wiki/bin/view/Main/CustomPreconditionsTable#operations and try one of the other operations. There are several stages in scm. I know that SCM is a bit different, which could explain your error. However, I have written several participants for work item save operations that work. You can find example code at http://rsjazz.wordpress.com.

One example is: http://rsjazz.wordpress.com/2012/11/30/a-create-approval-work-item-save-participant/ you have to make sure to resolve the latest state of the work item to be able to modify it.

You might need to go through Hong Kong to get at the blog.

In case of WordPress blogs, you can append the string ".nyud.net" to the blog URL and it should open just fine. For instance, if the main blog is located at labnol.wordpress.com, you can access a mirror image of this site from labnol.wordpress.com.nyud.net."

We have seen http://rsjazz.wordpress.com.nyud.net/ is accessible through Hong Kong.

 HI, Ralph!  Firstly , thank you for your help!

I have no idea why I'm not be able to open the link  http://rsjazz.wordpress.com.nyud.net/ but I understand what you did through the name a-create-approval-work-item-save-participant/.

However, I have try to reproduce the exception I meet before. I found that if I modify the workitem that provide from participant and save it, I will get the stale data exception, just like following code:
ISaveParameter saveParameter = (ISaveParameter) data;
IAuditable auditable = saveParameter.getNewState();
//get currentWorkitem
IWorkItem newWorkItem = (IWorkItem)auditable;
//modify summary
newWorkItem.setHTMLSummary(XMLString.createFromPlainText("test"));
//save workitem again after we save it in UI
workItemServer.saveWorkItem2(newWorkItem, wiRefs, null);

But If I retrieved the workitem myself and save it's working copy after modify it, that would be fine.

Hah, it confuse me for a time. 

Still, I need to ask, any progress in the scm question?

I can not comment on why officials in China have chosen to block wordpress. I can see that it (still) can be reached through Hong Kong. You can look at the code of the post here: http://dl.dropbox.com/u/12668004/CreateApprovalParticipant/20121130_CreateApprovalParticipants.zip
The key is this code piece

        // Get the full state of the parent work item so we can edit it
        IWorkItem workingCopy = (IWorkItem) fWorkItemServer
                .getAuditableCommon()
                .resolveAuditable(workItem, IWorkItem.FULL_PROFILE, monitor)
                .getWorkingCopy();

    IApprovals approvals = workingCopy.getApprovals();
    IApprovalDescriptor descriptor = approvals.createDescriptor(
            WorkItemApprovals.REVIEW_TYPE.getIdentifier(), APPROVAL_NAME);
    for (IContributorHandle approver : approvers) {
        IApproval approval = approvals.createApproval(descriptor, approver);
        approvals.add(approval);
    }


You need to get the latest state of the work item first, get a working copy and manipulate that.

For the modification of the delivery, I can't tell if that is possible or not.

I think I understand the participant behavior of save work item now. Thank you for your reminder.


But still I don't know the reason why both advisor and participant are run before the change sets are delivered to the stream(At least it look like that, I have try to setup a break point in my participant to block it and use another eclipse to create a snapshot for that stream but it's also blocked).

As I see it, both an advisor as well as a participant run before the transaction is finally committed, because the advisor as well as the participant need to be able to block the transaction to be finalized in case they detect an error.

I don't know what exactly you mean, all kind of operation advisor and participant or just only deliver operation advisor and participant?


If you mean all kind of advisor and participant, I think it doesn't make sense because the example we talked before that modify and save current work item in it's participant has prove there were two transactions or the participant would be block by the following code(our save need to wait for the UI save finish but the UI save won't finish until our save finish, it's deadlock):
workItemServer.saveWorkItem2(newWorkItem, wiRefs, null);

Am I right?


Hi Di,

I meant all advisors and participants. In the workitem save participant you are actually causing a new save operation as a by product. in saveWorkItem3() you can actually pass a string to, for instance, detect that the same participant is triggered by the additional modification, which prevents you from ungracefully dying in a recursion....

Other paricipants would for example start a build and prevent saving the work item if that is not possible like in the extensions workshop.

  HI Ralph,


I know that call method 'saveWorkItem2' will trig the participant and I think I am already prevent the recursive call, for example in my testing participant procedure(pseudo code):
workitemCopy = currentWorkitem.getWorkingCopy;
if ( workitemCopy.summary.contains("test")) {
    return;
} else {
    workitemCopy.summary += "test";
    workItemServer.saveWorkItem2(workitemCopy, wiRefs, null);
}

The question that confuse me is if the participant block the transaction before it finish, then why the method 'saveWorkItem2' won't block here? Dosen't transaction mean if it isn't end, no any other transaction can submit?
But if the transaction end before the participant, all make sense.

I don't know how all that is implemented. I can just say from what I have been seeing.  I would assume all the operations are run in a certain context that keeps together what happens. The second save would then issue a new save operation that is queued after the current one and isolates the changes. I could imagine that the second save could be cancelled if the first one is canceled in a later step.

The infrastructure has to isolate and manage multiple concurrent operations, so some framework is involved, that handles the database transactions.

Thank you for the explanation, I think you are right. 


So the different between advisor and participant is just enter the queue of current transaction early or later? 
There is a further question, Is that mean the thing that I can do in advisor also can be done in participant?

The other way around. You are not supposed to/should not modify the work item in the advisor.  The class implementing the advisor does assume you don't. See http://rsjazz.wordpress.com/2012/12/14/do-not-modify-the-triggering-element-in-an-operationadvisor/

/**
* Operation advisors are run before an operation is invoked to decide whether
* or not the operation should be executed. Advisors check conditions and
* report problems via the collector they are given. If an advisor reports a
* serious problem with an operation, the operation will not be executed (though
* subsequent advisors may still be checked).
*

<br>
* Advisors may not make modifications to data which is persisted in the
<br>
* repository. Clients wishing to participate in operations by modifying data
<br>
* should implement an {<a href="/forum/users/linkboston">@link</a> IOperationParticipant} instead.

<br>
*
<br>
* Operation advisors are contributed on the client and server via the
<br>
* com.ibm.team.process.client.operationAdvisors




You could modify e.g. a work item in an advisor today and you would even not have to save it. This would also, today, not cause an additional call to work item advisors.

In the future the extension point might track that and prevent you from doing it. Today it does not.

showing 5 of 14 show 9 more comments


3 answers

Permanent link
 SCM uses SaveItemInTxn and RepositoryTransactionContext. This means that there are 3 layers of delayed writes. Writing any kind of code that runs after an SCM write operation is very difficult and I am not sure that we intend to support that at all.

0 votes

Comments

0_0' Thank you for your reply, and is there any way to do that? 


Permanent link
 Hi Ralph,

I understand why the development team design the advisor and participant like what you say, and thank you for your 
recommendation.

About my scm question, do you know is there any transaction lock in RTC java api?
If there is, I can modify the RTC eclipse source code to create a snapshot after deliver.

Or, is there any way to add my transaction (create snapshot) to the system transaction queue in participant?

0 votes


Permanent link

 @Di Tang any update on this ?? did you resolved the above stale data error ? if yes can you tell me how you resolved, i have also slimier error    

0 votes

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
× 10,927
× 1,201
× 73

Question asked: Jan 12 '13, 1:30 a.m.

Question was seen: 6,340 times

Last updated: Jul 18 '18, 12:53 p.m.

Related questions
Confirmation Cancel Confirm