6.0 Practical Lab II: Building and Consuming Microservices
This exercise will demonstrate the core value proposition of microservices: building an application by composing multiple, independent, and technologically heterogeneous services. Our goal is to create a single Java application that orchestrates three different services—a custom REST service we build, a public SOAP service, and a public REST service—to perform a single, coordinated task. This lab showcases how functionality can be assembled from distributed components.
6.1 Application Architecture and System Setup
The application we will build will follow a chained or orchestrated pattern. We will create a custom REST service whose output will be parsed and used as the input for the other two public services. This demonstrates a common scenario where services collaborate to fulfill a business request.
The prerequisites for this lab include the setup from the previous lab, an internet connection to access public web services, and familiarity with the command line for generating a SOAP client. We will use the following public services:
- SOAP Service: GeoIP service from www.webservicex.net.
- REST Service: Country information service from services.groupkt.com.
6.2 Creating and Consuming the Services
We will follow a step-by-step process to build the orchestrator application and the services it consumes.
Step 1: Client Creation for SOAP Service
To consume a SOAP web service in Java, we first need to generate client stub files from its Web Services Description Language (WSDL) file. A WSDL is an XML document that defines the service’s contract: its methods, parameters, data types, and endpoint location. We use the wsimport command-line tool, included with the JDK, to automate this process. These generated classes act as a local proxy, converting simple Java method calls into the complex XML structure of a SOAP request, thus abstracting the network communication details from the developer.
Run the following command in your terminal: wsimport http://www.webservicex.net/geoipservice.asmx?WSDL
This command will download the WSDL, parse it, and generate a set of Java source files that act as a client proxy to the GeoIP service.
Step 2: Create Your Custom Web Service
Following the same process as Lab I, create a new Maven-based REST API project named CustomRest. In the MyResource.java class generated by the archetype, replace the content with the following code.
package com.tutorialspoint.customrest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path(“myresource”)
public class MyResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return “IND|INDIA|27.7.65.215”;
}
}
Code Analysis: This code creates a very simple REST endpoint at the path /myresource. When a GET request is made to this endpoint, it returns a static, pipe-delimited string: “IND|INDIA|27.7.65.215”. This service will act as the starting point for our data flow, providing the country code, country name, and an IP address that will be used by the subsequent services. Run this application on the server.
Step 3: Configure Another Rest API
The second service we will consume is a public REST API available at services.groupkt.com. This service can provide detailed country information when given a three-letter country code. It returns its data as a JSON object.
Steps 4 & 5: Create Java Application and Add SOAP Client
Create a new, standard Java application project in NetBeans. Then, copy the SOAP client files that were generated in Step 1 into this new project’s source directory. After adding the files, your project structure should include the generated packages and classes (e.g., net.webservicex).
Step 6: Create Your Main App
In the new Java project, create a main class named MicroServiceInAction.java. This class will serve as the orchestrator, responsible for calling the three web services in sequence to achieve the final goal.
Step 7: Call Your Custom Web Service
First, we must call our custom REST service to get the initial data. The following code snippet uses Java’s built-in HttpURLConnection class to make a GET request and read the response.
try {
url = new URL(“http://localhost:8080/CustomRest/webapi/myresource”);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(“GET”);
conn.setRequestProperty(“Accept”, “application/json”); // Although we get text, this is a common header
if (conn.getResponseCode() != 200) {
throw new RuntimeException(“Failed : HTTP error code : ” + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader( (conn.getInputStream())));
while ((output = br.readLine()) != null) {
inputToOtherService = output;
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Code Analysis: This code creates a URL object pointing to our custom service, opens a connection, sets the HTTP method to GET, and crucially checks the server’s response code to ensure the request was successful (an HTTP 200 OK status). It then reads the response stream character by character and assembles it into the inputToOtherService string variable. Finally, it disconnects to release the network resources.
Step 8: Consume SOAP Services
To find the correct method to call in the generated SOAP client, one must refer back to the WSDL file and look for the wsdl:service tag, which defines the entry point. Using the generated client classes, we can now invoke the SOAP service, passing it the IP address we obtained from our custom service.
GeoIPService newGeoIPService = new GeoIPService();
GeoIPServiceSoap newGeoIPServiceSoap = newGeoIPService.getGeoIPServiceSoap();
GeoIP newGeoIP = newGeoIPServiceSoap.getGeoIP(ipAddress);
System.out.println(“Country Name from SOAP Webserivce —“+newGeoIP.getCountryName());
Code Analysis: This code first instantiates the generated service class (GeoIPService). From this object, it gets a “port” or “proxy” object (GeoIPServiceSoap). This proxy object contains the Java methods that correspond to the web service operations. We then call the getGeoIP method, passing the ipAddress string. The generated code handles the complex task of creating a SOAP envelope, sending the request, and parsing the XML response into a GeoIP Java object, from which we can easily extract the country name.
Step 9: Consume REST Web Service
Finally, we consume the second REST service. We will customize the URL for this service using the country code obtained from our custom service. The connection logic is nearly identical to Step 7.
String url1=”http://services.groupkt.com/country/get/iso3code/”;
url1 = url1.concat(countryCode);
try {
URL url = new URL(url1);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(“GET”);
conn.setRequestProperty(“Accept”, “application/json”);
if (conn.getResponseCode() != 200) {
throw new RuntimeException(“Failed : HTTP error code : ” + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader( (conn.getInputStream())));
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Code Analysis: This code constructs the full request URL by concatenating the base URL with the countryCode variable. It then makes a standard GET request and prints the raw JSON response directly to the console.
Step 10: The Consolidated Application
Putting all the pieces together results in the final MicroServiceInAction.java class. This application demonstrates a complete microservice orchestration flow from start to finish.
package microserviceinaction;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.StringTokenizer;
import net.webservicex.GeoIP;
import net.webservicex.GeoIPService;
import net.webservicex.GeoIPServiceSoap;
public class MicroServiceInAction {
static URL url;
static HttpURLConnection conn;
static String output;
static String inputToOtherService;
static String countryCode;
static String ipAddress;
static String CountryName;
public static void main(String[] args) {
// 1. Consume our custom REST web service
try {
url = new URL(“http://localhost:8080/CustomRest/webapi/myresource”);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(“GET”);
conn.setRequestProperty(“Accept”, “application/json”);
if (conn.getResponseCode() != 200) {
throw new RuntimeException(“Failed : HTTP error code : ” + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
while ((output = br.readLine()) != null) {
inputToOtherService = output;
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 2. Parse the response from our custom service
StringTokenizer st = new StringTokenizer(inputToOtherService, “|”);
countryCode = st.nextToken();
CountryName = st.nextToken();
ipAddress = st.nextToken();
// 3. Call the SOAP web service with the IP address from our service
GeoIPService newGeoIPService = new GeoIPService();
GeoIPServiceSoap newGeoIPServiceSoap = newGeoIPService.getGeoIPServiceSoap();
GeoIP newGeoIP = newGeoIPServiceSoap.getGeoIP(ipAddress);
System.out.println(“Country Name from SOAP Webservice —“+newGeoIP.getCountryName());
// 4. Call the public REST API with the country code from our service
String url1 = “http://services.groupkt.com/country/get/iso3code/”;
url1 = url1.concat(countryCode);
try {
URL url = new URL(url1);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod(“GET”);
conn.setRequestProperty(“Accept”, “application/json”);
if (conn.getResponseCode() != 200) {
throw new RuntimeException(“Failed : HTTP error code : ” + conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Final Code Analysis: The application executes in a clear sequence. It first calls the custom REST service. It then uses a StringTokenizer, correctly initialized with the pipe | delimiter, to parse the response into three separate variables: countryCode, CountryName, and ipAddress. The ipAddress is then passed as an argument to the SOAP service call, and the countryCode is used to construct the URL for the second REST service call. This demonstrates a clear and tangible flow of data across independent, distributed services to achieve a unified result.
6.3 Final Output and Analysis
When you run this application (with the CustomRest service already running), the console will display the following output:
Country Name from SOAP Webservice —INDIA
{“RestResponse”:{“messages”:[“Country found matching code [IND].”],”result”:{“name”:”India”,”alpha2_code”:”IN”,”alpha3_code”:”IND”}}}
This simple application successfully demonstrates the core principles of microservice architecture. It composes a new functionality—retrieving detailed country data from an IP address—by orchestrating three separate, independent, and technologically distinct (custom REST, public SOAP, public REST) services. It highlights how complex business goals can be achieved by assembling functionality from distributed and reusable components, which is the foundational strength of the microservice paradigm.