JAX-WS and soap:address


JAX-WS is the easy-to-use Java API for XML-based web services and provides developers with an easy way to implement SOAP-based or ReSTful web services without having to fiddle with SOAP, WSDL or any XML at all (apart from the configuration).

If you use the "from-Java" approach to JAX-WS, the runtime will automatically generate a WSDL file for your service that will be available under an URL such as http://localhost:8080/my-service/myAction?wsdl. It contains a part such as

XML:
  1. <service name="MyService">
  2.     <port name="MyPort" binding="tns:MyPortBinding">
  3.       <soap:address location="http://localhost:8080/my-service/myAction"/>
  4.     </port>
  5. </service>

to point the clients that later will use this service to the correct URL to address the service itself. Very soon I came across the question, how to deploy this to a production environment, where the service and the client would, of course, run on different machines. The above excerpt from the WSDL isn't really portable from the way it look.

As a beginner with JAX-WS, at first I found no way to change this URL to reflect another server as localhost and got frustrated with the question how on earth to deploy this web service and change the soap:address part. As it turns out now, you don't have to change this part.

The service address (as the whole WSDL file) is generated on-the-fly by JAX-WS when a client requests it. The runtime then simply derives the service's address from the request URL for the WSDL file. So, if you can request it from http://localhost:8080/my-service/myAction?wsdl, the service address will read as shown above. If you deploy this to another server and address it for example with http://prod-ws.mycompany.tld/my-service/myAction?wsdl then the runtime will generate the following address:

XML:
  1. <service name="MyService">
  2.     <port name="MyPort" binding="tns:MyPortBinding">
  3.         <soap:address location="http://prod-ws.mycompany.tld/my-service/myAction"/>
  4.     </port>
  5. </service>

and everything will be fine. I hope, I could save you some headache with this.

Tags: , , , , , , ,

, , , , , , ,

  1. #1 von Robert Reiz am 2. Juli 2009 - 19:28

    Your approach does not work if I deploy the service to two App. servers behind a loadbalancer. To control the soapAdress with an annotation in the Endpoint would be very nice.

  2. #2 von Hendrik Busch am 10. Juli 2009 - 12:07

    I’ve never actually dealt with loadbalancers, but isn’t it the loadbalancers job to rewrite all incoming requests and all outgoing reponses? So if you have two appserver running your webservice (host1 and host2) and a loadbalancer (load), then the software using the web service should target the loadbalancer (e.g. http://load/my-service/myAction?wsdl) which then rewrites the request to the specific target machine (http://host2:8080/my-service/myAction?wsdl) and also rewrites the response from that machine (from <soap:address location="http://host2:8080/my-service/myAction"/> to <soap:address location="http://load/my-service/myAction"/>). Configuring the final location directly in the web service breaks portability and should not be done IMHO as the loadbalancer should handle request/response rewriting.

  3. #3 von Thomas Bayer am 13. Februar 2010 - 14:46

    Hi Hendrik,
    Membrane SOA Monitor and Router are open source tools that support loadbalancing and rewriting as you described it. They even rewrite includes and imports in WSDL or Schema documents. See:

    http://www.membrane-soa.org/url-rewriting.htm
    http://www.membrane-soa.org/soap-loadbalancing.htm

    Thomas

(wird nicht veröffentlicht)