RestTemplate and Proxy Authentication explained

Some time ago I’ve faced with requirements regarding retrieving data using REST behind proxy. There were some code samples available but I was really worried about thread safety and leaking resources. In this post I would like to dig into this topic using RestTemplate from Spring Framework

I will be using this awesome online REST API during this post for testing purposes. You can download source code  with sample project here and try it yourself.

We will be fetching following entity:

public class Post
{
    private int userId;
    private int id;
    private String title;
    private String body;

//... getters and setters omitted

    @Override
    public String toString()
    {
        return String.format("id=%s, userID=%s, title=%s, body=%s", id, userId, StringUtils.abbreviate(title, 20),
                StringUtils.abbreviate(body, 20));
    }
}

I’ve chosen RestTemplate because it allows you to avoid lots of boilerplate code regarding building, closing, handling etc of HttpRequest, HttpResponse etc. Consider sample code written using Apache HttpClient:

public class StandardRestClient implements RestClient
{
    private static final Logger LOG = LoggerFactory.getLogger(StandardRestClient.class);

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public Post getByID(int id)
    {
        CloseableHttpResponse response = null;
        InputStream is = null;
        CloseableHttpClient client = null;

        try
        {
            client = HttpClients.createDefault();

            HttpGet get = new HttpGet(String.format("http://jsonplaceholder.typicode.com/posts/%s", id));
            response = client.execute(get);
            HttpEntity getEntity = response.getEntity();

            is = getEntity.getContent();

            return MAPPER.readValue(is, Post.class);
        } catch (Exception ex)
        {
            LOG.error(String.format("Error fetching post by id = %s", id), ex);
        } finally
        {
            if (client != null)
            {
                try
                {
                    client.close();
                } catch (IOException e)
                {
                    LOG.trace("Error closing client", e);
                }
            }

            if (response != null)
            {
                try
                {
                    response.close();
                } catch (IOException e)
                {
                    LOG.trace("Error closing respose", e);
                }
            }

            if (is != null)
            {
                try
                {
                    is.close();
                } catch (IOException e)
                {
                    LOG.trace("Error closing input stream", e);
                }
            }
        }

        return null;
    }
}

Here is the same functionality using RestTemplate from Spring Framework (also see this post regarding proper URI building):

public class RestTemplateClient implements RestClient
{
    private static final RestTemplate TEMPLATE = new RestTemplate();

    @Override
    public Post getByID(int id)
    {
        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://jsonplaceholder.typicode.com");
        final URI uri = builder.path("posts/{id}").build().expand(id).encode().toUri();
        final ResponseEntity<Post> response = TEMPLATE.getForEntity(uri, Post.class);

        return response.getBody();
    }
}

What I find a little bit annoying is that there is no straightforward way  of using proxy authentication for RestTemplateAfter googling and searching on forums I’ve found elegant way of doing this using Apache HttpComponentsClientHttpRequestFactory.

First of all lets introduce base class (make proxy settings configurable in real scenarios):

public class RestClientBase
{
    private static final String PROXY_HOST = "127.0.0.1";
    private static final int PROXY_PORT = 8888;
    private static final String PROXY_USER = "test";
    private static final String PROXY_PASSWORD = "qwerty";

    private RestTemplate template;

    protected RestTemplate getTemplate()
    {
        if (template == null)
        {
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(new AuthScope(PROXY_HOST, PROXY_PORT),
                    new UsernamePasswordCredentials(PROXY_USER, PROXY_PASSWORD));

            HttpClientBuilder clientBuilder = HttpClientBuilder.create();

            clientBuilder.useSystemProperties();
            clientBuilder.setProxy(new HttpHost(PROXY_HOST, PROXY_PORT));
            clientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());

            CloseableHttpClient client = clientBuilder.build();

            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setHttpClient(client);

            template = new RestTemplate();
            template.setRequestFactory(factory);
        }

        return template;
    }
}
public class RestTemplateClient extends RestClientBase implements RestClient
{
    @Override
    public Post getByID(int id)
    {
        final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://jsonplaceholder.typicode.com");
        final URI uri = builder.path("posts/{id}").build().expand(id).encode().toUri();
        final ResponseEntity<Post> response = getTemplate().getForEntity(uri, Post.class);

        return response.getBody();
    }
}

Is this code thread safe and free from resource leeks? The answer is yes.

Rest Template Sequence

RestTemplate uses ClientRequestFactory  in order to create ClientHttpRequest. In our code we’re using HttpComponentsClientHttpRequestFactory concrete implementation which glues Spring and Apache HttpComponents together. This factory stores concrete implementation (internal Apache’s class) of org.apache.http.client.HttpClient interface and knows how to create org.springframework.http.client.ClientHttpRequest.

Please note that in our code we’re using org.apache.http.impl.client.CloseableHttpClient which is thread safe.

RestTemplate then executes this ClientHttpRequest and passes result of execution (ClientHttpResponse) into org.springframework.web.client.ResponseExtractor for transformation into final business entity. After that ClientHttpResponse is closed

rest-template-class

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: