Use request scope ClientProperties.READ_TIMEOUT in Jetty && Netty (#4415)

Fixes 4405

Signed-off-by: Jan Supol <jan.supol@oracle.com>
diff --git a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
index d9b42fa..2acd645 100644
--- a/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
+++ b/connectors/jetty-connector/src/main/java/org/glassfish/jersey/jetty/connector/JettyConnector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -301,7 +301,7 @@
         request.method(clientRequest.getMethod());
 
         request.followRedirects(clientRequest.resolveProperty(ClientProperties.FOLLOW_REDIRECTS, true));
-        final Object readTimeout = clientRequest.getConfiguration().getProperties().get(ClientProperties.READ_TIMEOUT);
+        final Object readTimeout = clientRequest.resolveProperty(ClientProperties.READ_TIMEOUT, -1);
         if (readTimeout != null && readTimeout instanceof Integer && (Integer) readTimeout > 0) {
             request.timeout((Integer) readTimeout, TimeUnit.MILLISECONDS);
         }
diff --git a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java
index d29244f..21469f4 100644
--- a/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java
+++ b/connectors/jetty-connector/src/test/java/org/glassfish/jersey/jetty/connector/TimeoutTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -89,7 +89,7 @@
     @Test
     public void testSlow() {
         final URI u = target().getUri();
-        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1000);
+        ClientConfig config = new ClientConfig().property(ClientProperties.READ_TIMEOUT, 1_000);
         config.connectorProvider(new JettyConnectorProvider());
         Client c = ClientBuilder.newClient(config);
         WebTarget t = c.target(u);
@@ -103,4 +103,22 @@
             c.close();
         }
     }
+
+    @Test
+    public void testTimeoutInRequest() {
+        final URI u = target().getUri();
+        ClientConfig config = new ClientConfig();
+        config.connectorProvider(new JettyConnectorProvider());
+        Client c = ClientBuilder.newClient(config);
+        WebTarget t = c.target(u);
+        try {
+            t.path("test/timeout").request().property(ClientProperties.READ_TIMEOUT, 1_000).get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        } finally {
+            c.close();
+        }
+    }
 }
diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
index 373d3c8..e3f3cdf 100644
--- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
+++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java
@@ -99,8 +99,7 @@
         try {
             CompletableFuture<ClientResponse> resultFuture = execute(jerseyRequest);
 
-            Integer timeout = ClientProperties.getValue(jerseyRequest.getConfiguration().getProperties(),
-                                                        ClientProperties.READ_TIMEOUT, 0);
+            Integer timeout = jerseyRequest.resolveProperty(ClientProperties.READ_TIMEOUT, 0);
 
             return (timeout != null && timeout > 0) ? resultFuture.get(timeout, TimeUnit.MILLISECONDS)
                                                     : resultFuture.get();
@@ -183,8 +182,7 @@
                 });
 
                // connect timeout
-               Integer connectTimeout = ClientProperties.getValue(jerseyRequest.getConfiguration().getProperties(),
-                                                                  ClientProperties.CONNECT_TIMEOUT, 0);
+               Integer connectTimeout = jerseyRequest.resolveProperty(ClientProperties.CONNECT_TIMEOUT, 0);
                if (connectTimeout > 0) {
                    b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout);
                }
diff --git a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/TimeoutTest.java b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/TimeoutTest.java
index d035d83..3cd8e8d 100644
--- a/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/TimeoutTest.java
+++ b/connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/TimeoutTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2020 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -64,7 +64,6 @@
 
     @Override
     protected void configureClient(ClientConfig config) {
-        config.property(ClientProperties.READ_TIMEOUT, 1000);
         config.connectorProvider(new NettyConnectorProvider());
     }
 
@@ -78,11 +77,22 @@
     @Test
     public void testSlow() {
         try {
-            target("test/timeout").request().get();
+            target("test/timeout").property(ClientProperties.READ_TIMEOUT, 1_000).request().get();
             fail("Timeout expected.");
         } catch (ProcessingException e) {
             assertThat("Unexpected processing exception cause",
                        e.getCause(), instanceOf(TimeoutException.class));
         }
     }
+
+    @Test
+    public void testTimeoutInRequest() {
+        try {
+            target("test/timeout").request().property(ClientProperties.READ_TIMEOUT, 1_000).get();
+            fail("Timeout expected.");
+        } catch (ProcessingException e) {
+            assertThat("Unexpected processing exception cause",
+                    e.getCause(), instanceOf(TimeoutException.class));
+        }
+    }
 }