[ 
https://issues.apache.org/jira/browse/AXIS2-4353?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12713975#action_12713975
 ] 

Ben Reif edited comment on AXIS2-4353 at 5/28/09 6:26 AM:
----------------------------------------------------------

To get around this issue, for now, I have changed the Axis2 code to look like 
this:

ServiceClient:
------------------

     //Fix for AXIS2-4353, Added URIResolver argument so that we can resolve
    //schema files that are inside Jars
    public ServiceClient(ConfigurationContext configContext, Definition 
wsdl4jDefinition,
                         QName wsdlServiceName, String portName, URIResolver 
customResolver) throws AxisFault {
        configureServiceClient(configContext, 
AxisService.createClientSideAxisService(
                wsdl4jDefinition, wsdlServiceName, portName, options, 
customResolver));
    }

    //Fix for AXIS2-4353, Added URIResolver argument so that we can resolve
    //schema files that are inside Jars
    public ServiceClient(ConfigurationContext configContext, URL wsdlURL,
                         QName wsdlServiceName, String portName, URIResolver 
customResolver) throws AxisFault {
        configureServiceClient(configContext, 
AxisService.createClientSideAxisService(wsdlURL,
                                                                                
      wsdlServiceName,
                                                                                
      portName,
                                                                                
      options,
                                                                                
      customResolver));
        Parameter transportName = axisService.getParameter("TRANSPORT_NAME");
        if(transportName != null ) {
            TransportOutDescription transportOut = 
configContext.getAxisConfiguration().getTransportOut(
                    transportName.getValue().toString());
            if (transportOut == null) {
                throw new AxisFault("Cannot load transport from binding, either 
defin in Axis2.config " +
                        "or set it explicitely in ServiceClinet.Options");
            } else {
                options.setTransportOut(transportOut);
            }
        }
    }


AxisService:
-----------------

//Fix for AXIS2-4353, Added URIResolver argument so that we can resolve
//schema files that are inside Jars
public static AxisService createClientSideAxisService(URL wsdlURL,
        QName wsdlServiceName, String portName, Options options, URIResolver 
customResolver)
                        throws AxisFault {
    try {
        InputStream in = wsdlURL.openConnection().getInputStream();
        Document doc = XMLUtils.newDocument(in);
        WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
        reader.setFeature("javax.wsdl.importDocuments", true);
        Definition wsdlDefinition = 
reader.readWSDL(getBaseURI(wsdlURL.toString()), doc);
        if (wsdlDefinition != null) {
                
wsdlDefinition.setDocumentBaseURI(getDocumentURI(wsdlURL.toString()));
        }
        return createClientSideAxisService(wsdlDefinition, wsdlServiceName,
                        portName, options, customResolver);
    } catch (IOException e) {
        log.error(e.getMessage(), e);
        throw AxisFault.makeFault(e);
    } catch (ParserConfigurationException e) {
        log.error(e.getMessage(), e);
        throw AxisFault.makeFault(e);
    } catch (SAXException e) {
        log.error(e.getMessage(), e);
        throw AxisFault.makeFault(e);
    } catch (WSDLException e) {
        log.error(e.getMessage(), e);
        throw AxisFault.makeFault(e);
    }
}

//Fix for AXIS2-4353, Added URIResolver argument so that we can resolve
//schema files that are inside Jars
public static AxisService createClientSideAxisService(
        Definition wsdlDefinition, QName wsdlServiceName, String portName,
        Options options, URIResolver customResolver) throws AxisFault {
    WSDL11ToAxisServiceBuilder serviceBuilder = new WSDL11ToAxisServiceBuilder(
                wsdlDefinition, wsdlServiceName, portName);
    //Fix for AXIS2-4353
    if(customResolver != null){
        serviceBuilder.setCustomResolver(customResolver);
    }
    //End Fix for AXIS2-4353
    serviceBuilder.setServerSide(false);
    AxisService axisService = serviceBuilder.populateService();
    AxisEndpoint axisEndpoint = (AxisEndpoint) axisService.getEndpoints()
                .get(axisService.getEndpointName());
    options.setTo(new EndpointReference(axisEndpoint.getEndpointURL()));
    if (axisEndpoint != null) {
        options.setSoapVersionURI((String) axisEndpoint.getBinding()
                        .getProperty(WSDL2Constants.ATTR_WSOAP_VERSION));
    }
    return axisService;
}

This allows me to pass in my own implementation of URIResolver via the 
ServiceClient, like this:

ServiceClient serviceClient = new ServiceClient(axisConfigContext, wsdlDef, 
wsdlServiceQName, port.getName(), new URIResolver());

I'm wondering though if the Axis2 team thinks this is the best long term 
solution, or if the correct solution would be to just fix the 
DefaultURIResolver in the ws-commons project? I can include the logic for my 
custom URIResolver, which just extends the DefaultURIResolver. But I think the 
same logic could easily be added to the DefaultURIResolver to make it a bit 
more robust. Ideally that would be the best solution for us. I'm curious to 
hear any opinions.


URIResolver
------------------

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.ws.commons.schema.resolver.DefaultURIResolver;
import org.xml.sax.InputSource;

public class URIResolver extends DefaultURIResolver {

    private String schemePrefix;
    private static final String JAR_SCHEME = "jar:";
    private static final String ZIP_SCHEME = "zip:";
    private static final String FILE_SCHEME = "file:";
        
    public InputSource resolveEntity(String targetNamespace, String 
schemaLocation, String baseUri) {
        if (baseUri == null || isAbsolute(schemaLocation) || 
baseUri.startsWith(FILE_SCHEME)) {
            return super.resolveEntity(targetNamespace, schemaLocation, 
baseUri);
        } else if(baseUri.startsWith(JAR_SCHEME+FILE_SCHEME) || 
baseUri.startsWith(ZIP_SCHEME+FILE_SCHEME)){
            if(baseUri.startsWith(JAR_SCHEME)){
                schemePrefix = JAR_SCHEME;
            } else{
                schemePrefix = ZIP_SCHEME;
           }
           try {
                 baseUri = baseUri.replaceFirst(schemePrefix, "");
                 String ref = schemePrefix + new URI(baseUri).resolve(new 
URI(schemaLocation)).toString();
                 InputSource inputSource = new InputSource(new 
URI(ref).toURL().openStream());
                 inputSource.setSystemId(ref);
                 inputSource.setPublicId(targetNamespace);
                 return inputSource;
           } catch (URISyntaxException e) {
        throw new RuntimeException(e);
           } catch (MalformedURLException e) {
        throw new RuntimeException(e);
           } catch (IOException e) {
        throw new RuntimeException(e);
           }
        }
        return new InputSource(schemaLocation);
    }
}


      was (Author: breif):
    To get around this issue, for now, I have changed the Axis2 code to look 
like this:

ServiceClient:
------------------

     //Fix for AXIS2-4353, Added URIResolver argument so that we can resolve
    //schema files that are inside Jars
    public ServiceClient(ConfigurationContext configContext, Definition 
wsdl4jDefinition,
                         QName wsdlServiceName, String portName, URIResolver 
customResolver) throws AxisFault {
        configureServiceClient(configContext, 
AxisService.createClientSideAxisService(
                wsdl4jDefinition, wsdlServiceName, portName, options, 
customResolver));
    }

    //Fix for AXIS2-4353, Added URIResolver argument so that we can resolve
    //schema files that are inside Jars
    public ServiceClient(ConfigurationContext configContext, URL wsdlURL,
                         QName wsdlServiceName, String portName, URIResolver 
customResolver) throws AxisFault {
        configureServiceClient(configContext, 
AxisService.createClientSideAxisService(wsdlURL,
                                                                                
      wsdlServiceName,
                                                                                
      portName,
                                                                                
      options,
                                                                                
      customResolver));
        Parameter transportName = axisService.getParameter("TRANSPORT_NAME");
        if(transportName != null ) {
            TransportOutDescription transportOut = 
configContext.getAxisConfiguration().getTransportOut(
                    transportName.getValue().toString());
            if (transportOut == null) {
                throw new AxisFault("Cannot load transport from binding, either 
defin in Axis2.config " +
                        "or set it explicitely in ServiceClinet.Options");
            } else {
                options.setTransportOut(transportOut);
            }
        }
    }


AxisService:
-----------------

                      //Fix for AXIS2-4353, Added URIResolver argument so that 
we can resolve
                     //schema files that are inside Jars
        public static AxisService createClientSideAxisService(URL wsdlURL,
                        QName wsdlServiceName, String portName, Options 
options, URIResolver customResolver)
                        throws AxisFault {
                try {
                        InputStream in = 
wsdlURL.openConnection().getInputStream();
                        Document doc = XMLUtils.newDocument(in);
                        WSDLReader reader = 
WSDLFactory.newInstance().newWSDLReader();
                        reader.setFeature("javax.wsdl.importDocuments", true);
                        Definition wsdlDefinition = 
reader.readWSDL(getBaseURI(wsdlURL
                                        .toString()), doc);
                        if (wsdlDefinition != null) {
                                
wsdlDefinition.setDocumentBaseURI(getDocumentURI(wsdlURL
                                                .toString()));
                        }
                        return createClientSideAxisService(wsdlDefinition, 
wsdlServiceName,
                                        portName, options, customResolver);
                } catch (IOException e) {
                        log.error(e.getMessage(), e);
                        throw AxisFault.makeFault(e);
                } catch (ParserConfigurationException e) {
                        log.error(e.getMessage(), e);
                        throw AxisFault.makeFault(e);
                } catch (SAXException e) {
                        log.error(e.getMessage(), e);
                        throw AxisFault.makeFault(e);
                } catch (WSDLException e) {
                        log.error(e.getMessage(), e);
                        throw AxisFault.makeFault(e);
                }
        }

                     //Fix for AXIS2-4353, Added URIResolver argument so that 
we can resolve
                     //schema files that are inside Jars
        public static AxisService createClientSideAxisService(
                        Definition wsdlDefinition, QName wsdlServiceName, 
String portName,
                        Options options, URIResolver customResolver) throws 
AxisFault {
                WSDL11ToAxisServiceBuilder serviceBuilder = new 
WSDL11ToAxisServiceBuilder(
                                wsdlDefinition, wsdlServiceName, portName);
                //WFX - Fix for AXIS2-4353
                if(customResolver != null){
                        serviceBuilder.setCustomResolver(customResolver);
                }
                //End WFX - Fix for AXIS2-4353
                serviceBuilder.setServerSide(false);
                AxisService axisService = serviceBuilder.populateService();
                AxisEndpoint axisEndpoint = (AxisEndpoint) 
axisService.getEndpoints()
                                .get(axisService.getEndpointName());
                options.setTo(new 
EndpointReference(axisEndpoint.getEndpointURL()));
                if (axisEndpoint != null) {
                        options.setSoapVersionURI((String) 
axisEndpoint.getBinding()
                                        
.getProperty(WSDL2Constants.ATTR_WSOAP_VERSION));
                }
                return axisService;
        }

This allows me to pass in my own implementation of URIResolver via the 
ServiceClient, like this:

ServiceClient serviceClient = new ServiceClient(axisConfigContext, wsdlDef, 
wsdlServiceQName, port.getName(), new URIResolver());

I'm wondering though if the Axis2 team thinks this is the best long term 
solution, or if the correct solution would be to just fix the 
DefaultURIResolver in the ws-commons project? I can include the logic for my 
custom URIResolver, which just extends the DefaultURIResolver. But I think the 
same logic could easily be added to the DefaultURIResolver to make it a bit 
more robust. Ideally that would be the best solution for us. I'm curious to 
hear any opinions.


URIResolver
------------------

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;

import org.apache.ws.commons.schema.resolver.DefaultURIResolver;
import org.xml.sax.InputSource;

public class URIResolver extends DefaultURIResolver {

    private String schemePrefix;
    private static final String JAR_SCHEME = "jar:";
    private static final String ZIP_SCHEME = "zip:";
    private static final String FILE_SCHEME = "file:";
        
    public InputSource resolveEntity(String targetNamespace, String 
schemaLocation, String baseUri) {
        if (baseUri == null || isAbsolute(schemaLocation) || 
baseUri.startsWith(FILE_SCHEME)) {
            return super.resolveEntity(targetNamespace, schemaLocation, 
baseUri);
        } else if(baseUri.startsWith(JAR_SCHEME+FILE_SCHEME) || 
baseUri.startsWith(ZIP_SCHEME+FILE_SCHEME)){
            if(baseUri.startsWith(JAR_SCHEME)){
                schemePrefix = JAR_SCHEME;
            } else{
                schemePrefix = ZIP_SCHEME;
           }
           try {
                 baseUri = baseUri.replaceFirst(schemePrefix, "");
                 String ref = schemePrefix + new URI(baseUri).resolve(new 
URI(schemaLocation)).toString();
                 InputSource inputSource = new InputSource(new 
URI(ref).toURL().openStream());
                 inputSource.setSystemId(ref);
                 inputSource.setPublicId(targetNamespace);
                 return inputSource;
           } catch (URISyntaxException e) {
        throw new RuntimeException(e);
           } catch (MalformedURLException e) {
        throw new RuntimeException(e);
           } catch (IOException e) {
        throw new RuntimeException(e);
           }
        }
        return new InputSource(schemaLocation);
    }
}

  
> ServiceClient can not resolve WSDL with imported schemas
> --------------------------------------------------------
>
>                 Key: AXIS2-4353
>                 URL: https://issues.apache.org/jira/browse/AXIS2-4353
>             Project: Axis 2.0 (Axis2)
>          Issue Type: Bug
>          Components: client-api
>    Affects Versions: 1.4.1, 1.4
>         Environment: all
>            Reporter: Ben Reif
>            Priority: Blocker
>         Attachments: ResolveXSDTestCase.zip
>
>
> I am using the ServiceClient to invoke a Web Service, but the WSDL file and 
> imported schema files are located within a jar file that is in the Classpth. 
> I can get the Definition object, and I set the DocumentBaseURI to the proper 
> URL pointing inside the jar file, but when I pass it to the ServiceClient I 
> get an error saying that it can't resolve the imported schema files. This 
> happens when it calls AxisService.createClientSideAxisService().
> It looks like a fix was put in the WSDLToAxisServiceBuilder class (the 
> addition of the setCustomResolver() method) so that you can set a custom 
> URIResolver to resolve imported schema files. This gets inherited by the 
> WSDL11ToAxisServiceBuilder, however the problem is that this setter is not 
> exposed to the ServiceClient, so I can never use it.  The ServiceClient 
> constructors and the AxisService.createClientSideAxisService() methods should 
> take in an additional argument so that calling code can pass in the right 
> URIResolver instance which would get set on the WSDL11ToAxisServiceBuilder 
> instance.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to