Java Web Services Tutorial
In this article, we will demonstrate examples of Java Web Services. We will provide a brief introduction to the topic, followed by a SOAP and a REST example in Java.
You can also check this tutorial in the following video:
1. Introduction
From W3C’s definition we are able to infer that there a web service is a piece of software that satisfies 3 key requirements :
- The web service should be designed in such a way, that other applications can interact with it. So there should be some form of data exchange happening between that and external applications.
- The web service should be interoperable, so it should be able to talk to applications across different platforms.
- The communication between this web service and other applications should be facilitated over the network.
The message from an application to a web service is called a Request, and the message back to the application is called a Response. In order to ensure that the web service is interoperable, the Request and Response messages have to be specified in a universal format. The 2 common formats used for this purpose are Javascript Object Notation(JSON) and Extensible Markup Language(XML).
Every web service must provide a definition. The goals of defining a service definition are:
- Specify the request/response format(XML/JSON).
- Define the request and response structure.
- Define and publish the endpoint of a web service.
2. Web Service Types
There are 2 ways to implement it that are defined as follows.
2.1 SOAP
SOAP stands for Simple Object Access Protocol. In SOAP, the request and response exchange format is XML. SOAP also defines a specific request and response XML structure. The service definition in SOAP is referred to as a Web Service Definition Language(WSDL). A WSDL defines the endpoint, all operations that are allowed through it, as well as the request and response structure. The WSDL acts as a contract between the application and the web service. SOAP does not have any restrictions on the transport mechanism of the request and response messages.
2.2 REST
REST stands for Representational State Transfer. The core idea while writing a RESTful web service is to consider any data that gets exposed to an external application as a resource. Each resource is assigned a Uniform Resource Indicator(URI) that can be used to obtain data back by an application. A RESTful web service conforms to the HTTP Methods such as GET, POST, PUT and DELETE, and uses the HTTP Status Codes(200, 404, etc). There is no standard service definition language for a RESTful web service, but popular languages are Swagger and WADL.
3. Tools used
The Java examples in this article were built and run with the following tools and dependencies:
- Java 8
- Maven 3.8.0
- Intellij IDEA Edu 2020.1
- Tomcat 8.0.53
- Jaxws 2.3.1
- Jersey 2.26
4. Currency Web Service
In this article, we will illustrate a currency web service, and how this can be implemented using SOAP and REST. In this section, we will show the pom.xml
, the code for the model object Currency.java
and the underlying static repository class CurrencyDao.java
.
4.1 Maven project
In this section, we will review the pom.xml
that contains the dependencies for the SOAP and RESTful web services.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jcg.ssowmya.demo</groupId> <artifactId>javaWebServices</artifactId> <version>1.0-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <release>11</release> </configuration> </plugin> </plugins> </build> <properties> <tomcat.version>8.0.53</tomcat.version> <jersey.version>2.26</jersey.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> <!-- Jersey for REST web service --> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> <version>${jersey.version}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-common</artifactId> <version>${jersey.version}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>${jersey.version}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>${jersey.version}</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.4.0-b180830.0438</version> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>${jersey.version}</version> </dependency> <!-- Tomcat to test REST web service --> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>${tomcat.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-logging-juli</artifactId> <version>${tomcat.version}</version> </dependency> <!-- JAXWS for SOAP web service --> <dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-rt</artifactId> <version>2.3.1</version> <type>pom</type> </dependency> <dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>rt</artifactId> <version>2.3.1</version> </dependency> </dependencies> </project>
4.2 Currency class
In this section, we will review the model object that will be used for the Currency web service, namely Currency.java
.
Currency.java
package jcg.ssowmya.demo.currency; public class Currency { private Integer id; private String name; private String symbol; private String code; public Currency(int id, String name, String symbol, String code) { this.id = id; this.name = name; this.symbol = symbol; this.code = code; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSymbol() { return symbol; } public void setSymbol(String symbol) { this.symbol = symbol; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Override public String toString() { return "Currency{" + "id=" + id + ", name='" + name + '\'' + ", symbol='" + symbol + '\'' + ", code='" + code + '\'' + '}'; } }
4.3 CurrencyDao class
In this section, we will look at the repository class CurrencyDao.java
that will define the different operations that will be used by the this Currency
CurrencyDao.java
package jcg.ssowmya.demo.currency; import java.util.ArrayList; import java.util.List; import java.util.Optional; public class CurrencyDao { private static List currencyList = new ArrayList(); private static int currencyCount = 0; static { currencyList.add(new Currency(1,"Indian Rupee","Rs","INR")); currencyList.add(new Currency(2,"American Dollar","$","USD")); currencyList.add(new Currency(3,"Canadian Dollar","$","CAD")); currencyList.add(new Currency(4, "Australian Dollar","$","AUD")); } public Currency findByCode(String code) { Optional currencyOptional = currencyList.stream().filter(matchId->code.equals(matchId.getCode())).findAny(); if(currencyOptional.isPresent()) return currencyOptional.get(); return null; } public Currency findById(int id) { Optional currencyOptional = currencyList.stream().filter(matchId->matchId.getId()==id).findAny(); if(currencyOptional.isPresent()) return currencyOptional.get(); return null; } public List findAll() { return currencyList; } public Currency save(Currency currency) { if(currency.getId() == null) currency.setId(++currencyCount); currencyList.add(currency); return currency; } public Currency deleteById(int id) { Optional currencyOptional = currencyList.stream().filter(matchId->matchId.getId()==id).findAny(); if(currencyOptional.isPresent()) { Currency removeCurrency = currencyOptional.get(); currencyList.remove(removeCurrency); return removeCurrency; } return null; } }
To maintain simplicity, we are using a static list of values that will be returned as valid currencies. The CurrencyDao
also has methods to find all or a specific currency, add and delete a currency.
5. SOAP Example in Java
In this section, we will implement a SOAP example in Java. The implementation makes use of Java API for XML Web Services(JAX-WS). There are 2 ways to implement a SOAP web service using JAX-WS :
- Top-down/Contract-first: A WSDL file is first created, and the JAVA classes are generated from the WSDL.
- Bottom-up/Contract-last: The Java classes are first written and the WSDL file is created from the classes.
We will be using the Bottom-up approach in our example, with the Currency
class above as a model.
5.1 CurrencyService interface
In this section, we will implement a CurrencyService
interface that will define the layout of the different operations that can be done by the web service.
CurrencyService.java
package jcg.ssowmya.demo.soapwebservices; import javax.jws.WebMethod; import javax.jws.WebService; import jcg.ssowmya.demo.currency.Currency; import java.util.List; @WebService public interface CurrencyService { @WebMethod public Currency getCurrencyById(int id); @WebMethod public Currency findByCode(String code); @WebMethod public List getAllCurrencies(); @WebMethod public Currency save(Currency currency); @WebMethod public Currency deleteById(int id); }
5.2 CurrencyServiceImpl class
In this section, we will write the class CurrencyServiceImpl
that implements the CurrencyService
interface.
CurrencyServiceImpl.java
package jcg.ssowmya.demo.soapwebservices; import jcg.ssowmya.demo.currency.Currency; import jcg.ssowmya.demo.currency.CurrencyDao; import javax.jws.WebMethod; import javax.jws.WebService; import java.util.List; @WebService(endpointInterface = "jcg.ssowmya.demo.soapwebservices.CurrencyService") public class CurrencyServiceImpl implements CurrencyService{ private static CurrencyDao currencyDao; static { currencyDao = new CurrencyDao(); } @WebMethod public Currency getCurrencyById(int id) { return currencyDao.findById(id); } @WebMethod public Currency findByCode(String code) { return currencyDao.findByCode(code); } @WebMethod public List getAllCurrencies() { return currencyDao.findAll(); } @WebMethod public Currency save(Currency currency) { return currencyDao.save(currency); } @WebMethod public Currency deleteById(int id) { return currencyDao.deleteById(id); } }
5.3 CurrencyServicePublisher class
In this section, we will implement the class CurrencyServicePublisher
to publish the endpoint and start the web service.
CurrencyServicePublisher.java
package jcg.ssowmya.demo.soapwebservices; import javax.xml.ws.Endpoint; public class CurrencyServicePublisher { public static void main(String[] args) { Endpoint.publish("http://localhost:8080/currencyservice", new CurrencyServiceImpl()); } }
In order to view the WSDL, we will need to Run the above class as a Java Application. This can be done by right-clicking the class in an IDE, and click on Run as Application. Then, when we open a browser and go to the URL http://localhost:8080/currencyservice?wsdl we will be able to see the WSDL file in an XML format.
Currency Service WSDL file
<!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.3.1 svn-revision#6ef5f7eb9a938dbc4562f25f8fa0b67cc4ff2dbb. --> <!-- Generated by JAX-WS RI (http://javaee.github.io/metro-jax-ws). RI's version is JAX-WS RI 2.3.1 svn-revision#6ef5f7eb9a938dbc4562f25f8fa0b67cc4ff2dbb. --> <definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://soapwebservices.demo.ssowmya.jcg/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://soapwebservices.demo.ssowmya.jcg/" name="CurrencyServiceImplService"> <types> <xsd:schema> <xsd:import namespace="http://soapwebservices.demo.ssowmya.jcg/" schemaLocation="http://localhost:8080/currencyservice?xsd=1"/> </xsd:schema> </types> <message name="getCurrencyById"> <part name="parameters" element="tns:getCurrencyById"/> </message> <message name="getCurrencyByIdResponse"> <part name="parameters" element="tns:getCurrencyByIdResponse"/> </message> <message name="findByCode"> <part name="parameters" element="tns:findByCode"/> </message> <message name="findByCodeResponse"> <part name="parameters" element="tns:findByCodeResponse"/> </message> <message name="getAllCurrencies"> <part name="parameters" element="tns:getAllCurrencies"/> </message> <message name="getAllCurrenciesResponse"> <part name="parameters" element="tns:getAllCurrenciesResponse"/> </message> <message name="deleteById"> <part name="parameters" element="tns:deleteById"/> </message> <message name="deleteByIdResponse"> <part name="parameters" element="tns:deleteByIdResponse"/> </message> <message name="save"> <part name="parameters" element="tns:save"/> </message> <message name="saveResponse"> <part name="parameters" element="tns:saveResponse"/> </message> <portType name="CurrencyService"> <operation name="getCurrencyById"> <input wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/getCurrencyByIdRequest" message="tns:getCurrencyById"/> <output wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/getCurrencyByIdResponse" message="tns:getCurrencyByIdResponse"/> </operation> <operation name="findByCode"> <input wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/findByCodeRequest" message="tns:findByCode"/> <output wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/findByCodeResponse" message="tns:findByCodeResponse"/> </operation> <operation name="getAllCurrencies"> <input wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/getAllCurrenciesRequest" message="tns:getAllCurrencies"/> <output wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/getAllCurrenciesResponse" message="tns:getAllCurrenciesResponse"/> </operation> <operation name="deleteById"> <input wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/deleteByIdRequest" message="tns:deleteById"/> <output wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/deleteByIdResponse" message="tns:deleteByIdResponse"/> </operation> <operation name="save"> <input wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/saveRequest" message="tns:save"/> <output wsam:Action="http://soapwebservices.demo.ssowmya.jcg/CurrencyService/saveResponse" message="tns:saveResponse"/> </operation> </portType> <binding name="CurrencyServiceImplPortBinding" type="tns:CurrencyService"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <operation name="getCurrencyById"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> <operation name="findByCode"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> <operation name="getAllCurrencies"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> <operation name="deleteById"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> <operation name="save"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> </binding> <service name="CurrencyServiceImplService"> <port name="CurrencyServiceImplPort" binding="tns:CurrencyServiceImplPortBinding"> <soap:address location="http://localhost:8080/currencyservice"/> </port> </service> </definitions>
5.4 CurrencyService Client application
In this section, we will review how to implement a client application that calls the web service we have created above. There are 2 parts to this process.
5.4.1 Generate Client artifact
The client application usually does not have access to the model objects that are used by the web service, unless these are made available in a JAR. However, in order to preserve the interoperability concept of web services, the client API is generated from the WSDL, by using the wsimport tool, which is part of the JDK package.
wsimport command line tool
wsimport -keep -p jcg.ssowmya.demo.jaxws.client http://localhost:8080/currencyservice?wsdl
In the above command, the -p
is used to specify the target location for the generated Java files. After running this command from the source folder of the project, we will see a number of Java classes generated under the package jcg.ssowmya.demo.jaxws.client
.
5.4.2 CurrencyServiceClient class
Now that we have a local copy of the API, we will see how to write the client application that invokes to retrieve data.
CurrencyServiceClient.java
package jcg.ssowmya.demo.soapwebservices.client; import src.main.java.jcg.ssowmya.demo.jaxws.client.Currency; import src.main.java.jcg.ssowmya.demo.jaxws.client.CurrencyService; import src.main.java.jcg.ssowmya.demo.jaxws.client.CurrencyServiceImplService; import java.net.URL; import java.util.List; public class CurrencyServiceClient { public static void main(String[] args) throws Exception{ URL url = new URL("http://localhost:8080/currencyservice?wsdl"); CurrencyServiceImplService currencyServiceImplService = new CurrencyServiceImplService(url); CurrencyService currencyService = currencyServiceImplService.getCurrencyServiceImplPort(); List currencyList = currencyService.getAllCurrencies(); System.out.println("Number of currencies retrieved: "+currencyList.size()); } }
6. REST Example in Java
In this section, we will show how to write a simple RESTful web service. The base model class for the REST Example will be Currency.java
, and the repository class will be CurrencyDao.java
that have been shown above. Further, the REST web service will make use of the Jersey dependency specified in the pom.xml
code above.
6.1 CurrencyResource class
For this the key idea is to view every base model object as a resource, and to get specific data from the resource, we will be using a Uniform Resource Identifier(URI). Let us look at an implementation of the CurrencyResource
class.
CurrencyResource.java
package jcg.ssowmya.demo.restfulwebservices; import jcg.ssowmya.demo.currency.Currency; import jcg.ssowmya.demo.currency.CurrencyDao; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import java.util.List; @Path("/CurrencyService") public class CurrencyResource { private CurrencyDao currencyDao = new CurrencyDao(); @GET @Path("/hello") @Produces(MediaType.TEXT_PLAIN) public String helloWorld() { return "Hello!"; } @GET @Path("/currency") @Produces(MediaType.APPLICATION_JSON) public List getAllCurrency() { return currencyDao.findAll(); } }
From the above code, we see that we will need to use the path /CurrencyService/currency
to retrieve the list of all currencies in JSON format.
6.2 Web.xml
The RESTful web service will need to be deployed as a web application on a local Tomcat server, and hence we will need to write a web.xml
as follows:
web.xml
<?xml version = "1.0" encoding = "UTF-8"?> <web-app xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns = "http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id = "javaWebServices" version = "3.0"> <display-name>Java Restful Web Services</display-name> <servlet> <servlet-name>Currency RESTful Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>jcg.ssowmya.demo.restfulwebservices</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Currency RESTful Application</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
6.3 CurrencyResourceApplication class
There are 2 ways to run the RESTful web service. If we have a local Tomcat server, then we just need to deploy it. If we do not have a locally installed Tomcat, then the class below will start an embedded Tomcat Server that will be used to deploy the web service.
CurrencyResourceApplication
package jcg.ssowmya.demo.restfulwebservices; import org.apache.catalina.Context; import org.apache.catalina.startup.Tomcat; import org.glassfish.jersey.servlet.ServletContainer; import java.io.File; public class CurrencyResourceApplication { public static void main(String[] args) throws Exception { Tomcat tomcat = new Tomcat(); tomcat.setPort(8082); tomcat.setBaseDir("tmp"); String webAppDirLocation ="src/main/resources/webapp/"; Context context = tomcat.addWebapp("/restfulws", new File(webAppDirLocation).getAbsolutePath()); File configFile = new File(webAppDirLocation+"WEB-INF/web.xml"); context.setConfigFile(configFile.toURI().toURL()); tomcat.start(); tomcat.getServer().await(); } }
In our IDE, we can right click on this class and select “Run as Application“. This will start an embedded Tomcat server on port 8082. Then, we can open any browser and type the URL http://localhost:8082/restfulws/CurrencyService/currency. This will result in the following JSON output in our browser:
Browser output for /CurrencyService/currency
[{"id":1,"name":"Indian Rupee","symbol":"Rs","code":"INR"},{"id":2,"name":"American Dollar","symbol":"$","code":"USD"},{"id":3,"name":"Canadian Dollar","symbol":"$","code":"CAD"},{"id":4,"name":"Australian Dollar","symbol":"$","code":"AUD"}]
7. Summary
In this article, we saw 2 different implementations of Java Web Services, using SOAP and REST. We were able to highlight the differences in implementations between the two, as well as the formats of the request and response messages in each case.
8. Download the Source Code
You can download the full source code of this example here: Java Web Services Tutorial