axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ben Reif (JIRA)" <j...@apache.org>
Subject [jira] Issue Comment Edited: (AXIS2-4353) ServiceClient can not resolve WSDL with imported schemas
Date Thu, 28 May 2009 13:31:46 GMT

    [ 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:31 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);
    //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);
    }
}

  
> 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.


Mime
View raw message