How to fetch weather forecast data from a RESTful web service in Java

In this article, we will use a RESTful web service to retrieve weather forecast data into a simple Java application. We will first retrieve the data as a comma separator value (CSV) string. After that we will retrieve the same weather forecast in JSON format so we can manipulate the weather forecast data easily within our Java application.

You can find the full sample code for this article on our GitHub:

https://github.com/visualcrossing/WeatherApi/blob/master/Java/com/visualcrossing/weather/samples/WeatherForecastRetrieval.java

Steps to retrieving the weather forecast in Java

Retrieving the weather forecast in Java is quite straightforward. Here are the steps involved:

  1. Create a RESTful request to retrieve the weather forecast.
  2. Retrieve the data via HTTP GET query.
  3. Process the data as as CSV or JSON.

Prerequisites

We are using the Visual Crossing Weather API so we need an API key to get started. Before continuing, please set up a free account and make a note of the API Key.

If you would like to experiment with the available weather data without using the API, you can create an account and view the data directly in the browser using the Weather Data Services.

Sample code one – retrieve the Weather Forecast as CSV in Java

In our first sample code, we will construct the Weather API request and retrieve the CSV formatted result.

Set up Apache HttpComponents

We will use the Apache HttpComponents library to submit the HTTP request. It’s possible to do this using raw Java communication packages, but using a library such as HttpComponents allows us to focus on constructing the Weather API request and processing the result. If you have a different library to submit and retrieve HTTP requests, then that should work as well.

To include the Apache HttpComponents you can use the following Maven Dependency:

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.5.12</version>
</dependency>

Importing the HTTPS certificate into your Java Keystore

As the weather API endpoint is a secure HTTPS endpoint, you may need to import the certificate into your Java keystore. For more information, see https://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html

Constructing the Weather API request

The following code constructs the request to retrieve the weather forecast for London, UK by day.

URIBuilder builder = new URIBuilder("https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/weatherdata/forecast");
		
builder.setParameter("aggregateHours", "24")
   .setParameter("contentType", "csv")
   .setParameter("unitGroup", "metric")
   .setParameter("key", "YOUR_API_KEY")
   .setParameter("locations", "London,UK");

There are two parts to the code. The first part sets up the end point of the request (/forecast). The second parts adds the parameters to the request. We are using six parameters:

aggregateHours=24 – we want a daily forecast so we specify 24 hours. We coudl also retrieve an hourly forecast using 1 or a day/night forecast using 12.

contentType=csv – We are retrieving the forecast in CSV table format.

unitGroup=metric – We would like metric units (eg celsius for temperature and mm for rainfall etc). We could also specify ‘us’ for the units typically used in the United States (fahrenheit, inches etc).

key=YOUR_API_KEY – to unique identify your request.

locations=London,UK – one or more locations specified by address, partial address (for example city, postal code or zip) or latitude, longitude values.

For more information on the parameters of the Weather API, see the API documentation.

Submit the Weather API Request

The following code submits the request to the Weather API. The techniques here are based around the fundamentals of the HttpClient.

String csvWeatherForecast = null;
		
//Retrieve the result
HttpGet get = new HttpGet(builder.build());
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(get);    

try {
   if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
      System.out.printf("Bad response status code:%d%n", 
      response.getStatusLine().getStatusCode());
      return;
   }
	
   HttpEntity entity = response.getEntity();
   if (entity != null) {
      csvWeatherForecast=EntityUtils.toString(entity, Charset.forName("utf-8"));
   }
    
} finally {
   response.close();
}

Note that we do not perform exception handling for clarity. It is important to ensure that the http response is closed when it’s used.

If the request is successful, we now have the weather forecast populated as a CSV formatted in the ‘csvWeatherForecast’ variable. We can then print it out:

System.out.printf("Result data:%n%s%n", csvWeatherForecast);

Sample code two – retrieve the Weather Forecast as JSON in Java

The previous code sample retrieves the weather forecast data as a CSV. In many cases it’s necessary to retrieve the data in a format that is easier to manipulate in Java. To do this we will now illustrate how to retrieve the same forecast but in JSON format.

Here’s the new request:

URIBuilder builder = new URIBuilder("https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/weatherdata/forecast");

builder.setParameter("aggregateHours", "24")
	.setParameter("contentType", "json")
	.setParameter("locationMode", "single")
	.setParameter("unitGroup", "metric")
	.setParameter("key", "1PYNQ6AWUDJE9AFERDCHJHSXK")
	.setParameter("locations", "London,UK");

There are two important differences in the request:

.setParameter(“contentType”, “json”)
.setParameter(“locationMode”, “single”)

Firstly, we retrieve the data in JSON format not CSV. In addition, we specify that we want the simplest form of the JSON because we are requesting the weather forecast for a single location. If we were requesting the forecast for multiple locations we could retrieve the locations as an array or Map.

Retrieving the data is almost identical however we are now going to parse the resulting string as JSON. In this sample we will use the org.json.JSON library. Other libraries do exist so you may choose one that suits your needs (or maybe that you are already using).

To add org.json.JSON as a dependency, you can use the following Maven dependency:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20200518</version>
</dependency>

To retrieve the weather forecast data and parse the result as JSON, we can then use very similar code to the above:

JSONObject jsonWeatherForecast = null;
 
HttpGet get = new HttpGet(builder.build());
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(get);    


try {
 if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
 System.out.printf("Bad response status code:%d%n", response.getStatusLine().getStatusCode());
 return;
 }
 
 HttpEntity entity = response.getEntity();
    if (entity != null) {
     String rawResult=EntityUtils.toString(entity, Charset.forName("utf-8"));
     
     jsonWeatherForecast = new JSONObject(rawResult);
     
    }
     
} finally {
 response.close();
}

Note that the only difference is that we parse the rawResult as JSON by creating a JSONObject:

jsonWeatherForecast = new JSONObject(rawResult);

Using the JSON Weather Data in Java

Now we have weather forecast as a JSONObject instance, we can use the data. In this case let’s just print out the high temperature, low temperature and probability of rainfall for each day of the forecast.

First we extract the location from the JSON:

JSONObject location=jsonWeatherForecast.getJSONObject("location");

System.out.printf("Weather forecast for: %s%n", location.getString("address"));
		

Each location includes an array of values representing the weather forecast data for each time period. In our cases each 24 hour day. We can retrieve the array easily:

JSONArray values=location.getJSONArray("values");

We can now display the weather forecast for each of the upcoming days using a simple loop:

System.out.printf("Date\tMaxTemp\tMinTemp\tChangeofPrecip%n");
for (int i = 0; i < values.length(); i++) {
    JSONObject forecastValue = values.getJSONObject(i);
    String datetimeString=forecastValue.getString("datetimeStr");
            
    ZonedDateTime datetime=ZonedDateTime.parse( datetimeString,                       DateTimeFormatter.ISO_OFFSET_DATE_TIME);
            
    double maxtemp=forecastValue.getDouble("maxt");
    double mintemp=forecastValue.getDouble("mint");
    double pop=forecastValue.getDouble("pop");

    System.out.printf("%s\t%.1f\t%.1f\t%.0f%n", datetime.format(DateTimeFormatter.ISO_LOCAL_DATE), maxtemp, mintemp, pop);
}

As you can see, the code iterates through the values and extracts the datetimeStr, maxt, mint and pop properties.

The ‘datetimeStr’ property is interesting because it is a ISO 8601 formatted string that includes the date, time and timezone of the weather forecast time period. In the sample we code, we parse this as a ZonedDateTime using Java’s inbuilt default DateTimeFormatter instance. We then reformat it as a simple local date. For more information on dates and times in the Weather API, see Dates and Times in the Weather API.

For more information on the structure of the JSON, including how the options to include multiple location results, see Weather API JSON structure.

Conclusions

Retrieving the weather forecast into a Java application is very straightforward with simple Java application such as this. This could be extended to retrieve historical weather data. If you have any questions or comments, let me know below in the comments!

Leave a Reply

Your email address will not be published. Required fields are marked *