Pages

Saturday, April 11, 2009

Changing WSDL url ( endpoint) in JAX-WS client

In JDeveloper 11G you can easily generate a JAX-WS client, just create a new Web Service proxy client and use the WSDL Url. This client works perfectly in your test environment but when you want to deploy this to an other environment then you will get IO errors. This is because JDeveloper generates JAX-WS client code with a WSDL Url.Off course you can change this file with the new WSDL Url but you can also change the endpoint url. IMPORTANT this only works when the original WSDL Url is still accessible. So don't use this.

@WebServiceRef
private static HelloWorldService helloWorldService;

public static void main(String [] args)
{
String newAddress = System.getProperty("wsdlurl");
helloWorldService = new HelloWorldService();
HelloWorld helloWorld = helloWorldService.getHelloWorldPort();
System.out.println("old address "+((BindingProvider)helloWorld).getRequestContext().get(BindingProvider.ENDPOINT_ADDRESS_PROPERTY));
((BindingProvider)helloWorld).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY , newAddress);

System.out.println(helloWorld.sayHello());


The other and better way is to use the other proxy client constructor and provide the new WDSL url.

@WebServiceRef
private static HelloWorldService helloWorldService;

public static void main(String [] args)
{
String newAddress = System.getProperty("wsdlurl");
try {
helloWorldService = new HelloWorldService( new URL(newAddress)
, new QName("http://ws.whitehorses.nl/", "HelloWorldService"));
} catch (MalformedURLException e) {
e.printStackTrace();
}
HelloWorld helloWorld = helloWorldService.getHelloWorldPort();
System.out.println(helloWorld.sayHello());
}

The last way ( if you use the jax-ws-client in a web application) is to add a jax-ws-catalog.xml file to the ear deployment of your web application, this will replace the WSDL url at runtime.
the file looks like this. See Gerard Devision blog for more information.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
<system systemId="http://localhost:7101/ws_helloworld-Project1-context-root/HelloWorldServicePort?wsdl"
uri="http://localhost:7001/ws_helloworld/HelloWorldServicePort?WSDL"/>
</catalog>

12 comments:

  1. Thanks a bunch, I was having trouble using the ENDPOINT_ADDRESS_PROPERTY solution and the metro documentation wasn't much help. This got me on track.

    ReplyDelete
  2. Thanks a lot for posting this. This helped me a lot !!

    ReplyDelete
  3. Thanks for the good and rare stuff... I am searching for this info, thanks a ton. However Is there a way in the jax-ws-catalog.xml to mention all the DEV, Test, Prod URLs at a time, and take it based on the environment?

    May be In the first two opetions we can do some trick to read the endpoint URL from a property file based on the environment.

    ReplyDelete
    Replies
    1. Hi,

      I think it can only contain one entry but maybe you can do some rewrite based on a parameter.

      this can help you
      http://jax-ws.java.net/nonav/2.1.5/docs/catalog-support.html
      http://jax-ws.java.net/nonav/2.1.5/docs/catalog.html

      also you can override it in the ear deployment, so your war with the ws can still be the same for environments

      thanks

      Delete
  4. Hi,
    Can you please provide an example for the THIRD option. First two way I could do. But the third option is completely clueless. I got the jax-ws-catalog.xml and the content is same as you mentioned, however how to check it whether its reflecting or not.

    Waiting for your quick help.
    Thanks
    Khaleel

    ReplyDelete
    Replies
    1. Hi,

      you need to deploy the web service twice on 2 different j2ee servers and some logging to the server log.

      Now make a client web application/ servlet which calls the service on 1 , deploy it some where and test it , now change it , deploy it again and see if server 2 is called.

      good luck

      Delete
  5. Hi Edwin,
    I have created a Hello worrl BPEL process and deployed on my local SOA Server.
    The WSDL URL is active at "http://LPT-KHALSHAI.bodhtree-int.com:8001/soa-infra/services/default/bpel-101-HelloWorld/helloworldprocess_client_ep?WSDL".

    I have created a WebApplication with a Servlet.
    I have created the JX-WS client for above WSDL.
    The Jdeveloper automatically created a jax-ws-catalog.xml with following content
    ======





    Now I have modified the client to pass a string as follows
    HelloWorldProcess helloWorldProcess =
    helloworldprocess_client.getHelloWorldProcess_pt();

    // Add your code to call the desired methods.
    System.out.println("HelloWorld Response: " +
    helloWorldProcess.process("EbstomdhJob@" +
    df.format(date)));

    Now I deployed the WAR file in the JDeveloper's integrated server and invooked the URL which intern initiates the BPEL Process call.
    The webservice is invoked well and the output is coming as expected.

    Now I changed the jax-ws-catalog.xml as follows (added additional lines inside the catalog element)











    Now redeployed the Servlet to the integrated server and expect a error as the rewritePrefix changed to some invalid server(testserver) name.

    I am expecting the call goes to test server where the webservice is not running and throw me an error

    Surprisingly, the call still goes to localhost system and service is executed successfully.

    So I am not really sure if the jax-ws-catalog.xml is really used when I am deploying the Application or not? I didn't see any reference to the jax-ws-catalog.xml in the Web.xml file. Am I missing some thing?

    Really need help on this ...

    ReplyDelete
    Replies
    1. Hi,

      maybe you can try to add the jax-ws-catalog.xml to the meta-inf folder of war or ear.

      Delete
  6. Thanks Edwin! Your second method worked for me with Jax-WS in a JBoss AS7 environment! I had this in my getServiceStub method:
    bwpss = new BWProvisioningServiceService();
    bwps = bwpss.getProvisioningService();

    And changed it to
    bwpss = new BWProvisioningServiceService(
    new URL(com.acme.webservice.BWProvisioningServiceService.class.getResource("."), getBrsWSDLUrl()),
    new QName("urn:com:acme:webservice", "BWProvisioningServiceService")
    );
    bwps = bwpss.getProvisioningService();

    Where getBrsWSDLUrl() returns basically http://acme.com/ws?wsdl domain obviously changed to protect the innocent! This in turn returns a string read from the web.xml file

    Again, thank you very much, struggled with this a bit a year or two ago, gave up, rehashed it, screwed with it for about an hour prior to finding your article, trying it a few different ways and then making it work with your number two example!

    Have a great day!

    Jason Glass


    ReplyDelete
  7. Hi,
    Thank you for the post where can i get the reference between jax-ws-catalog.xml and System.getProperty("wsdlurl"); .How did u get the wsdlurl.I did not see wsdlurl in jax-ws-catalog.xml.
    Thanks
    santosh

    ReplyDelete
  8. Thanks a lot, it was very clear and helpful ( Divakar Renganathan)

    ReplyDelete
  9. I am having difficulties integrating with Seibel Service - wsdl url is not available - javax.xml.ws.WebServiceException: Failed to access the WSDL at http://www.xyz.com?SWEExtSource=WebService&SWEExtCmd=Execute&WSSOAP=1

    Can you please help?

    ReplyDelete