In a world of microservices development and Docker-based deployments, RESTful web services tend to grab all of the headlines. And while the design of RESTful APIs can be a challenge, modern frameworks like Spring Boot and JAX-RS make RESTful web services incredibly easy to develop. As such, their proliferation comes as no surprise.
But we've made great strides in the world of JAX-WS (Java API for XML Web Services), and modern SOAP (Simple Object Access Protocol) web services development is no longer the arduous task it once was. In this step-by-step SOAP web services example in Java using Eclipse, we will demonstrate just how easy it is to develop and test a web service based in JAX-WS. The simplicity might surprise you. In fact, this SOAP web services tutorial might even convince you to give up on your RESTful APIs for good.
SOAP web services example
In a recently published Spring Boot RESTful web services tutorial, we implemented a microservice that keeps track of the number of wins, losses and ties in an online game of rock-paper-scissors. In this SOAP web services example in Java using Eclipse, I would like to implement the exact same use case, only with JAX-WS instead of JAX-RS.
Step 1: Create the Eclipse project
The first step is simply to create a dynamic web project in Eclipse named soap-ws-example. The project should use web module version 3.1, employ a minimal configuration and be associated with a runtime that supports the Java web profile. For this SOAP web services example in Java using Eclipse, we will employ WildFly 10.x as the chosen runtime.
Step 2: Code the Score class
This SOAP web services example will use two classes: a simple POJO (Plain Old Java Object) named Score and a class that mitigates remote access to the Score class named ScoreService. We will keep the Score class incredibly simple. The class will declare only three public variables, each of type int, named wins, losses and ties. To really keep things tight, we won't even add any setters or getters.
Step 3: Add XML annotations
The only minor complication to the Score class is that you have to decorate it with a couple of annotations. Since the data the Score class encapsulates will be sent to SOAP web services clients in XML format, the class requires an @XMLType annotation. Furthermore, since the class has no getter methods, the XML engine will need to look directly at the properties of the Score class. So, add an @XmlAccessorType annotation that indicates field-based access. The complete class looks as follows:
Step 4: Code the ScoreService
The ScoreService class will mitigate access to the Score class through methods such as getScore(), increaseWins() and getLosses(). Initialize the instance of the Score class the ScoreService references through dependency injection, or read from a NoSQL database, as a web service should never maintain any internal state. But to keep this SOAP web services example in Java using Eclipse as simple as possible, we will cheat a little and simply make the Score instance static. This will work when the SOAP web services example is tested on a single Java virtual machine. Just keep in mind that such an approach would fail in a distributed environment.
Step 5: Add SOAP WebService annotations
To turn the ScoreService into a SOAP web service, it needs to be decorated with two annotations: one to indicate the class complies with all of the semantics of a stateless Enterprise JavaBeans (EJB) architecture and another to indicate that the public methods in the class can be accessed through a SOAP-based service. The first iteration of the SOAP web services example looks as follows:
Step 6: Enhance the SOAP web service
All of the methods in the first iteration of the SOAP web services example have empty method signatures. To demonstrate how easy it is to pass data to a SOAP web service, we will add an updateScore method that takes three int parameters, updates all of the instance variables of the Score class and returns the updated Score instance:
Step 7: Use the @WebMethod annotation
Next, we will add a reset method. This sets the number of wins, losses and ties to nil.
The method in the class will be named reset, but when SOAP web services clients invoke the method, we want the remote API call to be resetScore. To override the default method to Web Services Description Language (WSDL) mappings, JAX-WS provides a special annotation called @WebMethod. By changing the operationName attribute of the @WebMethod annotation, the method name used by the SOAP web services client can be tweaked.
Step 8: Run and test the SOAP web service
With the Score and the ScoreService classes completed, simply right-click on the soap-ws-example project, and select Run As > Run on Server.
As the SOAP web services example starts, look in the console output of the server for a reference to a WSDL file. As the web container processes the @WebService annotation, it will create a WSDL file that describes the service's remote API. Note the location of the WSDL file.
Once you know the location of the WSDL file, open Eclipse's Web Services Explorer, and browse to the file. This will then open a web-based SOAP client that can you can use to invoke all of the public methods of the web service.
And that's all there is to it.
In the past, years before the release of the EJB 3.0 specification and the introduction of the @WebService annotation, the creation of a SOAP-based web service meant writing WSDL files. This was arduous work with XML parsing libraries and a fight with SOAP envelopes. But today, using popular frameworks and a modern IDE, web services development is extremely simple, as this SOAP web services example in Java using Eclipse demonstrates.
The Java source code used in this SOAP web services example in Java can be found on GitHub.