- Build a simple Weather App using Spring Boot, the OpenWeatherMap API, and Thymeleaf as the front-end template engine. Users can enter a city name, and the application will fetch and display current weather details.
- To get Api and APIKeys from “https://home.openweathermap.org/“
- After signup/login
- Get APIKey from “https://home.openweathermap.org/api_keys“
- Get APIURL: “https://api.openweathermap.org/data/2.5/weather?q={city name}&appid={API key}“
example:-
https://api.openweathermap.org/data/2.5/weather?q=Thiruvallur&appid=93c30d18b6d15d780cc94b291984ad88
Weather Response:
- you get response in JSON data format
Note:-
JSON response came from API call , now we need return the response to now created project.
Now we want to read to json data ,but we do not know how to write program , Don worry we need to add dependencies , that one is Jackason DataBind (Jackson Databind is a Java library that allows you to easily convert (bind) JSON data to Java objects and vice versa.)
Main Use of Jackson Databind:-
- Read JSON => Java Object (Deserialization)
- Write Java Object => JSON (Serialization)
Link:-
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind/2.19.2
copy dependencies and paste to you pom.xml
one website (you app or website) can get data from another website (open weather) using public ApI, This is Apis work.
1. Overall Project Flow
Request-Response Flow:-
User => Enters City in Form (HTML) => Controller => Service => OpenWeatherMap API
<= Response => Data sent to View via Model => Weather Displayed on Web Page
2.WeatherResponse.java (Model Layer)
Purpose: maps the Api Response to java objects using jackson.
Contains:
- name = city name
- main = temperature, humidity, etc.
- weather[] = an array of weather descriptions @JsonIgnoreProperties(ignoreUnknown = true) , ensure that any unnecesary Json fields.
package com.example.demo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
// we need particular JSON data another data ignore
@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResponse {
// only need those response from like https://api.openweathermap.org/data/2.5/weather?q=Thiruvallur&appid=93c30d18b6d15d780cc94b291984ad88
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Main getMain() {
return main;
}
public void setMain(Main main) {
this.main = main;
}
public Weather[] getWeather() {
return weather;
}
public void setWeather(Weather[] weather) {
this.weather = weather;
}
private String name ;
private Main main ; // Main class
private Weather[] weather; // weather class for array
}
// we want to use this response this class only that why private (like one time usage) and that why we create above the class's in same class
class Main
{
private double temp;
private int humidity;
private int sea_level;
private int pressure ;
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
public int getHumidity() {
return humidity;
}
public void setHumidity(int humidity) {
this.humidity = humidity;
}
public int getSea_level() {
return sea_level;
}
public void setSea_level(int sea_level) {
this.sea_level = sea_level;
}
public int getPressure() {
return pressure;
}
public void setPressure(int pressure) {
this.pressure = pressure;
}
public int getGrnd_level() {
return grnd_level;
}
public void setGrnd_level(int grnd_level) {
this.grnd_level = grnd_level;
}
private int grnd_level;
}
class Weather
{
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
// now we done json object convert to java object
3.WeatherController.java (Controller Layer)
- Controller handles the web API request.
- Calls the service to get weather data.
- Sends the data to the view using Model.
model.addAttribute("weather", weatherResponse);
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
public class WeatherController {
@Autowired
private WeatherService weatherService;
@GetMapping("/")
public String display()
{
return "weather";
}
// now to create src/main/resource create weather.html under templates
@GetMapping("/weather")
public String show_weather_details(@RequestParam String city , Model model)
{
// @RequestParam get data from the URL
/* Example: If URL is http://localhost:8080/weather?city=Chennai
* Then city will have the value "Chennai"
It reads the ?city=Chennai part from the URL.
* Model model
* it is used to store data that you want to send to the HTML(Thymleaf) page
* like Model is used to store and pass data from the controller to the view (HTML
*
*/
/* now Below this thing , to implement to code to service class.
* Api key ,we already defined application properties.
* City
* APIURL
* weather responce
*
*/
WeatherResponse weatherResponse = weatherService.getWeather(city); // 7
model.addAttribute("weather", weatherResponse);
return "weather" ;
}
}
** 4. WeatherService.java (Service Layer)**
- Purpose: Make the Rest Api call to OpenWeathermap using RestTemplate.
Uses:
return restTemplate.getForObject(APIURL, WeatherResponse.class, city, apiKey);
- Uses @Value("${weather.api.key}") to inject the API key from application.properties
package com.example.demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class WeatherService {
// Api key ,we already defined application properties
@Value("${weather.api.key}") // get the value in application properties
private String apiKey;
// * APIURL
private final String APIURL = "https://api.openweathermap.org/data/2.5/weather?q={city}&appid={apiKey}";
public WeatherResponse getWeather (String city)
{
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(APIURL,WeatherResponse.class,city,apiKey); // 5
// * weather response
//How to API Response data (Like weather data) get into to browser page (htmlpage ), That one is RestTemplate .
// Now we return APIURL,WeatherResponce.class(pojo class) ,city,apiKey with used to RestTemplate , to WeatherResponce class .
// now we connect to controller and response class go to controller class
}
}
5.Apllication properties
weather.api.key=YOUR_API_KEY_HERE
6.weather.html (View Layer - Thymeleaf)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Weather App</title>
<style>
body {
font-family: Arial, sans-serif;
background: linear-gradient(to right, #83a4d4, #b6fbff);
color: #333;
padding: 20px;
text-align: center;
}
.weather-box {
background-color: white;
border-radius: 10px;
padding: 30px;
max-width: 400px;
margin: 30px auto;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
}
input[type="text"] {
padding: 10px;
width: 60%;
border: 1px solid #ccc;
border-radius: 5px;
margin-top: 20px;
}
button {
padding: 10px 20px;
border: none;
background-color: #007BFF;
color: white;
border-radius: 5px;
margin-left: 10px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.info {
margin-top: 20px;
}
.error {
color: red;
}
</style>
</head>
<body>
<h1>🌦 Weather Application</h1>
<form action="/weather" method="get">
<input type="text" name="city" placeholder="Enter city name" required>
<button type="submit">Search</button>
</form>
<!-- Weather Result Section -->
<div class="weather-box" th:if="${weather != null}">
<h2 th:text="${weather.name}">City Name</h2>
<p class="info">🌡 Temperature: <span th:text="${weather.main.temp}"></span> °C</p>
<p class="info">💧 Humidity: <span th:text="${weather.main.humidity}"></span>%</p>
<p class="info">🌤 Condition: <span th:text="${weather.weather[0].description}"></span></p>
</div>
<!-- Show message if weather not found or city not entered -->
<div th:if="${weather == null}">
<p class="error">No weather data available. Please enter a valid city.</p>
</div>
</body>
</html>
<!-- when you submit that button it trigger the weather action , now back to controller class -->
Final Results:-
Top comments (0)