What is dynamic WSDL generation in Spring Web Services, and how does DefaultWsdl11Definition produce it?
answer
- XSD is source of truth, WSDL generated
- DefaultWsdl11Definition bean
- Request/Response suffix -> operations
- served at /{beanName}.wsdl
- MessageDispatcherServlet front controller
basics
~10 sSpring-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 sSpring 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@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
Know that Spring-WS is contract-first: write the XSD, the WSDL is generated by DefaultWsdl11Definition.
Explain the required properties and the bean-name -> .wsdl URL convention.
Explain the suffix-based operation derivation, schema-vs-WSDL namespaces, and static vs dynamic tradeoffs.
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