How do I set the proxy to be used by the JVM
Asked Answered
J

21

372

Many times, a Java app needs to connect to the Internet. The most common example happens when it is reading an XML file and needs to download its schema.

I am behind a proxy server. How can I set my JVM to use the proxy ?

Jacquard answered 23/9, 2008 at 12:53 Comment(1)
The Oracle documentation around this seems pretty stale (though still probably valid). Here's something more modern from Spring: docs.spring.io/spring-integration/reference/html/…Wallin
J
404

From the Java documentation (not the javadoc API):

http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html

Set the JVM flags http.proxyHost and http.proxyPort when starting your JVM on the command line. This is usually done in a shell script (in Unix) or bat file (in Windows). Here's the example with the Unix shell script:

JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...

When using containers such as JBoss or WebLogic, my solution is to edit the start-up scripts supplied by the vendor.

Many developers are familiar with the Java API (javadocs), but many times the rest of the documentation is overlooked. It contains a lot of interesting information: http://download.oracle.com/javase/6/docs/technotes/guides/


Update : If you do not want to use proxy to resolve some local/intranet hosts, check out the comment from @Tomalak:

Also don't forget the http.nonProxyHosts property!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.example.com|etc"
Jacquard answered 23/9, 2008 at 12:54 Comment(9)
Hi guys, how can you include the username and password in this also? ThanksCranmer
@Cranmer look at http.proxyUser and http.proxyPasswordMerriemerrielle
On my experience: to find the proxy address go to IE -> InternetOptions-> Lan setttingsAshleyashli
@Merriemerrielle http.proxyUser and http.proxyPassword are not Java system properties. They are for the Apache HTTP client.Vilberg
Also, don't forget to configure https.proxyHost and https.proxyPort for HTTPs.Skiver
This should be run at each start-up of the jar, am I right ?Troxler
ADDITIONALLY: Keep an eye on changes done between jdk 1.8.0_025 and jdk 1.8.0_144! If your proxy uses basic authentication it seems as if you have to set the property jdk.http.auth.tunneling.disabledSchemes to an empty string - or remove "basic" from it! The jdk default is to NOT USE basic authentication here! Just add something like -Djdk.http.auth.tunneling.disabledSchemes="" as a jvm-option to allow (all) authentication types.Donatist
http.nonProxyHosts (default: localhost|127.*|[::1]) prevents testing localhost APIs, so I am using this setting for that case -Dhttp.nonProxyHosts= (empty value) to override default. See docs.oracle.com/javase/7/docs/api/java/net/doc-files/…Guillemette
I'm getting following error; help pls - Exception:org.springframework.web.client.ResourceAccessException: I/O error on GET request for "hostname.com/api": Unexpected response code for CONNECT: 400; nested exception is java.io.IOException: Unexpected response code for CONNECT: 400Breastbeating
O
145

To use the system proxy setup:

java -Djava.net.useSystemProxies=true ...

Or programatically:

System.setProperty("java.net.useSystemProxies", "true");

Source: http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html

Overrefinement answered 17/7, 2012 at 17:13 Comment(7)
Awesome setting jvm arguement works for me like charm.. ThanksSeymourseys
I used this code to disable the proxy by "false" value on my SSLSocket. Thanks.Yttrium
Perhaps it is because my proxy requires authentication, but this did not work for me. I wish it did.Glum
This does not work with Proxy Auto-Config (PAC) files, see #10325496Fascinating
This is not working although it shows in VM arguments . Any help appriciatedSkylight
It has been 10 years but I think this only grabs the proxy server ip (or dns) and the port. I don't think java knew how to grab authentication information. Maybe because there are something like dozens of completely unrelated authentication methods. I had to also add lots of code to ask the user for and store and transmit username/password and even that wasn't good enough as there were other types of authentication.Overrefinement
While watching Kotlin - Making API Calls in Kotlin Without External Libraries i added System.setProperty("java.net.useSystemProxies", "true"); to line 9 and it worked like a charm.Mesial
F
92

To set an HTTP/HTTPS and/or SOCKS proxy programmatically:

...

public void setProxy() {
    if (isUseHTTPProxy()) {
        // HTTP/HTTPS Proxy
        System.setProperty("http.proxyHost", getHTTPHost());
        System.setProperty("http.proxyPort", getHTTPPort());
        System.setProperty("https.proxyHost", getHTTPHost());
        System.setProperty("https.proxyPort", getHTTPPort());
        if (isUseHTTPAuth()) {
            String encoded = new String(Base64.encodeBase64((getHTTPUsername() + ":" + getHTTPPassword()).getBytes()));
            con.setRequestProperty("Proxy-Authorization", "Basic " + encoded);
            Authenticator.setDefault(new ProxyAuth(getHTTPUsername(), getHTTPPassword()));
        }
    }
    if (isUseSOCKSProxy()) {
        // SOCKS Proxy
        System.setProperty("socksProxyHost", getSOCKSHost());
        System.setProperty("socksProxyPort", getSOCKSPort());
        if (isUseSOCKSAuth()) {
            System.setProperty("java.net.socks.username", getSOCKSUsername());
            System.setProperty("java.net.socks.password", getSOCKSPassword());
            Authenticator.setDefault(new ProxyAuth(getSOCKSUsername(), getSOCKSPassword()));
        }
    }
}

...

public class ProxyAuth extends Authenticator {
    private PasswordAuthentication auth;

    private ProxyAuth(String user, String password) {
        auth = new PasswordAuthentication(user, password == null ? new char[]{} : password.toCharArray());
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return auth;
    }
}

...

Remember that HTTP proxies and SOCKS proxies operate at different levels in the network stack, so you can use one or the other or both.

Facetiae answered 26/9, 2008 at 0:50 Comment(7)
If "java.net.socks.username/password" are set, why also set an Authenticator?Vilberg
why isn't "con.setRequest..." the con isn't recognized. What libraries are needed for this.Fulgor
+1 for the socks proxy option as sometimes http proxy can't solve my problemMansuetude
In my testing, it works if you only set the default Authenticator—no need to set the authentication propertiesNeoplasm
Doesn't work if you only the system properties. Methinks the java.net.socks.(username|password) properties do nothing.Neoplasm
@DrewStephens They don't even exist.Vilberg
Should this affect every connection made from the Java program? The SOCKS settings seem to have no effect when making the connection through Netty...Saluki
F
50

You can set those flags programmatically this way:

if (needsProxy()) {
    System.setProperty("http.proxyHost",getProxyHost());
    System.setProperty("http.proxyPort",getProxyPort());
} else {
    System.setProperty("http.proxyHost","");
    System.setProperty("http.proxyPort","");
}

Just return the right values from the methods needsProxy(), getProxyHost() and getProxyPort() and you can call this code snippet whenever you want.

Flasher answered 23/9, 2008 at 12:57 Comment(5)
"proxySet" does nothing. Proof: set it to "false". There is not and has never been such a property in the JDK, various books and online references notwithstanding. It came from the long-defunct HotJavaBean, an encapsulated browser, died a death in about 1998.Vilberg
Really are the property names without http/https ?Rusell
This is wrong on three counts: 1: as mentioned, there is no "proxySet" item; 2: "proxyHost" and "proxyPort" need to be "http.proxyHost" and "http.proxyPort" (or the 'https' equivalent); 3: System.getProperties().put(X,Y) is not the same as System.setProperty(X,Y). Other than that, though - great answer.Virgy
Almost correct. See: memorynotfound.com/configure-http-proxy-settings-javaCnidus
@RobCranfill 1: "proxySet" used to be a non-standard flag that was needed by an old JDK but is not necessary anymore; 2: "proxyHost" and "proxyPort" do work, the "http." prefix just restricts them to the HTTP protocol (similar for "https."), 3: here you're right.Brouwer
T
26

JVM uses the proxy to make HTTP calls

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");

This may use user setting proxy

System.setProperty("java.net.useSystemProxies", "true");
Tiu answered 13/1, 2015 at 9:49 Comment(1)
Use System.setProperty instead of System.getProperties().put(...)Glum
D
18

Set the java.net.useSystemProxies property to true. You can set it, for example, through the JAVA_TOOL_OPTIONS environmental variable. In Ubuntu, you can, for example, add the following line to .bashrc:

export JAVA_TOOL_OPTIONS+=" -Djava.net.useSystemProxies=true"

Dragonnade answered 10/9, 2015 at 21:25 Comment(1)
This option not working inside docker, only adding ARG _JAVA_OPTIONS="-Dhttps.proxyHost=myproxy -Dhttps.proxyPort=myport" like this working.. but hardcoding is not feasible...Officeholder
R
18

Combining Sorter's and javabrett/Leonel's answers:

java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar
Repairman answered 12/7, 2017 at 14:12 Comment(0)
A
13

You can set some properties about the proxy server as jvm parameters

-Dhttp.proxyPort=8080, proxyHost, etc.

but if you need pass through an authenticating proxy, you need an authenticator like this example:

ProxyAuthenticator.java

import java.net.*;
import java.io.*;

public class ProxyAuthenticator extends Authenticator {

    private String userName, password;

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(userName, password.toCharArray());
    }

    public ProxyAuthenticator(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }
}

Example.java

    import java.net.Authenticator;
    import ProxyAuthenticator;

public class Example {

    public static void main(String[] args) {
        String username = System.getProperty("proxy.authentication.username");
        String password = System.getProperty("proxy.authentication.password");

                if (username != null && !username.equals("")) {
            Authenticator.setDefault(new ProxyAuthenticator(username, password));
        }

                // here your JVM will be authenticated

    }
}

Based on this reply: http://mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

Alary answered 23/9, 2008 at 17:48 Comment(1)
this does not work. if you are not already authenticated the first line in the main function gets a bunch of null values and the code stops. This doesn't help someone authenticate their jvm so that they can make URL calls through a proxy.Fulgor
L
12

The following shows how to set in Java a proxy with proxy user and proxy password from the command line, which is a very common case. You should not save passwords and hosts in the code, as a rule in the first place.

Passing the system properties in command line with -D and setting them in the code with System.setProperty("name", "value") is equivalent.

But note this

Example that works:

C:\temp>java -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps.proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit com.andreas.JavaNetHttpConnection

But the following does not work:

C:\temp>java com.andreas.JavaNetHttpConnection -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps=proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit

The only difference is the position of the system properties! (before and after the class)

If you have special characters in password, you are allowed to put it in quotes "@MyPass123%", like in the above example.

If you access an HTTPS service, you have to use https.proxyHost, https.proxyPort etc.

If you access an HTTP service, you have to use http.proxyHost, http.proxyPort etc.

Loment answered 25/1, 2017 at 21:47 Comment(1)
ProxyUser and proxyPassword are not Java system properties, but Apache HTTP client properties so this doesn't work in all cases.Staley
H
9

If you want "Socks Proxy", inform the "socksProxyHost" and "socksProxyPort" VM arguments.

e.g.

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
Heliostat answered 30/11, 2017 at 22:2 Comment(0)
O
8

reading an XML file and needs to download its schema

If you are counting on retrieving schemas or DTDs over the internet, you're building a slow, chatty, fragile application. What happens when that remote server hosting the file takes planned or unplanned downtime? Your app breaks. Is that OK?

See http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files

URL's for schemas and the like are best thought of as unique identifiers. Not as requests to actually access that file remotely. Do some google searching on "XML catalog". An XML catalog allows you to host such resources locally, resolving the slowness, chattiness and fragility.

It's basically a permanently cached copy of the remote content. And that's OK, since the remote content will never change. If there's ever an update, it'd be at a different URL. Making the actual retrieval of the resource over the internet especially silly.

Octuple answered 23/9, 2008 at 17:9 Comment(0)
B
7

I am also behind firewall, this worked for me!!

System.setProperty("http.proxyHost", "proxy host addr");
System.setProperty("http.proxyPort", "808");
Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {

        return new PasswordAuthentication("domain\\user","password".toCharArray());
    }
});

URL url = new URL("http://www.google.com/");
URLConnection con = url.openConnection();

BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));

// Read it ...
String inputLine;
while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);

in.close();
Bandeau answered 6/9, 2012 at 7:37 Comment(0)
C
4

Add this before you connect to a URL behind a proxy.

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");
Cyprinodont answered 21/10, 2012 at 6:17 Comment(2)
http.proxyUser and http.proxyPassword are not Java system properties. They are for the Apache HTTP client.Vilberg
Use System.setProperty instead of System.getProperties().put(...)Glum
J
4

This is a minor update, but since Java 7, proxy connections can now be created programmatically rather than through system properties. This may be useful if:

  1. Proxy needs to be dynamically rotated during the program's runtime
  2. Multiple parallel proxies need to be used
  3. Or just make your code cleaner :)

Here's a contrived example in groovy:

// proxy configuration read from file resource under "proxyFileName"
String proxyFileName = "proxy.txt"
String proxyPort = "1234"
String url = "http://www.promised.land"
File testProxyFile = new File(proxyFileName)
URLConnection connection

if (!testProxyFile.exists()) {

    logger.debug "proxyFileName doesn't exist.  Bypassing connection via proxy."
    connection = url.toURL().openConnection()

} else {
    String proxyAddress = testProxyFile.text
    connection = url.toURL().openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, proxyPort)))
}

try {
    connection.connect()
}
catch (Exception e) {
    logger.error e.printStackTrace()
}

Full Reference: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

Jarv answered 1/10, 2015 at 22:34 Comment(1)
This is since Java 1.5, not 1.7.Vilberg
F
3

Recently I've discovered the way to allow JVM to use browser proxy settings. What you need to do is to add ${java.home}/lib/deploy.jar to your project and to init the library like the following:

import com.sun.deploy.net.proxy.DeployProxySelector;
import com.sun.deploy.services.PlatformType;
import com.sun.deploy.services.ServiceManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class ExtendedProxyManager {

    private static final Log logger = LogFactory.getLog(ExtendedProxyManager.class);

    /**
     * After calling this method, proxy settings can be magically retrieved from default browser settings.
     */
    public static boolean init() {
        logger.debug("Init started");

        // Initialization code was taken from com.sun.deploy.ClientContainer:
        ServiceManager
                .setService(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? PlatformType.STANDALONE_TIGER_WIN32
                        : PlatformType.STANDALONE_TIGER_UNIX);

        try {
            // This will call ProxySelector.setDefault():
            DeployProxySelector.reset();
        } catch (Throwable throwable) {
            logger.error("Unable to initialize extended dynamic browser proxy settings support.", throwable);

            return false;
        }

        return true;
    }
}

Afterwards the proxy settings are available to Java API via java.net.ProxySelector.

The only problem with this approach is that you need to start JVM with deploy.jar in bootclasspath e.g. java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. If somebody knows how to overcome this limitation, let me know.

Forgive answered 9/3, 2010 at 14:18 Comment(3)
I wish I could upvote this multiple times, it is the only solution that worked for me; thank you! I had to download the apache commons logging jar from here: commons.apache.org/proper/commons-logging/download_logging.cgi My code in Main(): System.setProperty("java.net.useSystemProxies", "true"); System.out.println("detecting proxies"); ExtendedProxyManager.init();Forereach
What would the xbootclasspath pointing to deploy.jar have for effect, couldn't i take that jar onto my normal classpath (when running without webstart)?Cauvery
in JDK 9, it fails :( Exception in thread "main" java.lang.IllegalAccessError: class ...) cannot access class com.sun.deploy.net.proxy.DeployProxySelector (in module jdk.deploy) because module jdk.deploy does not export com.sun.deploy.net.proxyCauvery
D
3

That works for me:

public void setHttpProxy(boolean isNeedProxy) {
    if (isNeedProxy) {
        System.setProperty("http.proxyHost", getProxyHost());
        System.setProperty("http.proxyPort", getProxyPort());
    } else {
        System.clearProperty("http.proxyHost");
        System.clearProperty("http.proxyPort");
    }
}

P/S: I base on GHad's answer.

Dumbfound answered 3/7, 2014 at 10:43 Comment(1)
This answer doesn't provide anything that hasn't already been said in the other answers.Glum
H
1

As is pointed out in other answers, if you need to use Authenticated proxies, there's no reliable way to do this purely using command-line variables - which is annoying if you're using someone else's application and don't want to mess with the source code.

Will Iverson makes the helpful suggestion over at Using HttpProxy to connect to a host with preemtive authentication to use a Proxy-management tool such as Proxifier ( http://www.proxifier.com/ for Mac OS X and Windows) to handle this.

For example with Proxifier you can set it up to only intercept java commands to be managed and redirected through its (authenticated) proxy. You're going to want to set the proxyHost and proxyPort values to blank in this case though, e.g. pass in -Dhttp.proxyHost= -Dhttp.proxyPort= to your java commands.

Hutment answered 20/12, 2012 at 7:22 Comment(0)
C
1

This is a complete example that worked for me - note that for HTTPS there are separate properties (as per https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html).

Code below sends a request to https://api.myip.com API and prints the response.

public static void main(String[] args) throws IOException {
    System.setProperty("java.net.useSystemProxies", "true");
    final String proxyUser = "proxy-user";
    final String proxyPass = "password123";
    final String host = "some.proxy.io";
    final Integer port = 50201;

    // http
    System.setProperty("http.proxyHost",host);
    System.setProperty("http.proxyPort", String.valueOf(port));
    System.setProperty("http.proxyUser", proxyUser);
    System.setProperty("http.proxyPassword", proxyPass);

    // https
    System.setProperty("https.proxyHost",host);
    System.setProperty("https.proxyPort", String.valueOf(port));
    System.setProperty("https.proxyUser", proxyUser);
    System.setProperty("https.proxyPassword", proxyPass);

    System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
    System.setProperty("jdk.https.auth.tunneling.disabledSchemes", "");

    Authenticator.setDefault(new Authenticator() {
                @Override
                public PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(proxyUser, proxyPass.toCharArray());
                }
        }
    );

    // create and send a https request to myip.com API
    URL url = new URL("https://api.myip.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setRequestMethod("GET");
    int status = connection.getResponseCode();
    
    // read the response
    BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    String responseLine;
    StringBuffer responseContent = new StringBuffer();
    while ((responseLine = in.readLine()) != null) 
        responseContent.append(responseLine);
    
    in.close();
    connection.disconnect();
    
    // print the response
    System.out.println(status);
    System.out.println(responseContent);
}
Cosmetician answered 5/7, 2022 at 20:57 Comment(0)
M
0

I know the question asks explicitly for the functionality inside Java. However, I think it is important to think about whether you SHOULD configure a proxy inside your application. I want to make it very clear, in my point of view, that this is not the best practice. In my experience, this kind of approach led to a complicated setup and boilerplate code.

Mainly due to better portability and separation of concerns, you should try to fix this issue NOT on the application layer. Also, different parts of your application may require different proxy configurations due to inconsistencies inside your dependencies.

Especially if your application runs containerized, it will make your life pretty hard. The main container platforms have their own solutions to implement proxy-configuration by network policies, services, and proxy settings on platform level. Handling Network-Settings on application level will interfere with the platform solutions.

Please consider to configuring your hosting system to use a proxy, to configure the server your application is running on or to configure the container your application is running in.

Mica answered 17/10, 2023 at 6:26 Comment(1)
The JVM can be considered to be the container from some perspectives. Setting this value in a system-wide JVM via lib/net.properties or conf/net.properties can affect many Java applications sharing that JVM. It would be nice if the java.net.useSystemProxies=true worked in all environments and cases, picking up each target system's configured proxy settings instead of having to make sure every invocation has the right environment or arguments.Loudmouthed
S
-1

You can utilize the http.proxy* JVM variables if you're within a standalone JVM but you SHOULD NOT modify their startup scripts and/or do this within your application server (except maybe jboss or tomcat). Instead you should utilize the JAVA Proxy API (not System.setProperty) or utilize the vendor's own configuration options. Both WebSphere and WebLogic have very defined ways of setting up the proxies that are far more powerful than the J2SE one. Additionally, for WebSphere and WebLogic you will likely break your application server in little ways by overriding the startup scripts (particularly the server's interop processes as you might be telling them to use your proxy as well...).

Stickney answered 23/2, 2010 at 19:46 Comment(0)
F
-5

I think configuring WINHTTP will also work.

Many programs including Windows Updates are having problems behind proxy. By setting up WINHTTP will always fix this kind of problems

Formation answered 3/11, 2011 at 20:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.