Changing the URL on a webservice client generated with wsimport

skiphoppy picture skiphoppy · Aug 25, 2010 · Viewed 9.6k times · Source

I am trying to write a module for a Java application that accesses a WSDL-described webservice. The source WSDL was downloaded straight from what I believe to be an ASP.NET webservice; the service URL ends in a .asmx extension, and viewing the service URL in a browser shows a link which can be used to download the WSDL.

A key requirement for me is to be able to switch out the service URL without recompiling. The URL given to me is obviously a test server and I know that in production I will be given a production URL to use. I would also like to be able to create a mock server myself for testing, and retain the ability to specify a new URL in the future without recompiling if the service is moved. In fact, I would like for an installation of our application to be able to instantiate multiple instances of the webservice at different URLs.

But my conception doesn't seem to match up with what the wsimport tool is doing for me. Following f1sh's answer here, I generated Java code from my downloaded WSDL with this command:

wsimport -Xnocompile -keep -b binding.xml wsdlFile.wsdl

What I find is that the generated code has a hardcoded reference to my downloaded wsdlFile.wsdl, which contains the service URL. Our application is not going to be running in such a way that it con be configured by editing a WSDL file at runtime. I need to have code that is compiled into my application at build time and can have the service URL set at instantiation time.

I'm not entirely sure why the WSDL even needs to be parsed at runtime; it was my understanding that WSDL provides enough information to generate code which can access the webservice, so I am not sure what it is providing to the generated code other than the service URL, and I am not sure why the service URL is not provided in a constructor or configurable through a method on the generated webservice class. I must be missing something.

What is the general practice for this scenario? Do most people regenerate code for each individual URL that they are going to be using? Is code generated at runtime? Is there another WSDL tool I can use that will build client code with a configurable URL?

Answer

skiphoppy picture skiphoppy · Aug 25, 2010

This answer has been eluding me for a couple of days, but somehow the act of writing the question always focuses me on finding an answer, and a couple more websearches have pointed to it:

http://www.fransvanbuul.net/?p=98

It seems that wsimport created a class, com.example.WebService, which extends javax.xml.ws.Service. This WebService class has two constructors. The no-arg constructor is hardcoded with a file:// URL to use the original WSDL I generated from. (I suppose that if I had supplied an https:// URL on the wsimport command-line, that would be the URL that is hardcoded.) Alternatively I can use a two-arg constructor and supply a WSDL URL at instantiation time! This approach requires me to also supply a javax.xml.namespace.QName object, which I don't yet understand, as the second argument.

Using this two-arg constructor will probably resolve my problem.

It seems that wsimport, which I am using from JDK 1.6, is a part of the JAX-WS package. JDK 1.6, in recent versions, contains JAX-WS 2.1, and JAX-WS 2.2 will address the difficulties I am raising in this question.

I'll be happy to accept any answer that explains some or all of the rest of this situation. I still don't understand why the WSDL is needed at runtime. More practically, it would help me for someone to show me how to use the two-argument constructor, or how to generate my code with JDK 1.6 and JAX-WS 2.2.