eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

Java API for XML Web Services (JAX-WS) is a standardized API for creating and consuming SOAP (Simple Object Access Protocol) web services.

In this article, we’ll create a SOAP web service and connect to it using JAX-WS.

2. SOAP

SOAP is an XML specification for sending messages over a network. SOAP messages are independent of any operating system and can use a variety of communication protocols including HTTP and SMTP.

SOAP is XML heavy, hence best used with tools/frameworks. JAX-WS is a framework that simplifies using SOAP. It is part of standard Java.

3. Top-Down vs. Bottom-Up

There are two ways of building SOAP web services. We can go with a top-down approach or a bottom-up approach.

In a top-down (contract-first) approach, a WSDL document is created, and the necessary Java classes are generated from the WSDL. In a bottom-up (contract-last) approach, the Java classes are written, and the WSDL is generated from the Java classes.

Writing a WSDL file can be quite difficult depending on how complex your web service is. This makes the bottom-up approach an easier option. On the other hand, since your WSDL is generated from the Java classes, any change in code might cause a change in the WSDL. This is not the case for the top-down approach.

In this article, we’ll take a look at both approaches.

4. Web Services Definition Language (WSDL)

WSDL is a contract definition of the available services. It is a specification of input/output messages, and how to invoke the web service. It is language neutral and is defined in XML.

Let’s look at the major elements of a WSDL document.

4.1. Definitions

The definitions element is the root element of all WSDL documents. It defines the name, the namespace, etc. of the service and, as you can see, can be quite spacious:

<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" 
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
  xmlns:tns="http://jaxws.baeldung.com/" 
  xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
  xmlns:wsp="http://www.w3.org/ns/ws-policy" 
  xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  targetNamespace="http://jaxws.baeldung.com/" 
  name="EmployeeService">
  ...
</definitions>

4.2. Types

The types element defines the data types used by the web service. WSDL uses XSD (XML Schema Definition) as the type system which helps with interoperability:

<definitions ...>
    ...
    <types>
        <xsd:schema>
            <xsd:import namespace="http://jaxws.baeldung.com/" 
              schemaLocation = "http://localhost:8080/employeeservice?xsd=1" />
        </xsd:schema>
    </types>
    ...
</definitions>

4.3. Messages

The message element provides an abstract definition of the data being transmitted. Each message element describes the input or output of a service method and the possible exceptions:

<definitions ...>
    ...
    <message name="getEmployee">
        <part name="parameters" element="tns:getEmployee" />
    </message>
    <message name="getEmployeeResponse">
        <part name="parameters" element="tns:getEmployeeResponse" />
    </message>
    <message name="EmployeeNotFound">
        <part name="fault" element="tns:EmployeeNotFound" />
    </message>
    ...
</definitions>

4.4. Operations and Port Types

The portType element describes each operation that can be performed and all the message elements involved. For example, the getEmployee operation specifies the request input, output and possible fault exception thrown by the web service operation:

<definitions ...>
    ...
    <portType name="EmployeeService">
        <operation name="getEmployee">
            <input 
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeRequest" 
              message="tns:getEmployee" />
            <output 
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployeeResponse" 
              message="tns:getEmployeeResponse" />
            <fault message="tns:EmployeeNotFound" name="EmployeeNotFound" 
              wsam:Action="http://jaxws.baeldung.com/EmployeeService/getEmployee/Fault/EmployeeNotFound" />
        </operation>
    ....
    </portType>
    ...
</definitions>

4.5. Bindings

The binding element provides protocol and data format details for each portType:

<definitions ...>
    ...
    <binding name="EmployeeServiceImplPortBinding" 
      type="tns:EmployeeService">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
          style="document" />
        <operation name="getEmployee">
            <soap:operation soapAction="" />
            <input>
                <soap:body use="literal" />
            </input>
            <output>
                <soap:body use="literal" />
            </output>
            <fault name="EmployeeNotFound">
                <soap:fault name="EmployeeNotFound" use="literal" />
            </fault>
        </operation>
        ...
    </binding>
    ...
</definitions>

4.6. Services and Ports

The service element defines the ports supported by the web service. The port element in service defines the name, binding and the address of the service:

<definitions ...>
    ...
    <service name="EmployeeService">
        <port name="EmployeeServiceImplPort" 
          binding="tns:EmployeeServiceImplPortBinding">
            <soap:address 
              location="http://localhost:8080/employeeservice" />
        </port>
    </service>
    ...
</definitions>

5. Top-Down (Contract-First) Approach

Let’s start with a top-down approach by creating a WSDL file employeeservicetopdown.wsdl. For the sake of simplicity, it has only one method:

<?xml version="1.0" encoding="UTF-8"?>
<definitions 
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="http://topdown.server.jaxws.baeldung.com/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.xmlsoap.org/wsdl/"
  targetNamespace="http://topdown.server.jaxws.baeldung.com/"
  qname="EmployeeServiceTopDown">
    <types>
        <xsd:schema 
          targetNamespace="http://topdown.server.jaxws.baeldung.com/">
            <xsd:element name="countEmployeesResponse" type="xsd:int"/>
        </xsd:schema>
    </types>

    <message name="countEmployees">
    </message>
    <message name="countEmployeesResponse">
        <part name="parameters" element="tns:countEmployeesResponse"/>
    </message>
    <portType name="EmployeeServiceTopDown">
        <operation name="countEmployees">
            <input message="tns:countEmployees"/>
            <output message="tns:countEmployeesResponse"/>
        </operation>
    </portType>
    <binding name="EmployeeServiceTopDownSOAP" 
      type="tns:EmployeeServiceTopDown">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
          style="document"/>
        <operation name="countEmployees">
            <soap:operation 
              soapAction="http://topdown.server.jaxws.baeldung.com/
              EmployeeServiceTopDown/countEmployees"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="EmployeeServiceTopDown">
        <port name="EmployeeServiceTopDownSOAP" 
          binding="tns:EmployeeServiceTopDownSOAP">
            <soap:address 
              location="http://localhost:8080/employeeservicetopdown"/>
        </port>
    </service>
</definitions>

5.1. Generating Web Service Source Files from WSDL

There are several ways to generate web service source files from a WSDL document.

One way is to use the wsimport tool which is part of JDK (at $JAVA_HOME/bin) till JDK 8.

From the command prompt:

wsimport -s . -p com.baeldung.jaxws.server.topdown employeeservicetopdown.wsdl

Command line options used: -p specifies the target package. -s specifies where to put the generated source files.

For later JDK versions, we can use jaxws-maven-plugin by MojoHaus as described here.

Alternatively, org.jvnet.jaxb2‘s maven-jaxb2-plugin can come in handy as detailed in Invoking a SOAP Web Service in Spring.

The generated files:

  • EmployeeServiceTopDown.java – is the service endpoint interface (SEI) that contains method definitions
  • ObjectFactory.java – contains factory methods to create instances of schema derived classes programmatically
  • EmployeeServiceTopDown_Service.java – is the service provider class that can be used by a JAX-WS client

5.2. Web Service Endpoint Interface

The wsimport tool has generated the web service endpoint interface EmployeeServiceTopDown. It declares the web service methods:

@WebService(
  name = "EmployeeServiceTopDown", 
  targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
@XmlSeeAlso({
    ObjectFactory.class
})
public interface EmployeeServiceTopDown {
    @WebMethod(
      action = "http://topdown.server.jaxws.baeldung.com/"
      + "EmployeeServiceTopDown/countEmployees")
    @WebResult(
      name = "countEmployeesResponse", 
      targetNamespace = "http://topdown.server.jaxws.baeldung.com/", 
      partName = "parameters")
    public int countEmployees();
}

5.3. Web Service Implementation

The wsimport tool has created the structure of the web service. We have to create the implementation of the web service:

@WebService(
  name = "EmployeeServiceTopDown", 
  endpointInterface = "com.baeldung.jaxws.server.topdown.EmployeeServiceTopDown",
  targetNamespace = "http://topdown.server.jaxws.baeldung.com/")
public class EmployeeServiceTopDownImpl 
  implements EmployeeServiceTopDown {
 
    @Inject 
    private EmployeeRepository employeeRepositoryImpl;
 
    @WebMethod
    public int countEmployees() {
        return employeeRepositoryImpl.count();
    }
}

6. Bottom-Up (Contract-Last) Approach

In a bottom-up approach, we have to create both the endpoint interface and the implementation classes. The WSDL is generated from the classes when the web service is published.

Let’s create a web service that will perform simple CRUD operations on Employee data.

6.1. The Model Class

The Employee model class:

public class Employee {
    private int id;
    private String firstName;

    // standard getters and setters
}

6.2. Web Service Endpoint Interface

The web service endpoint interface which declares the web service methods:

@WebService
public interface EmployeeService {
    @WebMethod
    Employee getEmployee(int id);

    @WebMethod
    Employee updateEmployee(int id, String name);

    @WebMethod
    boolean deleteEmployee(int id);

    @WebMethod
    Employee addEmployee(int id, String name);

    // ...
}

This interface defines an abstract contract for the web service. The annotations used:

  • @WebService denotes that it is a web service interface
  • @WebMethod is used to customize a web service operation
  • @WebResult is used to customize name of the XML element that represents the return value

6.3. Web Service Implementation

The implementation class of the web service endpoint interface:

@WebService(endpointInterface = "com.baeldung.jaxws.EmployeeService")
public class EmployeeServiceImpl implements EmployeeService {
 
    @Inject 
    private EmployeeRepository employeeRepositoryImpl;

    @WebMethod
    public Employee getEmployee(int id) {
        return employeeRepositoryImpl.getEmployee(id);
    }

    @WebMethod
    public Employee updateEmployee(int id, String name) {
        return employeeRepositoryImpl.updateEmployee(id, name);
    }

    @WebMethod
    public boolean deleteEmployee(int id) {
        return employeeRepositoryImpl.deleteEmployee(id);
    }

    @WebMethod
    public Employee addEmployee(int id, String name) {
        return employeeRepositoryImpl.addEmployee(id, name);
    }

    // ...
}

7. Publishing the Web Service Endpoints

To publish the web services (top-down and bottom-up), we need to pass an address and an instance of the web service implementation to the publish() method of the javax.xml.ws.Endpoint class:

public class EmployeeServicePublisher {
    public static void main(String[] args) {
        Endpoint.publish(
          "http://localhost:8080/employeeservicetopdown", 
           new EmployeeServiceTopDownImpl());

        Endpoint.publish("http://localhost:8080/employeeservice", 
          new EmployeeServiceImpl());
    }
}

We can now run EmployeeServicePublisher to start the web service. To make use of CDI features, the web services can be deployed as WAR file to application servers like WildFly or GlassFish.

8. Remote Web Service Client

Let’s now create a JAX-WS client to connect to the EmployeeService web service remotely.

8.1. Generating Client Artifacts

To generate JAX-WS client artifacts, we can once again use the wsimport tool:

wsimport -keep -p com.baeldung.jaxws.client http://localhost:8080/employeeservice?wsdl

The generated EmployeeService_Service class encapsulates the logic to get the server port using URL and QName.

8.2. Connecting to the Web Service

The web service client uses the generated EmployeeService_Service to connect to the server and make web service calls remotely:

public class EmployeeServiceClient {
    public static void main(String[] args) throws Exception {
        URL url = new URL("http://localhost:8080/employeeservice?wsdl");

        EmployeeService_Service employeeService_Service 
          = new EmployeeService_Service(url);
        EmployeeService employeeServiceProxy 
          = employeeService_Service.getEmployeeServiceImplPort();

        List<Employee> allEmployees 
          = employeeServiceProxy.getAllEmployees();
    }
}

9. Conclusion

This article is a quick introduction to SOAP Web services using JAX-WS.

We have used both the bottom-up and top-down approaches to creating SOAP Web services using the JAX-WS API. We have also written a JAX-WS client that can remotely connect to the server and make web service calls.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)