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