Time tracking is one of the biggest pluses for any issue tracking system. JIRA's time tracking is highly configurable and gives plenty of options to manage the work done and the remaining time.
Even though the time tracking in JIRA can be done using the JIRA UI, many users want to do it from the customized pages or third-party applications or plugins. In this recipe, we will see how to do time tracking using the JIRA APIs.
Before we start, each of the operations on worklogs, namely, create, edit, or delete, have different modes. Whenever one of these operations is performed, we can adjust the remaining amount of work to be done in the following ways:
Make sure time tracking is turned on, as explained at http://confluence.atlassian.com/display/JIRA/Configuring+Time+Tracking. It can be enabled from the Administration | System | Issue Features | Time Tracking menu.
Worklogs in JIRA can be managed using the WorklogService
class. It does all the major operations, like creating worklogs, updating them, or deleting them, and that too, in all the four different modes, we have seen earlier.
We will see how to create worklogs, or in other words, log work in the following four modes:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user);
WorklogInputParametersImpl.Builder
object to create the parameters needed for the worklog creation:final WorklogInputParametersImpl.Builder builder = WorklogInputParametersImpl.issue(issue) .timeSpent(timeSpent).startDate(new Date()) .comment(null).visibility(Visibilities.publicVisibility());
Here, issue
is the issue on which work is logged, and timeSpent
is the time that we are going to log in. timeSpent
is a String that represents the format in which time is entered in JIRA , that is, *w *d *h *m
(representing weeks, days, hours, and minutes, where * can be any number).
startDate
is the date from when the work was started. We can also optionally add comments and set the worklog visibility to certain groups or project roles! Visibility is set using the Visibility
bean, which can be constructed using the Visibilities
class, as shown in the preceding example.
WorklogInputParameters
object from the builder and validate it using the WorklogService
:WorklogResult result = this.worklogService.validateCreate(jiraServiceContext, builder.build());
WorklogService
, as shown here:Worklog worklog = this.worklogService .createAndAutoAdjustRemainingEstimate(jiraServiceContext, result, false);
Here, as you can see, the method invoked is createAndAutoAdjustRemainingEstimate
, which will create the worklog and automatically adjust the remaining estimate on the issue.
The method takes as input the service context we created, the WorklogResultobject
after validating the input parameters, and a Boolean, which will be used to dispatch an event, if needed. When the Boolean value is true, the Work Logged On Issue event is fired.
With this, the work will be logged on the issue.
Here, the first three steps are similar to what was discussed in the Auto-adjusting the remaining estimate section. The only difference is that the method invoked on WorklogService
is createAndRetainRemainingEstimate
instead of createAndAutoAdjustRemainingEstimate
.
The full code is as shown:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); final WorklogInputParametersImpl.Builder builder = WorklogInputParametersImpl.issue(issue).timeSpent(timeSpent) .startDate(new Date()).comment(null) .visibility(Visibilities.publicVisibility()); WorklogResult result = this.worklogService .validateCreate(jiraServiceContext, builder.build()); Worklog worklog = this.worklogService.createAndRetainRemainingEstimate (jiraServiceContext, result, false);
Here, the first two steps are similar to what was discussed in the Auto-adjusting the remaining estimate section:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user);
WorklogInputParametersImpl.Builder
object to create the parameters needed for the worklog creation:final WorklogInputParametersImpl.Builder builder = WorklogInputParametersImpl.issue(issue) .timeSpent(timeSpent) .startDate(new Date()). comment(null.visibility(Visibilities.publicVisibility());
final WorklogNewEstimateInputParameters params = builder.newEstimate(newEstimate).buildNewEstimate();
Here, we specify the newEstimate
, which is a string representation similar to timeSpent
. The newEstimate
will be set as the remaining estimate on the issue.
WorklogResult
from WorklogNewEstimateInputParameters
using WorklogService
:WorklogResult result = this.worklogService.validateUpdateWithNewEstimate (jiraServiceContext, params);
The result here will be an instance of WorklogNewEstimateResult
, which will be used in the next step.
WorklogService
:Worklog worklog = this.worklogService.createWithNewRemainingEstimate (jiraServiceContext, (WorklogNewEstimateResult) result, false);
Here, the method used is createWithNewRemainingEstimate
, which sets the newEstimate
as the remaining estimate on the issue, after logging the work using timeSpent
. As you might have noticed, the result object is converted to WorklogNewEstimateResult
.
Here, the process is very similar to the preceding section. The only difference is that the adjustmentAmount
method is used on Builder instead of newEstimate
, and validateCreateWithManuallyAdjustedEstimate
is used on WorklogService
to create the worklog. Also, the WorklogResult
is an instance of WorklogAdjustmentAmountResult
.
The code is as follows:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); final WorklogInputParametersImpl.Builder builder = WorklogInputParametersImpl.issue(issue).timeSpent(timeSpent) .startDate(new Date()).comment(null) .visibility(Visibilities.publicVisibility()); final WorklogAdjustmentAmountInputParameters params = builder.adjustmentAmount(estimateToReduce) .buildAdjustmentAmount(); WorklogResult result = worklogService.validateCreateWithManuallyAdjustedEstimate (jiraServiceContext, params); Worklog worklog = this.worklogService .createWithManuallyAdjustedEstimate (jiraServiceContext, (WorklogAdjustmentAmountResult) result, false);
Once we create or update the worklogs using the WorklogService
API, the changes will be reflected on the issue under the WorkLog tab, as shown in the following screenshot:
You can also see that the graphical representation of time tracking reflects these changes.
When a worklog is deleted, it appears on the Change history as shown:
Similarly, worklogs can be updated using WorklogService
as well.
Updating worklogs is similar to creating them in many ways. Here, we pass the ID of the Worklog
object to be updated instead of the issue we pass while creating a worklog. And, of course, the methods invoked on WorklogService
are different. The following is the code to update a given worklog for the first mode, where the remaining estimate is auto-adjusted:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); final WorklogInputParametersImpl.Builder builder = WorklogInputParametersImpl.worklogId(worklog.getId()) .timeSpent(timeSpent).startDate(new Date()).comment(null) .visibility(Visibilities.publicVisibility()); WorklogResult result = this.worklogService.validateUpdate (jiraServiceContext, builder.build()); Worklog updatedLog = this.worklogService.updateAndAutoAdjustRemainingEstimate (jiraServiceContext, result, false);
As you can see, a builder is created by passing the worklog ID, which is unique across issues. The WorklogResult
here is created using the validateUpdate
method and the worklog is finally updated using the updateAndAutoAdjustRemainingEstimate
method.
The other modes are also similar to how we created the worklogs. Let us quickly see how to update a worklog with a new remaining estimate:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); final WorklogInputParametersImpl.Builder builder = WorklogInputParametersImpl.worklogId(worklog.getId()) .timeSpent(timeSpent).startDate(new Date()) .comment(null).visibility(Visibilities.publicVisibility()); final WorklogNewEstimateInputParameters params = builder.newEstimate(newEstimate).buildNewEstimate(); WorklogResult result = this.worklogService .validateUpdateWithNewEstimate(jiraServiceContext, params); Worklog updatedLog = this.worklogService .updateWithNewRemainingEstimate(jiraServiceContext, (WorklogNewEstimateResult) result, false);
The preceding code looks pretty familiar, doesn't it? It is similar to creating a worklog with a new estimate, except that we call the respective update methods, as discussed before.
We can update a worklog by retaining the estimate and also adjust it by a specified amount of time from the remaining estimate in the same way.
Deleting a worklog is slightly different and maybe easier than creating or updating one, as it doesn't involve building the input parameters.
All we need here is the worklog ID and to create the JIRA Service Context. The code is as shown here:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); WorklogResult worklogResult = worklogService.validateDelete (jiraServiceContext, worklog.getId()); worklogService.deleteAndAutoAdjustRemainingEstimate (jiraServiceContext, worklogResult, false);
Here, the validateDelete
method takes the worklog ID as input and creates a WorklogResult
, which is then used in the deleteAndAutoAdjustRemainingEstimate
method.
This is done in almost the same way as mentioned in the previous section, expect that the deleteAndRetainRemainingEstimate
method is used instead of deleteAndAutoAdjustRemainingEstimate
:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); WorklogResult worklogResult = worklogService.validateDelete (jiraServiceContext, worklog.getId()); worklogService.deleteAndRetainRemainingEstimate (jiraServiceContext, worklogResult, false);
As mentioned before, we don't create the input parameters while deleting worklogs. Instead, the newEstimate
is used to create WorklogResult
, which is an instance of WorklogNewEstimateResult
, while validating. The code is as follows:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); WorklogResult worklogResult = worklogService.validateDeleteWithNewEstimate (jiraServiceContext, worklog.getId(), newEstimate); worklogService.deleteWithNewRemainingEstimate (jiraServiceContext, (WorklogNewEstimateResult) worklogResult, false);
This is also pretty much the same as mentioned in the previous section, except for the method names:
JiraServiceContext jiraServiceContext = new JiraServiceContextImpl(user); WorklogResult worklogResult = worklogService.validateDeleteWithManuallyAdjustedEstimate (jiraServiceContext, worklog.getId(), adjustmentAmount); worklogService.deleteWithManuallyAdjustedEstimate (jiraServiceContext, (WorklogAdjustmentAmountResult) worklogResult, false);
Here, adjustmentAmount
is the value that is used to increase the remaining estimate on the issue.
3.144.151.126