52

Using code that was generated with wsimport, can the service endpoint be overridden without having to regenerate the code?

I have written a simple java webservice, following are the steps:

  1. I compile the java class and generate a war file
  2. Deploy the war file to my app server (tomcat)
  3. Access the WSDL via the URL e.g. localhost:8080/service/helloservice?wsdl
  4. use the URL with wsimport.bat to generate client classes for example: wsimport http://localhost:8080/service/helloservice?Wsdl
  5. I use those classes in my client app to call the service

The problem is that is the service is deployed on an app server running on port other than 8080, the communication between client and service never happens. I am trying to know what is the best way to create stubs that does not have server and port hardcoded in the stub used by the client.

GargantuChet
  • 5,691
  • 1
  • 30
  • 41
user363808
  • 527
  • 1
  • 4
  • 5
  • Related question: http://stackoverflow.com/questions/3567856/changing-the-url-on-a-webservice-client-generated-with-wsimport – McDowell Aug 25 '10 at 19:25

2 Answers2

85

Your client can set the end-point in the service "port" at runtime via the BindingProvider interface.

Consider the JAX-WS client in this JAX-WS tutorial. Another way to write this code would be:

HelloService service = new HelloService();
Hello port = service.getHelloPort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(
      BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
      "http://foo:8086/HelloWhatever");
String response = port.sayHello(name);

Caveat: I haven't downloaded the tutorial code and tested this code against it.

McDowell
  • 107,573
  • 31
  • 204
  • 267
  • 1
    I am looking at this. Apparently with code generated with recent versions of JAX-WS wsimport, the WSDL must be accessible at the address specified to wsimport at the time `new HelloService()` is executed (long before the binding provider even has a chance for kicking in). Is the only way to fix this, to have a local copy of the WSDL which can be parsed so the constructor is successful? – Thorbjørn Ravn Andersen Jul 18 '13 at 16:23
  • @ThorbjørnRavnAndersen If memory serves you can set the WSDL location to anything you want at generation time - see the `-wsdllocation` argument for the [wsimport](http://download.oracle.com/javase/6/docs/technotes/tools/#webservices) tool. But I would generally provide it explicitly in an unmanaged client - [example](http://illegalargumentexception.blogspot.co.uk/2011/04/java-jax-ws-web-services-and-clients.html#ws_client). – McDowell Jul 23 '13 at 09:26
  • In my case, it throws exception when creating the service object. How can i solve this? – emre Jan 09 '14 at 15:25
  • 1
    @ThorbjørnRavnAndersen. Recent versions of wsimport has `-clientjar` flag. See https://weblogs.java.net/blog/ramapulavarthi/archive/2010/09/03/wsimport-clientjar-option-ease-client-side-web-service-progra. – peterh Jan 09 '14 at 19:03
  • @emre That isn't enough information - create a new question with the details. – McDowell Jan 10 '14 at 15:33
2

I faced the same issue, and it was terrible coz once the code is moved to production it always looked for the hardcoded WSDL location i.e. Windows C:........etc

I have gone thru various post and pages to find the answer however all was failing then found myself a way by looking at the Service Class generated by JAX-WS imports.

I had to override the JAX-WS WSDL location implementation in my calling class like this.

URL baseUrl;
URL wsdlURL = null;
baseUrl = <your Services>.class.getResource(".");
try {
    wsdlURL = new URL(baseUrl, "http://<your path>?wsdl");
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
}

<your Services> yourServices = new <your Services(wsdlURL,new QName("your namespace", "<your service name>"));
System.out.println(Services.getWSDLDocumentLocation());
YourInterface YourInterfacePort =  yourServices.getServicePort();
BindingProvider bindingProvider = (BindingProvider)YourInterfacePort;
bindingProvider.getRequestContext().put(
          BindingProvider.ENDPOINT_ADDRESS_PROPERTY,      url);

YourInterfacePort.methods();

Rick-777
  • 9,714
  • 5
  • 34
  • 50
  • is there any way to get namespace and service name which is required is service constructor(innew QName("","")) programmatically? we only have url of .wsdl file. why service don't read service name and namespace from .wdsl file itself ? thanks in advance – Khalid Shah May 31 '18 at 05:59