Back to Metro Guide

2.11. Developing client application with locally packaged WSDL

In the JAX-WS programming model, to develop a web services client you compile the deployed WSDL using wsimport and then at runtime the same WSDL is used to determine binding information. The default WSDL used can be determined by looking in the subclass generated by wsimport. You can choose another location (network or local file directory) for the WSDL other than the one you used wsimport with, for example if you do not want runtime accesses of the WSDL to go over the network or if you want to edit a copy of the WSDL to work around some bug (dangerous but we do it sometimes).

There are the different ways in which you can provide the local WSDL information to the JAX-WS runtime:

2.11.1. Service API to pass the WSDL information

Sample service creation using local WSDL

        URL baseUrl = client.MtomService.class.getResource(".");
        URL url = new URL(baseUrl, "../Soap11MtomUtf8.svc.xml");
        MtomService service = new MtomService(url, new QName("", "MtomService"));
        IMtomTest proxy = service.getBasicHttpBindingIMtomTest();
        String input="Hello World";
        byte[] response = proxy.echoStringAsBinary(input);

2.11.2. Xml Catalog

This works well but requires some work, such as composing the right catalog file then package it appropriately.

2.11.3. Using -wsdlLocation switch

There is another easy way to do it - just run wsimport with -wsdlLocation switch and provide the WSDL location value which is relative to the generated Service class and provide the WSDL location value which is relative to the generated Service class and you need to put this WSDL file at this relative location.

Let us try to create a client for the NET 3.0 MTOM endpoint. I am using Metro 1.0 M5.

First I save the .NET 3.0 MTOM WSDL locally then run wsimport giving the relative location to where you will package the wsdl with your application

Sample wsimport command

        wsimport -keep -d build/classes -p client etc/Soap11MtomUtf8.svc.xml -wsdlLocation ../Soap11MtomUtf8.svc.xml
Why is the relative location is ../Soap11MtomUtf8.svc.xml? Basically the generated Service will be at build/classes/client location and I would copy this WSDL at build/classes, see option -d and -p.

Here is excerpt from the generated MtomService class. You can see how the wsdlLocation value is generated inside it and is used internally to create the Service.

        * This class was generated by the JAX-WS RI.
        * JAX-WS RI 2.1.2-hudson-53-SNAPSHOT
        * Generated source version: 2.1
        @WebServiceClient(name = "MtomService", targetNamespace = "", ../Soap11MtomUtf8.svc.xml")
        public class MtomService
        extends Service{

            private final static URL MTOMSERVICE_WSDL_LOCATION;
            private final static Logger logger = Logger.getLogger(client.MtomService.class.getName());

            static {
                URL url = null;
                try {
                    URL baseUrl;

                    baseUrl = client.MtomService.class.getResource(".");
                    url = new URL(baseUrl, "../Soap11MtomUtf8.svc.xml");
                } catch (MalformedURLException e) {
                    logger.warning("Failed to create URL for the wsdl Location: ../Soap11MtomUtf8.svc.xml");
                MTOMSERVICE_WSDL_LOCATION = url;

            public MtomService() {
                super(MTOMSERVICE_WSDL_LOCATION, new QName("", "MtomService"));


See below it invokes the .NET 3.0 service. You may notice here that you dont need to enable MTOM explicitly. Metro bring in .NET 3.0 interop thru WSIT and due to this the MTOM policy assertions in the .NET 3.0 WSDL, it correctly interpreted and the IMtomTest port is configured with MTOM enabled.

package client;


 * Client that invokes .NET 3.0 MTOM endpoint using a local wsdl
public class Client {

    public static void main(String[] args) {

        //enble SOAP Message logging
        HttpTransportPipe.dump = true;

        //Create IMtomTest proxy to invoke .NET 3.0 MTOM service
        IMtomTest proxy = new MtomService().getBasicHttpBindingIMtomTest();
        String input="Hello World";
        byte[] response = proxy.echoStringAsBinary(input);
        System.out.println("Sent: "+input+", Received: "+new String(response));

Get the complete client bundle from here and see the enclosed Readme.txt for instructions on how to run it.