How does DefaultWsdl11Definition decide which schema elements become WSDL operations, and how do requestSuffix/responseSuffix and multiple schemas factor in?
answer
- top-level elements ending Request/Response -> operations
- operation name = request element minus suffix
- setRequestSuffix/setResponseSuffix configurable
- CommonsXsdSchemaCollection inline=true for multi-schema
- faults added generically, not per element
basics
~20 sIt scans top-level XSD element declarations and pairs those ending in the request suffix ('Request' by default) with matching 'Response' ones, turning each pair into a WSDL operation. You can change the suffixes; multiple schemas need a schema collection.
solid answer
~40 sDefaultWsdl11Definition delegates to inline providers (a Wsdl11Definition builder) that inspect the XsdSchema's top-level element declarations. By default it treats any element whose name ends with requestSuffix='Request' as an operation input and the correspondingly-named element ending in responseSuffix='Response' as the output, deriving <message>, <operation>, <portType>, SOAP <binding>, and <service>. Both suffixes are configurable (setRequestSuffix/setResponseSuffix) — useful if your naming differs, but every input element must have a partner or you get an incomplete/one-way operation. A single SimpleXsdSchema covers one schema; for several interrelated XSDs you instead give it an XsdSchemaCollection such as CommonsXsdSchemaCollection with inline=true, which resolves imports/includes and inlines them so the generated WSDL's <types> is self-contained. Fault handling is added generically; you don't declare faults per element.
code
java · 21 lines@Bean
public XsdSchemaCollection schemaCollection() {
CommonsXsdSchemaCollection collection = new CommonsXsdSchemaCollection(
new ClassPathResource("orders.xsd"), // imports common.xsd
new ClassPathResource("common.xsd"));
collection.setInline(true); // resolve & inline imports into WSDL <types>
return collection;
}
@Bean(name = "orders")
public DefaultWsdl11Definition ordersWsdl(XsdSchemaCollection schemaCollection) {
DefaultWsdl11Definition wsdl = new DefaultWsdl11Definition();
wsdl.setPortTypeName("OrdersPort");
wsdl.setLocationUri("/ws");
wsdl.setTargetNamespace("http://example.com/orders");
wsdl.setSchemaCollection(schemaCollection); // not setSchema
// Non-default naming, e.g. GetOrderReq / GetOrderResp:
// wsdl.setRequestSuffix("Req");
// wsdl.setResponseSuffix("Resp");
return wsdl;
}go deeper
Know operations come from Request/Response-suffixed elements.
Explain operation-name derivation and configurable suffixes.
Explain the provider-based generation, generic faults, and single-vs-collection schema handling with inlining.
Weigh dynamic generation vs frozen static WSDL for contract stability, and namespace/import strategy across many XSDs.
## Element scanning and the suffix convention `DefaultWsdl11Definition` builds a WSDL 1.1 document by composing several *providers* internally (implementations around `org.springframework.ws.wsdl.wsdl11.provider.*` — e.g. a schema-based messages provider, a suffix-based port-type provider, a SOAP binding provider, a service provider). The port-type/messages logic works by convention on the **XSD element declarations**: - Every **top-level `<xs:element>`** whose *name* ends with **`requestSuffix`** (default literal string `"Request"`) is taken as the **input message** of an operation. - The operation's **output message** is the element whose name ends with **`responseSuffix`** (default `"Response"`) and whose base name matches. - The operation *name* is the request element name minus the suffix. So `GetCountryRequest` + `GetCountryResponse` -> operation `GetCountry`. From those pairs it emits WSDL `<message>` (one per element), `<operation>` inside a single `<portType>` (named by `portTypeName`), a SOAP 1.1 `<binding>`, and a `<service>` whose port `<address location>` is `locationUri`. ### Changing the suffixes `setRequestSuffix("Req")` / `setResponseSuffix("Resp")` reconfigure the matching. Reasons to change: your team's XSD naming standard, or avoiding accidental matches. **Gotcha**: change one without the other and pairs stop matching — you get one-way operations or none. An element that matches *neither* suffix simply becomes an unused type in `<types>` (no operation). ## Faults You do **not** enumerate SOAP faults per element. Spring-WS adds a generic fault to each operation's binding, and runtime exceptions are turned into SOAP Faults by an `EndpointExceptionResolver` (e.g. `SoapFaultMappingExceptionResolver`). So the WSDL advertises a fault mechanism without you naming fault elements in the schema. ## Single vs multiple schemas - **One schema**: `SimpleXsdSchema` wrapping a single `.xsd` `Resource`. Simplest, most common. - **Multiple / imported schemas**: use an `XsdSchemaCollection` — the standard implementation is **`org.springframework.xml.xsd.commons.CommonsXsdSchemaCollection`** (backed by Apache WS-Commons XmlSchema). Set **`inline=true`** so that `<xs:import>`/`<xs:include>` references are resolved and inlined into the WSDL's `<types>`, producing a self-contained WSDL clients can consume without fetching side files. Without inlining, the WSDL references external schema locations that may not be reachable by the client. When you have a collection, feed it via `DefaultWsdl11Definition.setSchemaCollection(...)` instead of `setSchema(...)`. ## Namespaces - The **XSD `targetNamespace`** becomes the namespace of the message element types. - The **`targetNamespace`** you set on `DefaultWsdl11Definition` is the *WSDL document's* namespace. Keeping them consistent/aligned avoids confusing generated qualified names. A common convention is to set the WSDL target namespace equal to the schema target namespace. ## Edge cases / gotchas - **No matching pairs** -> WSDL with an empty/degenerate port type; clients see no callable operations. - **Abstract vs element**: only *element* declarations drive operations, not named complexTypes; wrap your operation payloads in top-level elements. - **Ordering**: operations appear in schema element order; not usually significant but affects diffs. - **Static alternative**: if the exact WSDL wording/order is contractually fixed, serve a frozen file with `SimpleWsdl11Definition` instead — generation may not reproduce a third-party WSDL byte-for-byte. ## When to use Dynamic generation with the suffix convention is ideal when you control the XSD and follow the `XxxRequest`/`XxxResponse` naming. Reach for the schema collection as soon as you split types across imported XSDs.
- You added a GetCountryRequest element but no operation appears in the WSDL. Likely cause?No matching GetCountryResponse element (or the response suffix was reconfigured and doesn't match), so the pair can't form an operation; or it's a complexType rather than a top-level element.
- Why set inline=true on CommonsXsdSchemaCollection?To resolve xs:import/xs:include and inline the referenced schemas into the WSDL's <types>, making the WSDL self-contained so clients don't have to fetch external .xsd files.
saying these in an interview costs you the question
- Thinking complexTypes (not elements) become operations
- Assuming you must declare each SOAP fault element in the XSD
- Changing only requestSuffix and expecting pairs to still match
- Believing multiple XSDs work with a single SimpleXsdSchema