Java – Spring WS WSDL automatic exposure : xsd import are not followed

javaspringspring-wswsdlxsd

I'm trying to dynamically generate WSDL for a Spring WS web service, based on multiple xml schemas. I have a multiple xsd files, all of them are "connected" using xsd:import elements.

Spring WS reference says :

If you want to use multiple schemas, either by includes or imports, you will want to put Commons XMLSchema on the class path. If Commons XMLSchema is on the class path, the above element will follow all XSD imports and includes, and will inline them in the WSDL as a single XSD. This greatly simplifies the deployment of the schemas, which still making it possible to edit them separately.

so I added this maven dependency :

    <dependency>
        <groupId>org.apache.ws.xmlschema</groupId>
        <artifactId>xmlschema-core</artifactId>
        <version>2.2.1</version>
    </dependency>

and configurated the WSDL builder in this way :

@Bean(name="updateContactService")
public DefaultWsdl11Definition defaultWsdl11Definition() throws Exception {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("updateContactPort");
    wsdl11Definition.setLocationUri("/ws/updateContact");
    wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
    wsdl11Definition.setSchema(updateContactXsd());
    return wsdl11Definition;
}   

@Bean
public XsdSchemaCollection updateContactXsd() throws Exception {
    return new SimpleXsdSchema(new ClassPathResource("xsds/contact/outboundMessage.xsd"));
}

but the generated WSDL only contains a single schema element (and showing the import with a wrong location).

<xs:import namespace="http://xmlns.oracle.com/apps/cdm/foundation/parties/personService/" schemaLocation="personService.xsd"/>

Any tips? Spring WS version is 2.3.1

<?xml version="1.0" encoding="UTF-8" standalone="no"?><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://xmlns.oracle.com/apps/crmCommon/content/outboundMessage/types/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://spring.io/guides/gs-producing-web-service" targetNamespace="http://spring.io/guides/gs-producing-web-service">
  <wsdl:types>
    <xs:schema xmlns="http://xmlns.oracle.com/apps/crmCommon/content/outboundMessage/types/" xmlns:ns2="http://xmlns.oracle.com/apps/cdm/foundation/parties/personService/" xmlns:tns0="http://xmlns.oracle.com/apps/crmCommon/content/outboundMessage/types/" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/apps/crmCommon/content/outboundMessage/types/">
    <xs:import namespace="http://xmlns.oracle.com/apps/cdm/foundation/parties/personService/" schemaLocation="personService.xsd"/>
    <xs:element name="process" type="tns0:processType"/>
    <xs:complexType name="processType">
        <xs:sequence>
            <xs:element maxOccurs="unbounded" minOccurs="0" name="Person" type="ns2:Person"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="processResponse" type="tns0:processResponseType"/>
    <xs:complexType name="processResponseType">
        <xs:sequence>
            <xs:element maxOccurs="unbounded" minOccurs="0" name="Person" type="ns2:Person"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="processResponse">
    <wsdl:part element="sch:processResponse" name="processResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="updateContactPort">
    <wsdl:operation name="process">
      <wsdl:output message="tns:processResponse" name="processResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="updateContactPortSoap11" type="tns:updateContactPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="process">
      <soap:operation soapAction=""/>
      <wsdl:output name="processResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="updateContactPortService">
    <wsdl:port binding="tns:updateContactPortSoap11" name="updateContactPortSoap11">
      <soap:address location="https://localhost:4440/ws/updateContact"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Best Answer

Solved!

I had to use XsdSchemaCollection instead of a SimpleXsdSchema; in addition I had to set to true the "inline" parameter of the collection.

@Bean(name="updateContactService")
public DefaultWsdl11Definition defaultWsdl11Definition() throws Exception {
    DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
    wsdl11Definition.setPortTypeName("updateContactPort");
    wsdl11Definition.setLocationUri("/ws/updateContact");
    wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
    wsdl11Definition.setSchemaCollection(updateContactXsd());
    return wsdl11Definition;
}   

@Bean
public XsdSchemaCollection updateContactXsd() throws Exception {
    CommonsXsdSchemaCollection xsds = new CommonsXsdSchemaCollection(new ClassPathResource("xsds/contact/outboundMessage.xsd"));
    xsds.setInline(true);  <-------------------
    return xsds;
}

Note :

xsds.setInline(true);

I'll open an issue on Jira because I think that reference it's not clear!

Related Topic