Saturday, 14 July 2012

Java Web Service Client - Proxy Configuration

Over the past few days I’ve been integrating an application with the Experian bank account validation service. I’ve been using an Axis2 web service client to generate requests and call the service. My web service client worked fine in our office but when I deployed it on our customers sever (Tomcat running on Windows Server 2008) the client was unable to connect to the target URL.

The Axis client was throwing an UnknownHostException which meant that it wasn't able to resolve the service URL. Strangely though, on the same machine I was able to paste the same URL into a browser and view the service WSDL. After a little heading scratching I realised that all HTTP requests to public URLs had to be routed through our customers ‘bluecoat’ proxy server. I looked around and found a few different ways of doing this - I’ll document each approach and hopefully it’ll help out someone else.

Solution 1 - Set Proxy Details On Axis2 Web Service Stub
Axis provides a convenient way for you to set proxy configuration details if your web service request has to be routed through a proxy. The sample code below shows how this is done.
    
TokenServiceStub tokenService = new TokenServiceStub("https://secure.authenticator.uat.uk.experian.com/WASPAuthenticator/TokenService.asmx");

HttpTransportProperties.ProxyProperties proxyProperties = new HttpTransportProperties.ProxyProperties();
proxyProperties.setDomain("mydomain");
proxyProperties.setProxyName("192.192.135.189");
proxyProperties.setProxyPort(80);
proxyProperties.setUserName("myusername");
proxyProperties.setPassWord("mypassword");
tokenService._getServiceClient().getOptions().setProperty(HTTPConstants.PROXY, proxyProperties);

This code is pretty straight forward and simply sets the proxy details on a HttpTransportProperties.ProxyProperties object. That object is then set on the ServiceClients Options.
When the service stub (TokenServiceStub) is used to call a service method the HTTP request will be routed through the proxy defined above. This approach is very straight forward but is specific to this particular service stub. The next solution is a little more generic and can be used to proxy all web service requests sent by your application.

Solution 2 - Set Proxy Details programmatically as Java System Properties
This approach allows your application to set proxy details as Java system properties. The advantage of this approach is that it will ensure that all HTTP requests generated by your application will be affected which is convenient if you have an application with multiple web service clients. Rather than set proxy properties on each Service stub you can simply set them once as system properties and these values will automatically be used by all web service clients in your application. The code below shows how you can set target proxy details as system properties.
    
System.setProperty("http.proxyHost", "192.155.1168.101");
System.setProperty("http.proxyPort", "80");
System.setProperty("https.proxyHost", "192.167.134.103");
System.setProperty("https.proxyPort", "81");
System.setProperty("http.nonProxyHosts","192.168.170.105|192.168.170.104");
Note
If you need to support HTTPS proxying you can change http.proxyHost to https.proxyHost and http.proxyPort to https.proxyPort

By default these settings will ensure that all HTTP traffic is sent via the specified proxy. But what if you have exceptions to this rule? Luckily the nonProxyHosts setting allows you to specify one or more exceptions to the proxy rule. For example your application may connect to a number of internal and external services. You may only want to route the external service requests through the proxy and let internal requests go directly to their target URL. If this is the case you specify the hosts that you do not want to route through the proxy using nonProxyHosts. You can wildcard values using * and multiple entries are delimited by |.

Solution 3 - Set Proxy Details declaratively as JVM arguments
Another approach (this is the approach I went for) is to set the proxy values as JVM arguments. This means that your application code is free from having to set the proxy details programmatically. For a simple command line application you would set these values as follows.
java -Dhttp.proxyHost=192.164.162.103 -Dhttp.proxyPort=80 –jar StandaloneApp.jar
In most instances though your application will be deployed inside a servlet container like Tomcat. If this is the case you can add these values as JVM arguments that are read on server startup. In my case I had Tomcat set up as a windows service, so to add the proxy settings as JVM arguments I followed these steps.

1.       Go to $TOMCAT_HOME/bin
2.       Open Tomcat6W.exe and the following options will be displayed.
3.       Click on the Java tab
4.       Add your proxy settings to the existing list of JVM parameters as shown in the screenshot below.

Tomcat JVM Proxy Settings

If Tomcat is not running as a windows service you’ll need to add the start up parameters to Catalina.bat or Catalina.sh (depending on what platform you’re running Tomcat).

3 comments:

  1. Hi Brain,
    I want to implemet solution 1 but i am using 1.4
    How do I do that.My Jdeveloepr is unable to find the suitable packge for the same.

    Regards,
    Sankalp

    ReplyDelete
  2. This article is very informative and cool. Thanks for share this beautiful article.
    access torrentHound in UK

    ReplyDelete