skip to content

What is dynamic WSDL generation in Spring Web Services, and how does DefaultWsdl11Definition produce it?

level: juniorimportance: should knowfreq 45%

answer

  1. XSD is source of truth, WSDL generated
  2. DefaultWsdl11Definition bean
  3. Request/Response suffix -> operations
  4. served at /{beanName}.wsdl
  5. MessageDispatcherServlet front controller

basics

~10 s

Spring-WS generates the WSDL at runtime from your XSD schema instead of you hand-writing it. You declare a DefaultWsdl11Definition bean pointing at an XsdSchema, and Spring builds the WSDL from that schema on request.

solid answer

~40 s

Spring Web Services follows a contract-first style but lets you avoid maintaining a WSDL by hand. You author only the XSD (the XML schema describing your request/response element types). You then register a DefaultWsdl11Definition bean, give it an XsdSchema (typically a SimpleXsdSchema wrapping a .xsd resource), and set portTypeName, locationUri, and targetNamespace. At runtime Spring inspects the schema: elements ending in 'Request'/'Response' (by default suffix convention) become WSDL operations, messages, and a port type; it wires in the SOAP binding and service. The WSDL is served live at '{beanName}.wsdl'. Because it is generated from the single source of truth (the XSD), the WSDL and the schema never drift apart. This all runs through the MessageDispatcherServlet, Spring-WS's front controller for SOAP.

code

java · 20 lines
java
@EnableWs
@Configuration
public class WebServiceConfig {

    @Bean
    public XsdSchema countriesSchema() {
        return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
    }

    // Bean name "countries" -> WSDL served at /ws/countries.wsdl
    @Bean(name = "countries")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
        DefaultWsdl11Definition wsdl = new DefaultWsdl11Definition();
        wsdl.setPortTypeName("CountriesPort");
        wsdl.setLocationUri("/ws");
        wsdl.setTargetNamespace("http://example.com/countries");
        wsdl.setSchema(countriesSchema);
        return wsdl;
    }
}

go deeper

for a junior

Know that Spring-WS is contract-first: write the XSD, the WSDL is generated by DefaultWsdl11Definition.

for a middle

Explain the required properties and the bean-name -> .wsdl URL convention.

for a senior

Explain the suffix-based operation derivation, schema-vs-WSDL namespaces, and static vs dynamic tradeoffs.

for a principal

Discuss multi-schema collections, location rewriting behind proxies, and when to freeze to a static WSDL for contract stability.

## The problem it solves A SOAP web service is described by a **WSDL** (Web Services Description Language) document — an XML file that tells clients what operations exist, what messages they take, and where the endpoint lives. Hand-writing WSDL is verbose and error-prone. Spring Web Services (Spring-WS) is **contract-first**: you write the data contract as an **XSD** (XML Schema Definition — the file that declares your XML element types, e.g. a `GetCountryRequest` element containing a `name` string) and let the framework derive the rest. **Dynamic WSDL** means the WSDL document is *generated at runtime from the XSD* rather than stored as a static file. The class that does this is `org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition`. ## How DefaultWsdl11Definition works You expose it as a Spring bean. It needs: - **`schema`** — an `XsdSchema` (usually `SimpleXsdSchema` wrapping a classpath `.xsd` resource). This is the source of truth. - **`portTypeName`** — the WSDL `<portType>` name (the abstract set of operations). - **`locationUri`** — the URL where the service is reachable (the SOAP `<address location=...>`). - **`targetNamespace`** — the WSDL's own target namespace (distinct from the schema's namespace). At startup/first request, `DefaultWsdl11Definition` uses a set of **providers** (`Wsdl11DefinitionBuilder`/provider classes) that walk the schema. By convention it looks at top-level element declarations whose names end with the configured **request suffix** (`Request`, default) and **response suffix** (`Response`, default). For each matching `XxxRequest`/`XxxResponse` pair it synthesizes: - WSDL `<message>` elements, - a WSDL `<operation>` inside the `<portType>`, - a `<binding>` (default SOAP 1.1 over HTTP), - a `<service>` with the `locationUri`. The bean *name* matters: the WSDL is served at **`/{beanName}.wsdl`**. So a bean named `countries` is reachable at `.../ws/countries.wsdl`. ## The servlet that serves it Spring-WS does not use the normal `DispatcherServlet`. It has its own front controller, **`MessageDispatcherServlet`**, which understands SOAP message dispatching and also serves the generated WSDL. You register it (see the wiring question) mapped to a path like `/ws/*`. When a client GETs `/ws/countries.wsdl`, the servlet finds the `DefaultWsdl11Definition` bean and streams the generated WSDL. ## Gotchas / edge cases - **Suffix convention**: only elements ending in the exact configured suffixes become operations. A mis-named element (`GetCountryReq`) is silently ignored — no operation appears, and clients get an incomplete WSDL. - **Schema vs WSDL namespace**: `targetNamespace` on the definition is the WSDL's namespace; the XSD has its *own* `targetNamespace`. Confusing them breaks generated references. - **`locationUri`** may be templated/rewritten (`transformLocations`) so the advertised URL matches the actual host behind a proxy. - Multiple schemas need `CommonsXsdSchemaCollection` (with `inline=true`) instead of a single `SimpleXsdSchema`. ## When to use Use dynamic WSDL when you own the XSD and want the WSDL to stay automatically in sync. If you must expose a *pre-existing, externally-agreed* WSDL byte-for-byte, serve it statically via `SimpleWsdl11Definition` (wraps a fixed .wsdl) instead — generation could reorder/rename things.

  • What URL serves the generated WSDL and what determines it?
    The bean name plus '.wsdl', under the MessageDispatcherServlet mapping. A bean named 'countries' mapped at /ws/* is served at /ws/countries.wsdl.
  • Why does the XSD element naming matter?
    DefaultWsdl11Definition derives operations from elements ending in the configured request/response suffixes (default 'Request'/'Response'). Mis-named elements are ignored and produce no operation.

saying these in an interview costs you the question

  • Thinking you must hand-write the WSDL file
  • Confusing the WSDL's targetNamespace with the XSD's targetNamespace
  • Believing the normal DispatcherServlet serves SOAP/WSDL

context