Customizing our connections with proxies

Nowadays, it is clear that Java / Java EE are mainly back end technologies. In this role, it is quite common for a Java / Java EE application to connect to different systems to collect data or perform different operations, using REST web services, SOAP web services, sockets or other technologies that allow different systems to exchange information without a human being interference.

In complex systems, in addition to the big number of external and internal connections the system performs, we need to consider that sometimes we need to use one or more different proxies to reach the destiny.

Sometime the objects we are using to create and manage connections allow us to add this proxy information inside, but not always, and this creates always a big headache. We usually end, wrapping our object inside others that support a proxy addition.

Today, I have another suggestion that, in some cases, can do our lives easier. This option is to extend the ProxySelector class. This class has been around for a long time, you can find the API page for different Java version:

The idea is to extend this class and implement its abstract methods and assign this extended class as the default class for our system. Each time that a connection is going to be performed, the method List<Proxy> select(URI uri) is going to be called. In this method, we can decide if we need to add a proxy or not to this connection.

The resultant code should be something like that:

package com.wordpress.binarycoders.proxy;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class CustomProxySelector extends ProxySelector {

    private static final int DEFAULT_PORT = 80;

    private final ProxySelector defaultProxySelector;

    private Proxy proxy;

    private List<Proxy> proxyList = new ArrayList<Proxy>();

    public CustomProxySelector(String proxyHost, Integer proxyPort) {

        defaultProxySelector = ProxySelector.getDefault();

        proxy = new Proxy(Proxy.Type.HTTP,
                          new InetSocketAddress(proxyHost,
                                                (proxyPort == null) ?
                                                 DEFAULT_PORT :
                                                 proxyPort));
        proxyList.add(proxy);
    }

    @Override
    public List<Proxy> select(URI uri) {

        if (uri == null) {
            throw new IllegalArgumentException("URI cannot be null.");
        }

        if (needsProxy(uri)) {
            return proxyList;
        }

        return def.select(uri);
    }

    @Override
    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {

        if ((uri == null) || (sa == null) || (ioe == null)) {
            throw new IllegalArgumentException("Arguments cannot be null.");
        }

        defaultProxySelector.connectFailed(uri, sa, ioe);
    }

    private boolean needsProxy(URI uri) {
        return uri.getHost().contains("urlNeedsProxy");
    }
}

As you can see, we only need a few lines to make it works. Obviously, we can make as complex as you want the method to determinate if a connection needs a proxy or not.

To use this class, we only need to add a simple line to the code in the start point of our application:

ProxySelector.setDefault(new CustomProxySelector(proxyHost, proxyPort));

And that’s all. Now with a few tests we can check if our solution works fine or not.

See you.

Note: Take care if your application share the server with other applications. Remember to test all of them just in case.

Advertisements
Customizing our connections with proxies