Skip to content

Commit

Permalink
Added Apache client property to allow application to specify a retry …
Browse files Browse the repository at this point in the history
…handler.

Change-Id: I38d1a1348f1415e03f8d8b39a86fd48d1b630ff2
  • Loading branch information
agherardi authored and pavelbucek committed Mar 7, 2017
1 parent 6090d54 commit 372b0e5
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
Expand Down Expand Up @@ -145,6 +145,18 @@ public final class ApacheClientProperties {
*/
public static final String REQUEST_CONFIG = "jersey.config.apache.client.requestConfig";

/**
* HttpRequestRetryHandler which will be used to create {@link org.apache.http.client.HttpClient}.
* <p/>
* The value MUST be an instance of {@link org.apache.http.client.HttpRequestRetryHandler}.
* <p/>
* If the property is absent a default retry handler will be used
* ({@link org.apache.http.impl.client.DefaultHttpRequestRetryHandler}).
* <p/>
* The name of the configuration property is <tt>{@value}</tt>.
*/
public static final String RETRY_HANDLER = "jersey.config.apache.client.retryHandler";

/**
* Get the value of the specified property.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2010-2016 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
Expand Down Expand Up @@ -90,6 +90,7 @@
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
Expand Down Expand Up @@ -139,6 +140,7 @@
* <li>{@link ClientProperties#PROXY_PASSWORD}</li>
* <li>{@link ClientProperties#REQUEST_ENTITY_PROCESSING} - default value is {@link RequestEntityProcessing#CHUNKED}</li>
* <li>{@link ApacheClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION}</li>
* <li>{@link ApacheClientProperties#RETRY_HANDLER}</li>
* </ul>
* <p>
* This connector uses {@link RequestEntityProcessing#CHUNKED chunked encoding} as a default setting. This can
Expand Down Expand Up @@ -248,6 +250,11 @@ class ApacheConnector implements Connector {
clientBuilder.setDefaultCredentialsProvider((CredentialsProvider) credentialsProvider);
}

final Object retryHandler = config.getProperties().get(ApacheClientProperties.RETRY_HANDLER);
if (retryHandler != null && (retryHandler instanceof HttpRequestRetryHandler)) {
clientBuilder.setRetryHandler((HttpRequestRetryHandler) retryHandler);
}

final Object proxyUri;
proxyUri = config.getProperty(ClientProperties.PROXY_URI);
if (proxyUri != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013-2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
Expand Down Expand Up @@ -66,6 +66,7 @@
* <li>{@link org.glassfish.jersey.client.ClientProperties#REQUEST_ENTITY_PROCESSING}
* - default value is {@link org.glassfish.jersey.client.RequestEntityProcessing#CHUNKED}</li>
* <li>{@link ApacheClientProperties#PREEMPTIVE_BASIC_AUTHENTICATION}</li>
* <li>{@link ApacheClientProperties#RETRY_HANDLER}</li>
* </ul>
* </p>
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* http://glassfish.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/

package org.glassfish.jersey.apache.connector;

import java.io.IOException;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;

import org.apache.http.client.HttpRequestRetryHandler;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class RetryHandlerTest extends JerseyTest {
private static final int READ_TIMEOUT_MS = 100;

@Override
protected Application configure() {
return new ResourceConfig(RetryHandlerResource.class);
}

@Path("/")
public static class RetryHandlerResource {
private static volatile int postRequestNumber = 0;
private static volatile int getRequestNumber = 0;

// Cause a timeout on the first GET and POST request
@GET
public String get(@Context HttpHeaders h) {
if (getRequestNumber++ == 0) {
try {
Thread.sleep(READ_TIMEOUT_MS * 10);
} catch (InterruptedException ex) {
// ignore
}
}
return "GET";
}

@POST
public String post(@Context HttpHeaders h, String e) {
if (postRequestNumber++ == 0) {
try {
Thread.sleep(READ_TIMEOUT_MS * 10);
} catch (InterruptedException ex) {
// ignore
}
}
return "POST";
}
}

@Test
public void testRetryGet() throws IOException {
ClientConfig cc = new ClientConfig();
cc.connectorProvider(new ApacheConnectorProvider());
cc.property(ApacheClientProperties.RETRY_HANDLER,
(HttpRequestRetryHandler) (exception, executionCount, context) -> true);
cc.property(ClientProperties.READ_TIMEOUT, READ_TIMEOUT_MS);
Client client = ClientBuilder.newClient(cc);

WebTarget r = client.target(getBaseUri());
assertEquals("GET", r.request().get(String.class));
}

@Test
public void testRetryPost() throws IOException {
ClientConfig cc = new ClientConfig();
cc.connectorProvider(new ApacheConnectorProvider());
cc.property(ApacheClientProperties.RETRY_HANDLER,
(HttpRequestRetryHandler) (exception, executionCount, context) -> true);
cc.property(ClientProperties.READ_TIMEOUT, READ_TIMEOUT_MS);
Client client = ClientBuilder.newClient(cc);

WebTarget r = client.target(getBaseUri());
assertEquals("POST", r.request()
.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED)
.post(Entity.text("POST"), String.class));
}
}

0 comments on commit 372b0e5

Please sign in to comment.