34

I have written simple REST web service client class which uses the JAX-RS 2.0 client API to make REST requests. I am trying to figure out how to set a request timeout for each invocation. Here is the code for a request:

Client client = ClientBuilder.newBuilder().build();
WebTarget resourceTarget = client.target(restServiceUrl)
        .path("{regsysID}/{appointmentID}/")
        .resolveTemplate("regsysID", regSysId)
        .resolveTemplate("appointmentID", apptId);

Invocation invocation = resourceTarget.request(MediaType.APPLICATION_JSON).buildPut(null);
String createSessionJson = invocation.invoke(String.class);
Jens Piegsa
  • 7,399
  • 5
  • 58
  • 106
sarabdeep singh
  • 878
  • 1
  • 11
  • 16

6 Answers6

50

Note: this is a new method available on JAX-RS 2.1

This is a very old post but the below code will work for both jersey and resteasy.

ClientBuilder clientBuilder = ClientBuilder.newBuilder();
clientBuilder.connectTimeout(10, TimeUnit.SECONDS);
clientBuilder.readTimeout(12, TimeUnit.SECONDS);
Client client = clientBuilder.build();
Panu Haaramo
  • 2,932
  • 19
  • 41
Pravat
  • 495
  • 4
  • 3
  • 8
    A down-vote is unwarranted. The answer is still helpful even though the question is about 2.0. At the time the question was asked 2.0 was the most current. Now that 2.1 is the most current, information up to date. Up-vote from me. – Paul Samsotha May 03 '18 at 20:37
  • 1
    This in fact is the only answer which does not rely on a specific implementation. Probably the other authors haven't understood the difference between API and implementation. – Benjamin Marwell Mar 29 '19 at 10:38
25

You can do this by creating a ClientConfig first and providing it as an argument when creating the new client.

import org.glassfish.jersey.client.ClientProperties;

ClientConfig configuration = new ClientConfig();
configuration.property(ClientProperties.CONNECT_TIMEOUT, 1000);
configuration.property(ClientProperties.READ_TIMEOUT, 1000);
Client client = ClientBuilder.newClient(configuration);
Jarekczek
  • 7,456
  • 3
  • 46
  • 66
Jeroen
  • 3,076
  • 1
  • 17
  • 16
  • 7
    I think you are assuming that I am using jersey as implementation for JAXRS. Actually, I am using resteasy. But I wanted to find out if it is possible to do in generic way using pure JAX RS 2.0 client API. – sarabdeep singh Mar 27 '14 at 18:27
  • 1
    @Jeroen Did you find a pure solution? I need this. – Jdruwe Jun 03 '15 at 13:43
  • 2
    No generic JAX-RS 2.0 way to do it? – icordoba Dec 08 '15 at 18:24
  • 3
    @icordoba Try: client.property(org.apache.cxf.message.Message.CONNECTION_TIMEOUT, 300000) // 5min .property(Message.RECEIVE_TIMEOUT, 300000) // 5min – Custard Jan 25 '16 at 15:51
  • Thanks @Custard. The problem is that I don't have CXF in the class path as it is just used internally by Liberty Profile as JAX-RS 2.0 provider. That is why I was looking on doing it in a generic way, not relying on any implementation classes. – icordoba Jan 26 '16 at 16:40
  • 2
    Answer from @Custard works great. Searched many sites for a solution before finding that nugget in this thread. Just use string constants instead of cxf class constants if you want to keep it 'generic' (e.g. "javax.xml.ws.client.connectionTimeout", "javax.xml.ws.client.receiveTimeout"). – patrickd Jan 30 '17 at 14:20
13

With Resteasy this can be accomplished by building your Client as such.

Client client = new ResteasyClientBuilder()
    .establishConnectionTimeout(2, TimeUnit.SECONDS)
    .socketTimeout(2, TimeUnit.SECONDS)
    .build();

I have not seen a list of standard configuration properties you could set via ClientBuilder.newClient(Configuration configuration) which would be needed to make this portable.

codylerum
  • 218
  • 2
  • 7
  • Thanks @codylerum. Yes i think it will be nice to have a way to specify such properties in JAX-RS 2.0 ClientBuilder class. – sarabdeep singh Jul 25 '14 at 18:52
  • 4
    **Beware!** This works only for GET requests. For any other - there is an issue in Resteasy->Apache.HttpClient integration, which drops all client configurations and substitutes them with default values. – Maxim Karavaev Sep 19 '16 at 08:43
  • @MaximKaravaev any way of solving what you point? I also need to make a post. – jlanza Oct 20 '16 at 11:37
  • @jlanza I have to add dependencies to the both libraries (HTTPClient & RestEASY) and override one method, which causes this problem. See next comment for the code sample – Maxim Karavaev Dec 08 '16 at 05:54
5

First, you have to add relevant dependencies (here is for the WildFly 10.1):

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-client</artifactId>
    <version>3.0.14.Final</version>
    <scope>provided</scope>
</dependency>

Next - create a normal Apache HttpClient and push it the RestEasy Enginge with overriding one method, which causes the problem:

// create here a normal Apache HttpClient with all parameters, that you need
HttpClient httpClient = createHttpClient(connectTimeout,
                                         socketTimeout,
                                         connectionRequestTimeout,
                                         maxTotalHTTPConnections);
// Deprecated Apache classes cleanup https://issues.jboss.org/browse/RESTEASY-1357
// Client Framework not honoring connection timeouts Apache Client 4.3 https://issues.jboss.org/browse/RESTEASY-975
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient) {
        @Override
        protected void loadHttpMethod(ClientInvocation request, HttpRequestBase httpMethod) throws Exception {
            super.loadHttpMethod(request, httpMethod);
            httpMethod.setParams(new BasicHttpParams());
        }
    };

return new ResteasyClientBuilder().httpEngine(engine).build();

Have a look at https://issues.jboss.org/browse/RESTEASY-975 Seems, that the problem was just resolved in the version 3.1.0.Final.

Maxim Karavaev
  • 186
  • 1
  • 9
1

For people stuck with older JAX-RS 2.0 API and old Resteasy implementation, you may use this method:

Client client = new ResteasyClientBuilder()             
     .establishConnectionTimeout(3, TimeUnit.SECONDS)
     .socketTimeout(5, TimeUnit.SECONDS).build();

Despite the name, socketTimeout stands for "read timeout", since by the docs, it stands for "The timeout for waiting for data".

dliber
  • 281
  • 2
  • 5
0

If you are using Jersey 2.x Here it is the simple solution it's work for me

import com.jclient.JClient;

Client c = Client.create();
WebResource webResource = c.resource("requestUrl");
c.setConnectTimeout(yourMins*60*1000);
Nazik
  • 8,696
  • 27
  • 77
  • 123