It's all about the answers!

Ask a question

Getting file (versionable) history using Server Java API


Morten Madsen (3032240) | asked May 12 '17, 7:07 a.m.
edited May 15 '17, 12:39 p.m.
(EDITED 2017-05-15 18:38 CET)

 Hi,


I'm building a followup action to SaveChangeSetLink (IOperationParticipant).

Put simply I want to find the parent change set of a versionable (that is, a change set that includes the parent of my Versionable)

The end goal is to automatically create a "Blocked by" relation to other work items, that are linked to parent change sets. In this way, we can easily see what work items would create gaps in our stream, should we decide to promote these. It makes our deployment planning a lot easier.

I have tried this in two ways. Firstly I've tried to get the change set history of my versionable by using the following method:

ChangeHistoryEntry[] com.ibm.team.scm.common.IScmService.getHistoryForVersionable(ServiceHistoryProvider historyProvider, IVersionableHandle versionableHandle, int limit, boolean examineEras, ISynchronizationTimes[] syncTimes, IRepositoryProgressMonitorHandle monitor) throws TeamRepositoryException
    

But I'm getting the exception in the ccm.log:

java.lang.IllegalStateException: Illegal transaction in progress for service method call.
at com.ibm.team.repository.service.internal.PrimitiveTransactionService.checkValidTransaction(PrimitiveTransactionService.java:86)
at sun.reflect.GeneratedMethodAccessor312.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord.invoke(ExportProxyServiceRecord.java:361)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord.access$0(ExportProxyServiceRecord.java:347)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord$ExportedServiceInvocationHandler.invoke(ExportProxyServiceRecord.java:56)
at com.sun.proxy.$Proxy142.checkValidTransaction(Unknown Source)
at com.ibm.team.repository.service.AbstractService.checkValidTransaction(AbstractService.java:238)
at com.ibm.team.scm.service.internal.ScmService.getHistoryForVersionable(ScmService.java:2696)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord.invoke(ExportProxyServiceRecord.java:361)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord.access$0(ExportProxyServiceRecord.java:347)
at org.eclipse.soda.sat.core.internal.record.ExportProxyServiceRecord$ExportedServiceInvocationHandler.invoke(ExportProxyServiceRecord.java:56)
at com.sun.proxy.$Proxy1292.getHistoryForVersionable(Unknown Source)

I can see in the documentation, that "You cannot call this method within a transaction", so I guess that is my problem. Does anyone know of any other method? 

I've also tried to find the parent Versionable and then use the IScmQueryService to fire off a ChangeSetSearchCriteria, but I'm also getting the "transaction error" once again. I cannot call this service during a transaction.

Any ideas how I can go about this? 

Thanks all,
/Morten.


Comments
Morten Madsen commented May 15 '17, 9:59 a.m.

 I actually got it to work "somewhat" by using:


IScmService scms;

ChangeHistoryEntry[] historyEntries = scms.recentEntries(historyProvider, null, null);

I have to loop all change-sets and look for if cs.afterState() is equal to my Versionable I'm looking for. Quite tedious. And what if my versionable has not been changed recently?

Please, anyone? I just need to be able to find change history for a certain Versionable, by all methods I call seem to be block because I'm "In a transaction".


Ralph Schoon commented May 15 '17, 12:16 p.m. | edited May 15 '17, 12:17 p.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Sorry, never tried that. It might be impossible as you are blocking the DB for everyone else in the follow up action and that might be a long operation.

There is also no information what you want to achieve and why, so it is unlikely that others can come up with reasonable suggestions.


Morten Madsen commented May 15 '17, 12:27 p.m.

Thanks Ralph. I've just clarified my question a bit.


My problem is basically the Server API. I can easily do all this using the Java Client API though.


Ralph Schoon commented May 16 '17, 2:23 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

According to the error message, it looks as if the extension point basically does not allow such a long running operation within the context of a protecting transaction.


If this is the case, you would have to decouple the history search from the follow up action, e.g. trigger a long running background thread or use an asynchronous task.

Accepted answer


permanent link
Morten Madsen (3032240) | answered May 24 '17, 4:49 a.m.
edited May 24 '17, 3:36 p.m.

 I settled for doing the following:




public static IChangeSet findVersionableStateChangeSet(IVersionableHandle version, IProjectAreaHandle projh, IRepositoryItemService rs, IScmService scms, IScmQueryService scmqs, IReportInfoCollector collector, String streamName) throws TeamRepositoryException
{
    IWorkspaceHandle wsh = getStreamWorkspaceHandle(streamName, projh, rs, scmqs, collector);
    
    IComponentHandle[] compHdls = scms.getComponentsContainingVersionable(wsh, version, null, null);
    
    ServiceHistoryProvider historyProvider = ServiceHistoryProvider.FACTORY.create(wsh, compHdls[0]);
    ChangeHistoryEntry[] historyEntries = scms.recentEntries(historyProvider, null, null);
    
    IChangeSet foundChangeSet = searchForVersionableChangeSetInHistory(version, rs, historyEntries);
    
    if (foundChangeSet != null)
        return foundChangeSet; // change set located
    ChangeHistoryHandle chHdl = scms.previousHistory(historyProvider, null, null);
    int loopCount = 0;
    while (chHdl != null && loopCount < 100 / infinite loop protection /)
    {
        historyProvider = ServiceHistoryProvider.FACTORY.create(chHdl);
        
        
        historyEntries = scms.recentEntries(historyProvider, null, null);
        
        foundChangeSet = searchForVersionableChangeSetInHistory(version, rs, historyEntries);
        
        if (foundChangeSet != null)
            return foundChangeSet;
    
        chHdl =scms.previousHistory(historyProvider, null, null);
        
        loopCount++;
    }
    return null; // no changeset with versionable found
}



private static IChangeSet searchForVersionableChangeSetInHistory(IVersionableHandle version, IRepositoryItemService rs, List<ChangeHistoryEntry> historyEntryList) throws TeamRepositoryException
{
    // looping all change-sets
    IChange change;
    IChangeSetHandle csh;
    IChangeSet cs;
    for (ChangeHistoryEntry changeEntry : historyEntryList)
    {
        csh = changeEntry.getChangeSet();
        cs = (IChangeSet) rs.fetchItem(csh, null);
        // looping all changes (files) in each change-set
        for (Object co : cs.changes())
        {
            change = (IChange) co;

            if (change.afterState() != null && change.afterState().getStateId().equals(version.getStateId()))
            {
                return cs;
            }
        }
    }
    return null; // no results found 
}

Ralph Schoon selected this answer as the correct answer

Comments
Ralph Schoon commented May 24 '17, 5:33 a.m.
FORUM ADMINISTRATOR / FORUM MODERATOR / JAZZ DEVELOPER

Thanks for sharing, Morton!


Morten Madsen commented May 24 '17, 3:39 p.m.

 I just updated my code. I've tested it a bit more.


You have to create a new historyProvider and then call recentEntries(). You cannot fetch a ChangeHistoryHandle by using IRepositoryItemService. It cannot resolve it.

The code now works as expected, and you can now find the change-set for a certain Versionable in a components history.


Morten Madsen commented Jun 08 '17, 2:54 p.m.

 But if any RTC developers have an easy way of finding a change-set for a specific Versionable using the Server Java API I'm all ears!


My solution can sometimes run for a minute, because it has to go through all the history of the component sequentially!! :(

Your answer


Register or to post your answer.