0

So there is a SOAP webservice. The targetNamespace in the WSDL dynamically changes based on customer's configurable string. Think of it like

targetNamespace="http://myservice."+ [CouldBeAnyString] + "domain.com"

I have two questions:

  1. My basic research tells me that this is a pretty weird(bad?) practice for developing webservices. Thoughts ?

  2. How does one write a client for such a webservice ? I have tested using jax-ws stub and it isn't compatible when targetNamespace changes. Any other suggestions ? I have been trying to understand dynamic client generation based on wsdl. Would prefer a nicer path though if one exists

Update: I am only the client. Service is provided by someone else. Same customer has multiple environments (eg test,production) where the service is hosted under different targetNamespaces

mishal153
  • 1,498
  • 3
  • 26
  • 37
  • You didn't provide some important context. Are you the service provider or just a client? Why is this WSDL changing? Does the `CouldBeAnyString` value changes for the same client or not? Is this a way to differentiate between the callers? – Bogdan Apr 15 '15 at 19:56
  • Sure. Updated the question with additional info – mishal153 Apr 16 '15 at 15:46
  • The namespace per environment is a strange setup, for me at least it's the first time I see this. Just out of curiosity, any idea why they chose to do it like this? Did the service provider offer some explanations? – Bogdan Apr 26 '15 at 20:03

3 Answers3

0

If the SOAPUI call works even if the targetNamespace has change, you could use a lightweight HTTP library called HTTPCLIENT.

With this library you don't need to generate client, since you are sending the SOAP envelope as a string, the way you would do via SOAPUI.

The downside is to work with Strings.

Eduardo Briguenti Vieira
  • 4,351
  • 3
  • 37
  • 49
0

In theory, it is feasible to create such a Web Service client. Steps:

  • Create Java artifacts based on the WSDL using wsimport.exe of JDK (see: http://www.mkyong.com/webservices/jax-ws/jax-ws-wsimport-tool-example as a reference)
  • For the purposes of the code displayed below, I have used the Calculator WSDL provided by Microsoft
  • Create a "Dynamic Web Project" via Eclipse J2EE
  • Copy the Java artifacts created in step #1, under src folder of the project created in step #2.
  • Create a new Class containing you main method. Normally you would have something similar to:
String wsdlLocation = "127.0.0.1:8088";//Normally you should retrieve that value dynamically
Url url = new URL(wsdlLocation + "?wsdl");// ?wsdl is actually needed
String namespaceURI = "http://Example.org";//Normally you should retrieve that value dynamically
String localPart = "CalculatorService";// as specified in WSDL file (see name attribute of service tag)
QName qname = new QName(namespaceURI, localPart);
CalculatorService service = new CalculatorService(url,qname);
ICalculator iCalculator = service.getICalculator();
int response = iCalculator.add(1, 2);
System.out.println(response);

Now for the tricky part:

  • If you have followed the example with the aforementioned WSDL, you should now have several Annotated Classes having hard-coded namespace (e.g. ICalculator is annotated with:

    @WebResult(name = "result", targetNamespace = "..."))//where ... is similar to http ://example .org

  • Using Java reflection modify all the hard-coded values at runtime (see an example here: https://stackoverflow.com/a/14276270/2625635 on how to modify Annotations)

The aforementioned solution should do the trick.

Community
  • 1
  • 1
G.L.M
  • 1
  • 4
  • @mishal153: Is using an [Axis](https://axis.apache.org/axis/) client an option for you? If so, note that the generated classes are not annotated, therefore you may refactor them in order to retrieve the namespaces in a dynamic manner. – G.L.M Apr 23 '15 at 11:48
0

Most client frameworks allow you to create an interface for calling your client (i.e. they create a contract interface). They also provide an implementation for that interface and it is the implementation that has specific annotations or extends "SOAP aware" classes, while the interface is clean of such details.

From what you posted I assume the clients have the same interface, it's just the implementation namespace that's different? If yes, then write your application to use the interface then build a jar for each environment's implementation. When you deploy on test servers deploy with the test jar, while on production deploy with the production jar (i.e. pick a different implementation for the same contract depending on the environment).

Even if the framework you use doesn't create an interface for you, you can create one yourself and hide the various implementations behind an adapter of some sort.

You can also do something like edubriguenti suggested but I wouldn't go as far as working with strings. Work with SAAJ instead.

Bogdan
  • 23,890
  • 3
  • 69
  • 61