java jira rest客户端超时问题

时间:2014-03-04 14:58:02

标签: java jira-rest-java-api

我在jira中搜索时得到java.net.SocketTimeoutException。如何增加超时?

代码:

JiraRestClientFactory restClientFactory = new AsynchronousJiraRestClientFactory();
SearchResult results = null;

try {
    URI uri = new URI(jira_url);
    restClient = restClientFactory.createWithBasicHttpAuthentication(uri, jira_username, jira_password);
    final SearchRestClient searchClient = restClient.getSearchClient();
    String jql = searchClient.getFilter(jira_filterid).get().getJql();
    // setting max result to 1000 and start with 0
    results = searchClient.searchJql(jql, 500, 0).claim();
    System.out.println("Took: " + stopWatch.toString() + " to find " + results.getTotal() + " case in jira filter with id " + jira_filterid);
} catch (Exception e) {
    e.printStackTrace();
    System.exit(1);
}
return results;

搜索不应该花这么长时间,我认为这是在做声明()时。

例外:

java.lang.RuntimeException: java.net.SocketTimeoutException
    at com.google.common.base.Throwables.propagate(Throwables.java:160)
    at com.atlassian.httpclient.apache.httpcomponents.DefaultHttpClient$3.apply(DefaultHttpClient.java:256)
    at com.atlassian.httpclient.apache.httpcomponents.DefaultHttpClient$3.apply(DefaultHttpClient.java:249)
    at com.atlassian.util.concurrent.Promises$Of$2.apply(Promises.java:276)
    at com.atlassian.util.concurrent.Promises$Of$2.apply(Promises.java:272)
    at com.atlassian.util.concurrent.Promises$2.onFailure(Promises.java:167)
    at com.google.common.util.concurrent.Futures$4.run(Futures.java:1172)
    at com.google.common.util.concurrent.MoreExecutors$SameThreadExecutorService.execute(MoreExecutors.java:297)
    at com.google.common.util.concurrent.ExecutionList.executeListener(ExecutionList.java:156)
    at com.google.common.util.concurrent.ExecutionList.execute(ExecutionList.java:145)
    at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:202)
    at com.google.common.util.concurrent.SettableFuture.setException(SettableFuture.java:68)
    at com.atlassian.httpclient.apache.httpcomponents.SettableFuturePromiseHttpPromiseAsyncClient$1$2.run(SettableFuturePromiseHttpPromiseAsyncClient.java:59)
    at com.atlassian.httpclient.apache.httpcomponents.SettableFuturePromiseHttpPromiseAsyncClient$ThreadLocalDelegateRunnable$1.run(SettableFuturePromiseHttpPromiseAsyncClient.java:197)
    at com.atlassian.httpclient.apache.httpcomponents.SettableFuturePromiseHttpPromiseAsyncClient.runInContext(SettableFuturePromiseHttpPromiseAsyncClient.java:90)
    at com.atlassian.httpclient.apache.httpcomponents.SettableFuturePromiseHttpPromiseAsyncClient$ThreadLocalDelegateRunnable.run(SettableFuturePromiseHttpPromiseAsyncClient.java:192)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:680)
Caused by: java.net.SocketTimeoutException
    at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.timeout(HttpAsyncRequestExecutor.java:279)
    at org.apache.http.impl.nio.client.LoggingAsyncRequestExecutor.timeout(LoggingAsyncRequestExecutor.java:128)
    at org.apache.http.impl.nio.DefaultHttpClientIODispatch.onTimeout(DefaultHttpClientIODispatch.java:136)
    at org.apache.http.impl.nio.DefaultHttpClientIODispatch.onTimeout(DefaultHttpClientIODispatch.java:50)
    at org.apache.http.impl.nio.reactor.AbstractIODispatch.timeout(AbstractIODispatch.java:169)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.sessionTimedOut(BaseIOReactor.java:257)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.timeoutCheck(AbstractIOReactor.java:494)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.validate(BaseIOReactor.java:207)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:284)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:106)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:604)
    ... 1 more

3 个答案:

答案 0 :(得分:1)

似乎有效的一种解决方法是每次迭代获取100个结果并设置start at

results = searchClient.searchJql(jql, 100, 0).claim();
results1 = searchClient.searchJql(jql, 100, 100).claim();
results2 = searchClient.searchJql(jql, 100, 200).claim();

等等。

答案 1 :(得分:1)

免责声明:我正在使用Groovy programming language,但语法与Java非常相似,因此您应该能够重用代码(提示:在Groovy中不需要使用分号,return语句是可选的,而不是变量声明我只使用deffinal

我使用的是以下库版本(gradle样式):

compile "com.atlassian.jira:jira-rest-java-client-core:4.0.0"
compile "com.atlassian.fugue:fugue:2.2.1"

这里我们有标准的rest客户端定义:

JiraRestClient getJiraRestClient()
{
    // read user specific Jira password settings and build authentification
    final inputFile = new File("${System.getProperty('user.home')}/jiraSettings.json")
    final authInfo = new JsonSlurper().parseText(inputFile.text)

    // setting up the jira client
    def restClient = new AsynchronousJiraRestClientFactory()
        .createWithBasicHttpAuthentication(
            jiraServerUri,
            authInfo.jiraUser.toString(),
            authInfo.jiraPassword.toString())

    restClient
}

我潜入createWithBasicHttpAuthentication函数并提取并调整了代码(仅getClientOptions - 我将套接字超时设置为45秒,查看HttpClientOptions默认设置):

JiraRestClient getJiraRestClient()
{
    return new AsynchronousJiraRestClient(jiraServerUri, getHttpClient());
}

HttpClientOptions getClientOptions()
{
    def options = new HttpClientOptions();
    options.socketTimeout = 45000L;
    options
}

DisposableHttpClient getHttpClient()
{
    final DefaultHttpClientFactory defaultHttpClientFactory =
        new DefaultHttpClientFactory(new AsynchronousHttpClientFactory.NoOpEventPublisher(),
        new AsynchronousHttpClientFactory.RestClientApplicationProperties(jiraServerUri),
        new ThreadLocalContextManager() {
            @Override
            public Object getThreadLocalContext() {
                return null;
            }

            @Override
            public void setThreadLocalContext(Object context) {}

            @Override
            public void clearThreadLocalContext() {}
        });

    final HttpClient httpClient = defaultHttpClientFactory.create(getClientOptions())

    return new AtlassianHttpClientDecorator(httpClient, getAuthenticationHandler()) {
        @Override
        public void destroy() throws Exception {
            defaultHttpClientFactory.dispose(httpClient);
        }
    }
}

BasicHttpAuthenticationHandler getAuthenticationHandler()
{
    // read user specific Jira password settings and build authentification
    final inputFile = new File("${System.getProperty('user.home')}/jiraSettings.json")
    final authInfo = new JsonSlurper().parseText(inputFile.text)

    return new BasicHttpAuthenticationHandler(
        authInfo.jiraUser.toString(),
        authInfo.jiraPassword.toString())
}

缺点是当我切换到jira-rest-java-client的新版本时,我可能会被迫调整此代码,但我真的需要这个,因为即使大量使用分页,时间也只是短暂的

答案 2 :(得分:1)

我无法相信我必须如此深刻才能改变它。你可以使用反射来实现它

    try (JiraRestClient client = clientFactory.createWithBasicHttpAuthentication(new URI(jira.getUrl()), jira.getUsername(), jira.getPassword())) {
        try {
            Field f1 = Class.forName("com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClient").getDeclaredField("httpClient");
            Field f2 = Class.forName("com.atlassian.jira.rest.client.internal.async.AtlassianHttpClientDecorator").getDeclaredField("httpClient");
            Field f3 = Class.forName("com.atlassian.httpclient.apache.httpcomponents.ApacheAsyncHttpClient").getDeclaredField("httpClient");
            Field f4 = Class.forName("org.apache.http.impl.client.cache.CachingHttpAsyncClient").getDeclaredField("backend");
            Field f5 = Class.forName("org.apache.http.impl.nio.client.InternalHttpAsyncClient").getDeclaredField("defaultConfig");
            Field f6 = Class.forName("org.apache.http.client.config.RequestConfig").getDeclaredField("socketTimeout");
            f1.setAccessible(true);
            f2.setAccessible(true);
            f3.setAccessible(true);
            f4.setAccessible(true);
            f5.setAccessible(true);
            f6.setAccessible(true);
            Object requestConfig = f5.get(f4.get(f3.get(f2.get(f1.get(client)))));
            f6.setInt(requestConfig, 120 * 1000);
            f1.setAccessible(false);
            f2.setAccessible(false);
            f3.setAccessible(false);
            f4.setAccessible(false);
            f5.setAccessible(false);
            f6.setAccessible(false);
        } catch (Exception ignore) {
        }
        // now you can start using it :)
    } catch (URISyntaxException | IOException e) {
        logger.error("invalid jira server address: " + jira.getUrl(), e);
        throw new RuntimeException("can not access jira server");
    }

它会给你120秒的插座时间。