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

Saving Timesheet Entry causes Error in Eclipse IDE but not web UI

 I have an application to pull timesheet data from RTC, allow the user to add time and post the information back into RTC.  While developing, I used the web UI to validate my results, and when using the web UI, I can see the timesheets being saved and the data displays.  Now I am trying to use the Eclipse RTC plugin to perform the same functionality.  I can enter the time on a task without a problem in Eclipse.  Once the application pulls the timesheet and the user makes the changes and saves, I can see it in the web UI, but the Eclipse interface gets an error.  The visible error is "Error running operation 'Unnamed'"  I then looked in the log and see the stacktrace below.  I have also attached the save code. below the stack trace.  Does anyone have an idea as to why I am getting the error and what I can do to resolve it?

java.lang.NullPointerException
at com.ibm.team.tpt.ide.ui.timesheet.internal.TimeSheetEntryPartIDE$3.widgetSelected(TimeSheetEntryPartIDE.java:261)
at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:234)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4066)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3657)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2640)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2604)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2438)
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:671)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:664)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:600)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:620)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:575)
at org.eclipse.equinox.launcher.Main.run(Main.java:1408)

public void processTimeSheets (List<RTCTaskEntries> inTasks, RTCClient client, String username, Date startDate) throws Exception {
// Declaration section for reusable objects/variables
if (!TeamPlatform.isStarted()) {
TeamPlatform.startup();
}
service = TeamPlatform.getTeamRepositoryService();
teamRepository = service.getTeamRepository(client.getBaseURL());
teamRepository.registerLoginHandler(new LoginHandler(client.username, client.password));
teamRepository.login(monitor);
itemManager = teamRepository.itemManager();
processClient = (IProcessClientService) teamRepository.getClientLibrary(IProcessClientService.class);
uri = URI.create(client.projectName.replaceAll(" ", "%20"));
projectArea = (IProjectArea) processClient.findProcessArea(uri, null, null);
queryClient = (IQueryClient) teamRepository.getClientLibrary(IQueryClient.class);
wicService = (IWorkItemClient) teamRepository.getClientLibrary(IWorkItemClient.class);
wcm = wicService.getWorkItemWorkingCopyManager();
try {
IWorkItemHandle wiHandle = null;
IWorkItem wi = null;
WorkItemWorkingCopy wc = null;
ITimeSheetEntry tseRec; // Not able to initialize to null due to object type.
IItemHandle refItem = null;
RTCTaskEntries inItem = null;

//  Loop through the task/timesheet entries and post them.  Do not check to see if there were changes, just update everything
Iterator<RTCTaskEntries> inTasksIterator = inTasks.iterator();
while (inTasksIterator.hasNext()) {
inItem = inTasksIterator.next();

// Query where clause parameters.  Look for the project we got in the incoming list.
IQueryableAttribute idAttribute = findAttribute(teamRepository, projectArea, IWorkItem.ID_PROPERTY, null);
Expression idExpression = new AttributeExpression(idAttribute, AttributeOperation.EQUALS, inItem.getId());
Term term = new Term(Operator.AND);
term.add(idExpression);
IQueryResult<IResolvedResult<IWorkItem>> results = queryClient.getResolvedExpressionResults(projectArea, term, IWorkItem.FULL_PROFILE);

if (!results.hasNext(monitor)) {
// There is no project of the type coming in.  This is an error condition and should never occur.
logger.error("Task recieved which we do not recognize.");
}
else {
// Get a working Item so we can make changes.  Need a Copy Manager object to create it so we can save.
wi = results.next(monitor).getItem();
wiHandle = (IWorkItemHandle) wi.getItemHandle();
wcm.connect(wiHandle, IWorkItem.FULL_PROFILE, monitor);
wc = wicService.getWorkItemWorkingCopyManager().getWorkingCopy(wiHandle);
// Get item from WC to mess with so we can use the WC.Save function to write it back
IWorkItem wiCopy = wc.getWorkItem();
IWorkItemHandle copyHandle = (IWorkItemHandle) wiCopy.getItemHandle();
// Move the new duration into the DB
wiCopy.setDuration(new Double(inItem.getEstimate()*60*60*1000).longValue());
// Ensure the epmsBucketId is saved.
if (inItem.getEpmsBucketId() != null) {
for (IAttributeHandle epmsHandle : wiCopy.getCustomAttributes()) {
IAttribute epmsAttrib = (IAttribute) itemManager.fetchCompleteItem(epmsHandle, IItemManager.REFRESH, monitor);
if (epmsAttrib.getIdentifier() == "com.usaa.team.attribute.epmsBucketId") {
wiCopy.removeCustomAttribute(epmsAttrib);
wc.save(monitor);
}
}
IAttribute epmsAttribId = wicService.findAttribute(projectArea, "com.usaa.team.attribute.epmsBucketId", monitor);
wiCopy.setValue(epmsAttribId, inItem.getEpmsBucketId());
}
// If there are time sheet entries post them
Iterator<RTCTimeSheet> inTimeIterator = inItem.getTimeEntries().iterator();
while (inTimeIterator.hasNext()) {
RTCTimeSheet inTs = inTimeIterator.next();
// Iterate through the references and check each time sheet entry to see if it matches the one we have.
IWorkItemReferences itemReference = wc.getReferences();
List<IReference> times = itemReference.getReferences(WorkItemEndPoints.WORK_TIME);
boolean found = false;
for (IReference workTimes : times) {
if (workTimes.isItemReference()) {
refItem = ((IItemReference) workTimes).getReferencedItem();
if (refItem instanceof ITimeSheetEntryHandle) {
tseRec = (ITimeSheetEntry) itemManager.fetchCompleteItem(refItem, IItemManager.REFRESH, monitor);
if (tseRec.getItemId().equals(inTs.getTimeSheetId())) {
// match found
found = true;
ITimeSheetEntry newEntry = wicService.createTimeSheetEntry(projectArea.getProjectArea());
newEntry.setHoursSpent(inTs.getHoursSpent());
newEntry.setTimeSpent(new Duration(new Double(inTs.getHoursSpent()*1000*60*60).longValue()));
newEntry.setStartDate(tseRec.getStartDate());
newEntry.setCreator(tseRec.getCreator());
newEntry.setWorkType(tseRec.getWorkType());
newEntry.setTimeCode(tseRec.getTimeCode());
newEntry.setTimeCodeId(tseRec.getTimeCodeId());
IItemReference tsRef = IReferenceFactory.INSTANCE.createReferenceToItem(newEntry);
itemReference.remove(workTimes);
wc.getDependentItems().remove((IAuditableHandle) refItem);
wc.save(monitor);
itemReference.add(WorkItemEndPoints.WORK_TIME, tsRef);
wc.getDependentItems().add(newEntry);
// Save the changes to the Work Item.
IDetailedStatus result = wc.save(monitor);
if (!result.isOK()) {
switch (result.getCode()) {
case IDetailedStatus.INFO: {logger.info(result.getMessage()); break;}
case IDetailedStatus.WARNING: {logger.warn(result.getMessage()); break;}
case IDetailedStatus.ERROR: {logger.error(result.getMessage()); break;}
}
}
}
}
}
}
if (!found) {
// we did not find the record in the DB and must enter it new
ITimeSheetEntry newEntry = wicService.createTimeSheetEntry(projectArea.getProjectArea());
newEntry.setHoursSpent(inTs.getHoursSpent());
newEntry.setTimeSpent(new Duration(new Double(inTs.getHoursSpent()*1000*60*60).longValue()));
newEntry.setStartDate(inTs.getStartDate());
newEntry.setCreator(getOwner(username, teamRepository));
newEntry.setWorkType(Identifier.create(ILiteral.class, "Task"));
newEntry.setTimeCode("Default");
newEntry.setTimeCodeId("Default");
IItemReference tsRef = IReferenceFactory.INSTANCE.createReferenceToItem(newEntry);
itemReference.add(WorkItemEndPoints.WORK_TIME, tsRef);
wc.getDependentItems().add(newEntry);
// Save the changes to the Work Item.
IDetailedStatus result = wc.save(monitor);
if (!result.isOK()) {
switch (result.getCode()) {
case IDetailedStatus.INFO: {logger.info(result.getMessage()); break;}
case IDetailedStatus.WARNING: {logger.warn(result.getMessage()); break;}
case IDetailedStatus.ERROR: {logger.error(result.getMessage()); break;}
}
}
}
}
// Save the changes to the Work Item.
IDetailedStatus result = wc.save(monitor);
if (!result.isOK()) {
switch (result.getCode()) {
case IDetailedStatus.INFO: {logger.info(result.getMessage()); break;}
case IDetailedStatus.WARNING: {logger.warn(result.getMessage()); break;}
case IDetailedStatus.ERROR: {logger.error(result.getMessage()); break;}
}
}
}
}
}
catch (Exception ex) {
logger.error(ex.getMessage());
throw ex;
}
finally {
teamRepository.logout();
wcm = null;
wicService = null;
queryClient = null;
projectArea = null;
uri = null;
processClient = null;
itemManager = null;
teamRepository = null;
service = null;
}
}

0 votes

Comments

To clarify, it sounds like the data is being saved fine (you can see the updates from the web UI) but when you try to view the updates from the Eclipse UI, you see this error. Correct? Does this only happen if the Eclipse UI has the timesheet open when you update it externally or is the timesheet in Eclipse "broken" forever after your update? And what RTC version (server and Eclipse client)? 

Millard.  That is correct.  Sorry for not providing the versions before.  The brain wasnt quite working on all cylinders.  Eclipse version 3.6.2 and RTC Client version 4.0.  This also occurs in RTC Client verion 4.0.1 running in Eclipse version 3.6.3.  Server is RTC version 4.0.1

Sorry, I had another question in there: After this happens, does your Eclipse client remain in error or will a restart/refresh type action make things work again?

Sorry about that.  Too many things going on at one time. :) 

The error occurs each and every time I go into Eclipse and attempt to access the timesheet tab of the work item.  Restarting has no affect on the behavior.  The other tabs all seem to work fine both before and after I attempt to access the timesheet tab.

Not sure if this could cause issues, but you never disconnect your WorkingCopyManager from the workitem as described here http://rsjazz.wordpress.com/2013/03/20/understanding-and-using-the-rtc-java-client-api/ (search for disconnect). I am not sure of the effects this could have. I usually use WorkitemOperations instead of using the WorkingCopyManager as described here: https://rsjazz.wordpress.com/2012/11/26/manipulating-work-item-states/

Thanks Ralph.  I had placed the disconnect into the code and saw no difference.  I will take a look at the WorkItemOperations and see if that can help out.

William, please provide your solution, as I think others would be interested to see this too. I know that other customers have done automation and even their own UIs for this data, so I assume it can be done. It would be interesting to understand what causes the error - if it is not a defect.

Another thought..... I have seen issues like that in case the links were not created correctly. You might check https://rsjazz.wordpress.com/2012/09/19/the-rtc-workitem-link-api-linking-workitems-to-other-elements/ for how links are created. I think my code looks different than yours. I have no idea if that could cause it however.

Hi Ralph, Sorry this took so long to reply.  I looked at your link, and the basic functionality for your code is here:

IItemReference reference = IReferenceFactory.INSTANCE.createReferenceToItem(fOpposite);
workingCopy.getReferences().add(WorkItemEndPoints.BLOCKS_WORK_ITEM, reference);

In my code, I use the same calls here:

IItemReference tsRef = IReferenceFactory.INSTANCE.createReferenceToItem(newEntry); //Note newEntry is a pointer to the new TimeSheet object.
IWorkItemReferences itemReference = wc.getReferences();
itemReference.add(WorkItemEndPoints.WORK_TIME, tsRef);

not quite sure why the timesheet reference is different than the one you provided as an example.

 Millard,  I finally got back to being able to test this more.  Cleared the log and went in to create the error again to validate what I was seeing before.  Am able to recreate the error, but now get this stack trace.


java.lang.NullPointerException
at com.ibm.team.tpt.ide.ui.timesheet.internal.helper.TimeSheetTableHelper.createTimesheetRow(TimeSheetTableHelper.java:140)
at com.ibm.team.tpt.ide.ui.timesheet.internal.helper.TimeSheetTableHelper.refresh(TimeSheetTableHelper.java:93)
at com.ibm.team.tpt.ide.ui.timesheet.internal.helper.TimeSheetTableHelper.setWeekDate(TimeSheetTableHelper.java:67)

Is there any way you can let me know what the code is trying to do there that is getting the null pointer so I can modify my code to ensure that is not null?

I've emailed a link to this question to the tracking and planning team and asked them to please lend a hand. Hopefully that will get you some more help. 

 Hi Millard,  Just checking to see if there is any word on the possible tracking and planning team help.


Thanks,

Bill

I sent an email to the TAP distribution list last week, apparently there were no takers, sorry. I'd suggest looking at Ralph's example more carefully, perhaps seeing if his will work in your environment. Maybe that will trigger some thoughts on what is missing.


I'll change Ralph's answer to a comment -- perhaps someone else from the community who has worked successfully with this data can lend a hand.

showing 5 of 13 show 8 more comments

Accepted answer

Permanent link
 Ok, I managed to figure out what the problem was.  As it turns out I was saving the incorrect value for the .setTimeCodeId() method.  I was using "Default" when I needed to use "timecode.literal.l1"

Thanks to everyone who helped with ideas and advice.

Bill Hunsicker
Ralph Schoon selected this answer as the correct answer

1 vote

Comments

Thanks for providing this information.

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,938

Question asked: May 22 '13, 1:40 p.m.

Question was seen: 5,439 times

Last updated: Jul 03 '13, 7:38 a.m.

Confirmation Cancel Confirm