1

I am using a JAXWS client. I need to use httpproxy for certain selected requests, so I do not want to set it the environment (which will get applied to all requests). I have not been able to find details on how I could set a httproxy for each request.

The best I could find was this post:

How can I use an HTTP proxy for a JAX-WS request without setting a system-wide property?

but it is not really detailed and gives little clue. Can anyone help?

Community
  • 1
  • 1
user1892775
  • 2,001
  • 6
  • 37
  • 58

2 Answers2

1

I find out what custom SSLSocketFactory never been called (jaxws-rt-2.2.10-b140803.1500). Reflection is the only solution to set proxy per service and not using system wide properties.

void initClient(BindingProvider bindings, String endpoint) {
  Map<String, Object> context = bindings.getRequestContext();
  context.put(BindingProviderProperties.CONNECT_TIMEOUT, CONNECT_TIMEOUT);
  context.put(BindingProviderProperties.REQUEST_TIMEOUT, REQUEST_TIMEOUT);

  Map<String, List<String>> userHeaders = new LinkedHashMap<String, List<String>>();
  context.put("javax.xml.ws.http.request.headers", userHeaders);

  userHeaders.put("User-Agent", Collections.singletonList("{YOUR-USER-AGENT}"));
  userHeaders.put("Proxy-Athorization",
                  Collections.singletonList("Basic " + "{PROXY-AUTH}"));

  if (bindings instanceof WSBindingProvider) {
    WSBindingProvider wsbinding = (WSBindingProvider) bindings;
    WSPortInfo wsport = wsbinding.getPortInfo();
    EndpointAddress addr = wsport.getEndpointAddress();

    try {
      Field proxy = EndpointAddress.class.getDeclaredField("proxy");
      proxy.setAccessible(true);
      proxy.set(addr, PROXY);

      Field url = EndpointAddress.class.getDeclaredField("url");
      url.setAccessible(true);
      url.set(addr, new URL(new URI(endpoint).toASCIIString()));

    } catch (Exception e) {
      log.warning("Edit EndpointAddress error: " + e);
    }
  }
}

Have fun!

lunicon
  • 1,690
  • 1
  • 15
  • 26
0

To my knowledge, there isn't a way in the specification - which means you may have to use a proprietary mechanism in your JAX-WS runtime provider.

For example, if your JAX-WS client application is running in IBM's WebSphere Application Server, you can set the https.proxyHost and https.proxyPort properties on the RequestContext of the BindingProvider (your client):

//Set the https.proxyHost as a property on the RequestContext.
BindingProvider bp = (BindingProvider)port;
bp.getRequestContext().put("https.proxyHost", "proxyHost1.ibm.com");
bp.getRequestContext().put("https.proxyPort", "80");

If you're using Metro, the JAX-WS reference implementation, the documentation says it utilizes the JDK's HttpsURLConnection to make the client HTTPS request, but offers this tip for providing your own SSLSocketFactory by setting a custom property on the RequestContext of the BindingProvider:

SSLSocketFactory sslSocketFactory = ...; //your implementation that uses a proxy
Map<String, Object> ctxt = ((BindingProvider)proxy).getRequestContext();
ctxt.put(JAXWSProperties.SSL_SOCKET_FACTORY, sslSocketFactory);

If you don't want to use the JAXWSProperties constant for the key, you can use its string value:

ctxt.put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory",
         sslSocketFactory);
Scott Heaberlin
  • 3,364
  • 1
  • 23
  • 22
  • Scotth, I am currently running it on a Tomcat server. I had given an attempt to the second approach of using SSLSocketFactory but I was not very sure how to create SSLSocketFactory that would use proxy. SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); How do I make sure that it uses the proxy is what is not clear to me. Can you help on that? – user1892775 Aug 06 '15 at 14:38
  • All my research points to a definitive article on that very topic, but it's rather involved: http://www.javaworld.com/article/2077475/core-java/java-tip-111--implement-https-tunneling-with-jsse.html – Scott Heaberlin Aug 07 '15 at 01:54