Of course! Generating a WSDL (Web Services Description Language) file from a Java interface is a core feature of Apache CXF. This process is often called "contract-first" development, where you start with your Java code (the "contract") and let CXF generate the WSDL and other necessary artifacts for you.

Here’s a comprehensive guide covering the main methods, from simple to more advanced.
The Core Concept
The process relies on JAX-WS (Java API for XML Web Services) annotations on your Java interface. These annotations provide the metadata that CXF uses to build the WSDL, defining things like:
- Service Name:
@WebService - Operation Name:
@WebMethod - Parameter/Return Names:
@WebParamand@WebResult - Message Parts:
@WebPart - SOAP Faults:
@WebFault
Method 1: Using the CXF wsdl2java Maven Plugin (Recommended)
This is the most common and automated approach in modern Java projects. You define a Maven plugin goal that runs during your build process to generate the WSDL.
Step-by-Step Guide
Project Structure

Let's assume you have a standard Maven project structure:
my-cxf-project/
├── pom.xml
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── ws/
│ │ └── HelloWorld.java <-- Your Java Interface
│ └── resources/
└── test/
The Java Interface (HelloWorld.java)
This is the starting point. It's a simple POJO interface with JAX-WS annotations.
package com.example.ws;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// Define the service name and target namespace
@WebService(
name = "HelloWorld",
targetNamespace = "http://ws.example.com/"
)
// Specify the SOAP binding style (RPC or Document) and use
@SOAPBinding(
style = SOAPBinding.Style.DOCUMENT,
use = SOAPBinding.Use.LITERAL,
parameterStyle = SOAPBinding.ParameterStyle.WRAPPED
)
public interface HelloWorld {
/**
* A simple web method to greet someone.
* @param name The name of the person to greet.
* @return A greeting string.
*/
@WebMethod
@WebResult(name = "greetingResponse") // Name of the root element in the SOAP response
String sayHello(
@WebParam(name = "name") // Name of the element in the SOAP request
String name
);
/**
* A method that takes a complex object.
*/
@WebMethod
@WebResult(name = "userResponse")
User getUserDetails(
@WebParam(name = "user")
User user
);
}
The Complex Object (User.java - A JAXB Annotated Class)

For methods that use complex types, you need a corresponding Java class. JAXB annotations are used to map this class to an XML schema type.
package com.example.ws;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class User {
private String username;
private String email;
// Getters and Setters are required by JAXB
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
The pom.xml (The Magic Happens Here)
This is where you configure the CXF wsdl2java plugin. You tell it where to find your Java interface and where to generate the WSDL file.
<project ...>
...
<properties>
<cxf.version>3.5.5</cxf.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- CXF Core Dependency -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${cxf.version}</version>
</dependency>
<!-- For running as a standalone server -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${cxf.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- This plugin will generate the WSDL -->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-wsdl</id>
<phase>generate-resources</phase> <!-- Run in the generate-resources phase -->
<goals>
<goal>wsdl</goal>
</goals>
<configuration>
<!-- The source directory containing your Java interfaces -->
<sourceRoot>${basedir}/src/main/java</sourceRoot>
<!-- The output directory for the generated WSDL and XSD files -->
<wsdlLocation>/wsdl</wsdlLocation>
<wsdlOptions>
<wsdlOption>
<!-- The fully qualified name of your SEI (Service Endpoint Interface) -->
<sei>com.example.ws.HelloWorld</sei>
<!-- A unique name for the WSDL file -->
<wsdlFileName>hello_world.wsdl</wsdlFileName>
</wsdlOption>
</wsdlOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Run the Build
Execute the Maven command from your project's root directory:
mvn clean generate-resources
Check the Output
After the command finishes, you will find the generated files in the target directory:
my-cxf-project/
├── pom.xml
├── src/
└── target/
├── generated-resources/
│ └── cxf/
│ └── wsdl/
│ └── hello_world.wsdl <-- YOUR WSDL FILE!
│ └── hello_world.xsd <-- The schema for your types
│ └── ... (other files)
└── ...
You can now take the hello_world.wsdl file and share it with clients who need to consume your web service.
Method 2: Programmatically Generating WSDL at Runtime
Sometimes you need to generate the WSDL dynamically when your web service starts. This is useful for testing or for highly dynamic services.
This approach requires you to first create and publish your web service using CXF's JaxWsServerBean.
Step-by-Step Guide
Create a Server Publisher Class
This class will start a simple HTTP server and publish your service.
package com.example.ws.server;
import com.example.ws.HelloWorld;
import com.example.ws.HelloWorldImpl;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
public class WsServerPublisher {
public static void main(String[] args) {
// 1. Create a CXF Server Factory
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
// 2. Set the service implementation bean
factory.setServiceBean(new HelloWorldImpl());
// 3. Set the service interface (SEI)
factory.setServiceClass(HelloWorld.class);
// 4. Set the address (URL) where the service will be published
factory.setAddress("http://localhost:8080/ws/hello");
// 5. Create and start the server
factory.create();
System.out.println("Server started at: http://localhost:8080/ws/hello");
System.out.println("WSDL is available at: http://localhost:8080/ws/hello?wsdl");
}
}
(You'll need HelloWorld interface and HelloWorldImpl class from before)
How to Get the WSDL Programmatically
The JaxWsServerFactoryBean has a method to get the generated WSDL definition as a string.
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.apache.cxf.service.model.ServiceInfo;
// ... inside your WsServerPublisher class or another utility class
public void printWsdls() {
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceBean(new HelloWorldImpl());
factory.setServiceClass(HelloWorld.class);
factory.setAddress("http://localhost:8080/ws/hello");
// Create the server to build the service model
Server server = factory.create();
// Get the service info which contains the WSDL definition
ServiceInfo serviceInfo = server.getEndpoint().getService().getServiceInfo();
// The WSDL definition object
org.apache.cxf.wsdl.WSDLDefinition wsdlDef = serviceInfo.getWsdlPort().getExtensor(org.apache.cxf.wsdl.WSDLDefinition.class);
if (wsdlDef != null) {
// Get the WSDL as a string
String wsdlString = wsdlDef.getDefinition().toString();
System.out.println("--- Generated WSDL ---");
System.out.println(wsdlString);
} else {
System.out.println("WSDL definition not found.");
}
}
When you run this code, it will print the entire WSDL content to your console. You can also access it by navigating to http://localhost:8080/ws/hello?wsdl in a web browser.
Summary: Which Method to Choose?
| Method | Pros | Cons | Best For |
|---|---|---|---|
| Maven Plugin | - Automated, part of the build process. - Generates WSDL and XSD in a structured way. - Standard practice in Maven projects. |
- Requires Maven configuration. - WSDL is generated at build time, not runtime. |
Almost all production projects. It's the cleanest, most maintainable approach. |
| Programmatic | - Dynamic generation. - Useful for testing or creating ad-hoc services. - No build tool dependency. |
- More manual work. - WSDL is not easily accessible for clients unless you expose it via an HTTP endpoint. |
- Quick prototyping and testing. - Scenarios where the service definition changes at runtime. |
