Open In App

Get Time Zone by Providing Latitude and Longitude using Spring MVC and REST API

Spring MVC Framework follows the Model-View-Controller design pattern. It is used to develop web applications. It works around DispatcherServlet. DispatcherServlet handles all the HTTP requests and responses. In this article, we are going to see about a REST API call to find the coordinates for the given latitude and longitude. Each and every area in the globe is identified by means of latitude and longitude. For example, India, Asia/Kolkata timezone can be identified by means of

Latitude -> 21.7679
Longitude -> 78.8718

Corresponding REST API call:



https://api.wheretheiss.at/v1/coordinates/<Latitude,Longitude>

Here in the place of Latitude, we need to substitute the proper Latitude value. In the place of Longitude, we need to substitute the proper Longitude value

Example:



https://api.wheretheiss.at/v1/coordinates/21.7679,78.8718

Output:

REST API call provides JSON response.

 

Via Spring MVC framework, let us parse the REST API call JSON response and render the necessary elements. It can be done via a maven-driven project. Let us see how to do that.

Step by Step Implementation

Project Structure for bringing the timezone value for a given Latitude and Longitude. Let us cover the required JUNIT test cases also for it.

 

Let us check the important files of the project

getTimeZone.jsp




<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>WTIA</title>
    <style type="text/css">
        .main-form, .profile-area {
            width: 640px;
        }
        .main-form {
            margin: 50px auto 0px;
        }
        .profile-area {
            margin: 10px auto;
        }
        .main-form section, .profile-area section {
            margin-bottom: 15px;
            background: #c080c0;
            box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
        }
        .main-form section {
            padding: 30px;
        }
        .profile-area section {
            padding: 30px 30px 30px;
        }
        .profile-area section > div {
            text-align: center;
        }
        .main-form h3 {
            margin: 0 0 15px;
        }
        .form-control, .btn {
            min-height: 38px;
            border-radius: 2px;
        }
        .btn {
            font-size: 20px;
            font-weight: inherit;
            font-family: sans-serif;
        }
        .hideElement {
            display: none;
        }
    </style>
</head>
<body>
<div class="main-form" id="main-form">
    <section>
        <h5 class="text-center">Enter Latitude</h5>
        <div class="form-group">
            <input id="latitude" type="text" class="form-control" placeholder="Enter latitude here..." required="required">
        </div>
        <h5 class="text-center">Enter Longitude</h5>
        <div class="form-group">
            <input id="longitude" type="text" class="form-control" placeholder="Enter longitude here..." required="required">
        </div>
        <div class="form-group">
            <button onclick="loadData()" class="btn btn-primary btn-block">Find TimeZone</button>
        </div>
    </section>
</div>
<div class="profile-area hideElement" id="profile-area">
    <section>
        <div id="loader" class="hideElement">
            <div class="spinner-border" role="status">
                <span class="sr-only">Loading...</span>
            </div>
        </div>
        <div id="profile" class="hideElement">
            <br><br>
             
 
<p><strong>TimeZone: <span id="timezone_id"></strong></span></p>
 
 
        </div>
    </section>
</div>
</body>
<script>
    function loadData() {
        document.getElementById("profile-area").classList.remove("hideElement");
        document.getElementById("loader").classList.remove("hideElement");
        document.getElementById("profile").classList.add("hideElement");
 
        var latitude = document.getElementById("latitude").value;
        var longitude = document.getElementById("longitude").value;
 
 
        if(latitude != "" && latitude != null && longitude != "" && longitude != null) {
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if (this.readyState == 4 && this.status == 200) {
                    var jsonResponse = JSON.parse(this.responseText);
                    document.getElementById("timezone_id").innerHTML = jsonResponse.timezone_id;
                    //document.getElementById("age").innerHTML = jsonResponse.age;
                    document.getElementById("loader").classList.add("hideElement");
                    document.getElementById("profile").classList.remove("hideElement");
                }
            };
            xhttp.open("GET", "getSateliteDetailsByLatAndLon?latitude=" + latitude + "&longitude=" + longitude, true);
            xhttp.send();
            console.log("done");
        } else {
            console.log("Enter latitude and lonitude...")
        }
    }
</script>
</html>

Output:

 

On entering the correct latitude and longitude, we will get the below screens

 

Example 2:

 

Let us see the important files required for the project. As it is the maven project, let us start with 

pom.xml




    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                        http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.wtia.WTIA_Rest_API</groupId>
    <artifactId>WTIA_Rest_API</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>profileGenerator</name>
    <url>http://maven.apache.org</url>
    <properties>
        <failOnMissingWebXml>false</failOnMissingWebXml>
        <spring-version>5.1.0.RELEASE</spring-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring-version}</version>
        </dependency>
 
        <!-- JSTL Dependency -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>javax.servlet.jsp.jstl-api</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
 
        <!-- Servlet Dependency -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
 
        <!-- JSP Dependency -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.6</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>Timezone</finalName>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!-- This should be added to overcome Could not initialize class
                  org.apache.maven.plugin.war.util.WebappStructureSerializer -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>
</project>

Java files:

AppConfig.java




import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
 
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.wtia.WTIA_Rest_API" })
public class AppConfig {
    @Bean
    public InternalResourceViewResolver resolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

SpringMvcDispatcherServletInitializer.java




import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
 
public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }
  
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { AppConfig.class };
    }
  
    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
  
}

WtiaController.java




import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
 
@Controller
public class WtiaController {
 
    @RequestMapping("/getSateliteDetailsByLatAndLon")
    public @ResponseBody
    JsonObject getSateliteDetails(String  latitude,String longitude ) throws IOException {
        JsonObject jsonObject = new JsonObject();
        String timezoneId = getSateliteData(latitude,longitude);
        timezoneId = timezoneId.replaceAll("^\"|\"$", "");
        jsonObject.addProperty("timezone_id", timezoneId);
        return jsonObject;
    }
 
    private String getSateliteData(String latitude,String longitude) throws IOException {
        String data = null;
        StringBuilder responseData = new StringBuilder();
        JsonObject jsonObject = null;
        URL url = null;     
        url = new URL("https://api.wheretheiss.at/v1/coordinates/"+latitude + "," + longitude);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        con.setRequestProperty("User-Agent", "Mozilla/5.0");
        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'GET' request to URL : " + url);
        System.out.println("Response Code : " + responseCode);
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()))) {
            String line;
            while ((line = in.readLine()) != null) {
                responseData.append(line);
            }
            jsonObject = new Gson().fromJson(responseData.toString(), JsonObject.class);         
            data = jsonObject.get("timezone_id").toString();
        }
        System.out.println(data);
        return data;
    }
}

Flow of the Program:

When “getTimeZone.jsp” is called and the proper latitude and longitude are given, it is sent to the “WtiaController.java” file and the GET request mapping is checked against “getSateliteDetailsByLatAndLon” and from jsp, latitude, and longitude are substituted, it will call the REST API call

https://api.wheretheiss.at/v1/coordinates/<Latitude,Longitude>
--Input latitude and longitude are getting substituted here

Then JSON response is parsed and the necessary details like timezone_id or country_code will be displayed. Necessary JUnit test case file

WtiaControllerTest.java




package com.wtia.WTIA_Rest_API.controller;
 
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import static org.junit.Assert.assertEquals;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 
public class WtiaControllerTest {
     
    // It is available in
    // org.springframework.test.web.servlet.MockMvc
    private MockMvc mockMvc;
 
    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(new WtiaController()).build();
    }
 
    @Test
    public void testWTIADetails() throws Exception {
         
        // expected
        String expectedTimezoneId = null;
        StringBuilder responseData = new StringBuilder();
        JsonObject expectedJsonObject = null;
        URL url = new URL("https://api.wheretheiss.at/v1/coordinates/50.11496269845,118.07900427317");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");
        con.setRequestProperty("User-Agent", "Mozilla/5.0");
        try (BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()))) {
 
            String line;
 
            while ((line = in.readLine()) != null) {
                responseData.append(line);
            }
 
            expectedJsonObject = new Gson().fromJson(responseData.toString(), JsonObject.class);
            expectedTimezoneId = expectedJsonObject.get("timezone_id").toString();
            expectedTimezoneId = expectedTimezoneId.replaceAll("^\"|\"$", "");
 
        }
 
        // actual
        MvcResult result = mockMvc.perform(get("/getSateliteDetailsByLatAndLon?latitude=50.11496269845&longitude=118.07900427317"))
                .andReturn();
        String receivedResponse = result.getResponse().getContentAsString();
        JsonObject actualJsonObject = new Gson().fromJson(receivedResponse, JsonObject.class);
        String actualTimezoneId = actualJsonObject.get("timezone_id").toString();
        actualTimezoneId = actualTimezoneId.replaceAll("^\"|\"$", "");
         
        // checking the expectedtimezone and actualtimezone
        assertEquals(expectedTimezoneId, actualTimezoneId);
    }
}

We have to run this file as JUnit test like this.

 

Output:

 

Conclusion

REST APIs are awesome. We can get valuable information from them. As it is producing JSON responses, they are lightweight, easily portable, and adaptable to any technology.


Article Tags :