Receiving SocketTimeoutException when using Jira Rest Java Client

Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.

Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

Certain requests to Jira using the Jira Rest java Client (JRJC) result in SocketTimeoutException when they exceed 20 seconds (20,000 milliseconds).

The below snippet can be seen in the error stack trace:

1 Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.net.SocketTimeoutException: 20,000 milliseconds timeout on connection http-outgoing-0 [ACTIVE]] with root cause

Environment

Jira Core 7.x and 8.x

All versions of JRJC (up to 5.2.1 at least)

Diagnosis

The only evidence we need is the SocketTimeoutMessage mentioning the 20,000 milliseconds in the stacktrace:

1 java.net.SocketTimeoutException: 20,000 milliseconds timeout on connection

Cause

JRJC has some hard-coded HTTP request properties, the socketTimeout included:

Excerpt from com.atlassian.httpclient.api.factory.HttpClientOptions

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public static final String OPTION_PROPERTY_PREFIX = "com.atlassian.httpclient.options"; public static final String OPTION_THREAD_WORK_QUEUE_LIMIT = "com.atlassian.httpclient.options.threadWorkQueueLimit"; private final Logger log = LoggerFactory.getLogger(this.getClass()); private List<String> blacklistedAddresses; private String threadPrefix = "httpclient"; private boolean ignoreCookies = false; private int ioThreadCount = Integer.getInteger("com.atlassian.httpclient.options.ioThreadCount", 10); private long ioSelectInterval = (long)Integer.getInteger("com.atlassian.httpclient.options.ioSelectInterval", 1000); private int threadWorkQueueLimit = Integer.getInteger("com.atlassian.httpclient.options.threadWorkQueueLimit", 256); private long connectionTimeout = 5000L; private long socketTimeout = 20000L; private long requestTimeout = 90000L; private int maxTotalConnections = 20; private int maxConnectionsPerHost = 20; private long connectionPoolTimeToLive = 30000L; private long maxCacheObjectSize = 102400L; private int maxCacheEntries = 100; private long maxEntitySize = 104857600L; private long leaseTimeout = 600000L; private int maxCallbackThreadPoolSize = 16; private boolean trustSelfSignedCertificates = false; private Consumer<Request> requestPreparer = (request) -> { }; private String userAgent = "Default"; private ExecutorService callbackExecutor; private ProxyOptions proxyOptions = ProxyOptionsBuilder.create().build(); private HostResolver hostResolver;

Solution

As of version 5.2.1, JRJC doesn't allow the configuration of any of the HTTP Options above.

Two workarounds have been shared on the Community, both consisting of writing custom classes to replace those internal to JRJC:

  • Write 2 custom classes (CustomAsynchronousJiraRestClientFactory and CustomAsynchronousHttpClientFactory) to substitute the default JRJC's

  • Write one custom class with use of Apache libs (CustomBasicHttpAuthenticationHandlerImpl) and use the AsynchronousJiraRestClientFactory.createWithAuthenticationHandler(url, handler) method

Both sample implementations can be seen in the Community thread.

As of Jul 2021, JRJC is still not under active development and we're unable to forecast when such improvements will be implemented.

This request is tracked on https://ecosystem.atlassian.net/browse/JRJC-141

Updated on March 19, 2025

Still need help?

The Atlassian Community is here for you.