I am following the documentation to connect to SOAP API through a proxy.
String proxyUsername = "";
String proxyPassword = "";
String username = "";
String password = "";
String endpoint = "https://test.salesforce.com/services/Soap/u/37.0";
String proxyHost = "";
int proxyPort = 0;
System.setProperty("http.proxyHost", proxyHost);
System.setProperty("http.proxyPort", Integer.toString(proxyPort));
System.setProperty("https.proxyHost", proxyHost);
System.setProperty("https.proxyPort", Integer.toString(proxyPort));
Authenticator.setDefault(new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(proxyUsername, proxyPassword.toCharArray());
}
});
ConnectorConfig partnerConfig = new ConnectorConfig();
partnerConfig.setUsername(username);
partnerConfig.setPassword(password);
partnerConfig.setAuthEndpoint(endpoint);
partnerConfig.setProxy(proxyHost, proxyPort);
partnerConfig.setProxyUsername(proxyUsername);
partnerConfig.setProxyPassword(proxyPassword);
PartnerConnection partner = new PartnerConnection(partnerConfig);
This has thrown:
com.sforce.ws.ConnectionException: Failed to send request to
https://test.salesforce.com/services/Soap/u/37.0 at
com.sforce.ws.transport.SoapConnection.send(SoapConnection.java:121)
at
com.sforce.soap.partner.PartnerConnection.login(PartnerConnection.java:770)
Caused by: java.io.IOException: Unable to tunnel through proxy. Proxy
returns "HTTP/1.0 407 Proxy Authentication Required" at
sun.net.www.protocol.http.HttpURLConnection.doTunneling(Unknown
Source) at
sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown
Source) at
sun.net.www.protocol.http.HttpURLConnection.getOutputStream0(Unknown
Source) at
sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown
Source) at
sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown
Source) at
com.sforce.ws.transport.JdkHttpTransport.connectRaw(JdkHttpTransport.java:136)
at
com.sforce.ws.transport.JdkHttpTransport.connectLocal(JdkHttpTransport.java:100)
at
com.sforce.ws.transport.JdkHttpTransport.connectLocal(JdkHttpTransport.java:95)
at
com.sforce.ws.transport.JdkHttpTransport.connect(JdkHttpTransport.java:91)
at
com.sforce.ws.transport.SoapConnection.send(SoapConnection.java:95)
I debugged the JdkHttpTransport class on Salesforce and it seems to set the proxy but this throws such an exception. I am able to connect through the Rest API though. The soap trace clearly states that it is setting the properties:
WSC: Creating a new connection to
https://test.salesforce.com/services/Soap/u/37.0 Proxy = HTTP @
/x.x.x.x:portname username username
Has anyone found a solution to this issue?
Best Answer
This is quite messy as force-wsc is supposed to handle the authenticated proxy but unfortunately it doesn't. Much worse fact is that dataloader - a similar tool for Apex written in Java works with proxy while wsc is riddled with issues and bugs for proxies. A workaround would be to incorporate a class similar to HttpClientTransport from the dataloader repository and add this line if proxy is enabled:
This should be handling authenticated proxy. However, the need is authenticated proxy for all the API connections (SOAP, Bulk, Metadata, etc.) but this covers only for SOAP. The bulk connection is not equipped with authenticated proxy as it uses
HttpURLConnection
class. I verified this fact with the dataloader.For Bulk connection, there isn't much of a choice than to rewrite the BulkConnection class. Extend the class and overwrite the
doHttpGet()
method. Recommended way is to use Apache'sHttpClient
libraries instead of theHttpURLConnection
class. I haven't analyzed the same solution for Metadata connection yet.It is appalling that a library that is widely used is broken with respect to a feature for so many years.