skip to content

How does DefaultWsdl11Definition decide which schema elements become WSDL operations, and how do requestSuffix/responseSuffix and multiple schemas factor in?

level: seniorimportance: should knowfreq 35%

answer

  1. top-level elements ending Request/Response -> operations
  2. operation name = request element minus suffix
  3. setRequestSuffix/setResponseSuffix configurable
  4. CommonsXsdSchemaCollection inline=true for multi-schema
  5. faults added generically, not per element

basics

~20 s

It 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 s

DefaultWsdl11Definition 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
java
@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

for a junior

Know operations come from Request/Response-suffixed elements.

for a middle

Explain operation-name derivation and configurable suffixes.

for a senior

Explain the provider-based generation, generic faults, and single-vs-collection schema handling with inlining.

for a principal

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

context