TeamCity 7.0 API features

Jun 5, 2012 at 10:16 AM

I'm pasting here a summary of an email sent by JetBrains about new features in version 7.0 API which the plugin may leverage.

Batch issue fetching support (added in 7.0).

We have introduced a IssueBatchProviderSupport interface that allows TeamCity to ask for multiple issues at once, and if the plugin is able to do that, it could speed up TeamCity significantly.
Here's what you can do to enable batch support for your plugin.
Override a couple of methods in your provider (AbstractIssueProvider provides a default implementation, but doesn't enable it by default):
  public boolean isBatchFetchSupported() {
    return true;

  public Map<String, IssueData> findIssuesByIds(@NotNull Collection<String> ids) {
    return findIssuesByIdsImpl(ids);

Override the following method in your fetcher:

  public Collection<IssueData> getIssuesInBatch(@NotNull final String host,
                                                @NotNull final Collection<String> ids,
                                                @Nullable final Credentials credentials) {
    return defaultGetIssuesInBatch(host, ids, new BatchFetchFunction() {
      public List<IssueData> batchFetch(@NotNull Collection<String> ids) {
        // Your actions here.
defaultGetIssuesInBatch will take care of the cache, you only need to retrieve the data and return it.
All issues that you can't retrieve this way should simply be ignored.
Improved error reporting (added in 7.0).
Now you have a way to tell TeamCity more about what went wrong when the plugin tried to get the issue. We have introduced aRetrieveIssueException base class and several subclasses to encapsulate the error and some details about it. 
AbstractIssueFetcher.fetchHttpFile is aware of that, and you don't need to do anything if you're dealing with HTTP errors only. But in case of XML-RPC, or any other low level API, or if you work with non-trivial issue parsing, you can report the errors like this:
    Element root = FileUtil.parseDocument(input, false);
    if (root == null) {
      throw new UnsupportedException("Failed to parse the issue: no root element found");
    Element bug = root.getChild("bug");
    if (bug == null) {
      throw new UnsupportedException("Failed to parse the issue: no bug element found");
The result will suggest TeamCity users that their issue tracker is not supported, or may be not configured properly to be used with TeamCity.
Besides since 7.0 AbstractIssueFetcher caches not only successful results, but also the errors (for 5 minutes by default), which can also be useful in some cases.
Other additions in 7.0: 
- we've added IssueProvider.isHasRelatedIssues(String), which improves the performance of the build page.
And even though it's much faster now, you're welcome to add your own implementation of this method if you think you can do that even more efficiently.
Additional issue fields (added in 7.1, latest EAP).
From the very beginning TeamCity was working with a limited set of issue fields, and we have changed that recently. The Issue and IssueDatainterfaces support issue summary, state, type, priority, severity out of the box, and also any other information that you wish to fetch.
Besides an old constructor, you can invoke a new one like this:
    return new IssueData(id,
                         CollectionsUtil.asMap(SUMMARY_FIELD, summary,
                                               STATE_FIELD, state,
                                               TYPE_FIELD, type,
                                               PRIORITY_FIELD,  priority,
                                               SEVERITY_FIELD, severity),
                         resolved != null,
Where SUMMARY_FIELD and others are statically imported from the IssueData:
  import static jetbrains.buildServer.issueTracker.IssueData.*;

But in fact you can store any string map you want and then present it to the user. For that you can create a "popup.jsp" file in your resources directory: if it exists, it will be used by TeamCity controller to display issue details.
A simple content of the popup.jsp file might be:

<%@ include file="/include.jsp"%>
<jsp:useBean id="issue" scope="request" type="jetbrains.buildServer.issueTracker.IssueEx"/>
<bs:issueDetailsPopup issue="${issue}" popupClass="my-issue-tracker"/>