0
votes

I am Creating a REST API in java and testing it in postman and in the database have the latitude and longitude, I am trying to use the OpenWeather API to return weather data based on the latitude and longitude. however, when testing it in postman it is returning an HTML and not the JSON data I requested.

the path I am trying to test is

http://localhost:8080/Assignment2C/map/weather/4

the code in my controller is

  @GetMapping(value = "weather/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public String getWeather(@PathVariable("id") int id) {
        BreweriesGeocode geocode = geocode_service.getGeocode(id);
        Breweries brewerie = breweries_service.getBrewerieById(id);

        double latitude = geocode.getLatitude();
        double longitude = geocode.getLongitude();
       String output = "https://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&appid=4a1f5501b2798f409961c62d384a1c74";
       return output;

when using Postman it returns this

https: //api.openweathermap.org/data/2.5/weather?lat=59.74509811401367&lon=10.213500022888184&appid=4a1f5501b2798f409961c62d384a1c74

but when I test the path that postman produces in the browser

https://api.openweathermap.org/data/2.5/weather?lat=59.74509811401367&lon=10.213500022888184&appid=4a1f5501b2798f409961c62d384a1c74

it returns the correct JSON data

which is

{"coord":{"lon":10.21,"lat":59.75},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"base":"stations","main":{"temp":291.36,"feels_like":289.49,"temp_min":288.71,"temp_max":294.26,"pressure":1028,"humidity":40},"wind":{"speed":0.89,"deg":190},"clouds":{"all":1},"dt":1587551663,"sys":{"type":3,"id":2006615,"country":"NO","sunrise":1587526916,"sunset":1587581574},"timezone":7200,"id":6453372,"name":"Drammen","cod":200}

how do I get the JSON data to appear in postman when I test it?

2

2 Answers

1
votes

The Postman is parsing/showing the correct value, as you are sending the url in the response.

To call an API within your code you need to use a HTTP Client/Handler. If you just assign the URL to a variable it will simply store it as a string and it is never going to call given url.

RestTemplate class (available by default in Spring, no other dependency required) is a simple HTTP client which allows to make API calls from within your code.
You can use RestTemplate to call the OpenWeather API and get the JSON response, the same response can be returned and viewed in Postman.


If you are sure that you are going to make only HTTP calls and no HTTPS, then follow approach 1 otherwise follow approach 2 -

Approach 1 :

@RestController
public class WeatherController{

    @Autowired
    RestTemplate restTemplate;

    @GetMapping(value = "weather/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public String getWeather(@PathVariable("id") int id) {
        BreweriesGeocode geocode = geocode_service.getGeocode(id);
        Breweries brewerie = breweries_service.getBrewerieById(id);

        double latitude = geocode.getLatitude();
        double longitude = geocode.getLongitude();
        String url = "http://api.openweathermap.org/data/2.5/weather?lat="+latitude+"&lon="+longitude+"&appid=4a1f5501b2798f409961c62d384a1c74";

        //Calling OpenWeather API
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
        String output = response.getBody();
        return output;
    }
}

Approach 2 :

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class CustomRestTemplate {

    /**
     * @param isHttpsRequired - pass true if you need to call a https url, otherwise pass false
     */
    public RestTemplate getRestTemplate(boolean isHttpsRequired)
            throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

        // if https is not required,
        if (!isHttpsRequired) {
            return new RestTemplate();
        }

        // else below code adds key ignoring logic for https calls
        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
        SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy)
                .build();

        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);

        RestTemplate restTemplate = new RestTemplate(requestFactory);       
        return restTemplate;
    }
}

Then in the controller class you can do as below-

@RestController
public class WeatherController{


    @Autowired
    CustomRestTemplate customRestTemplate;

    @GetMapping(value = "weather/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public String getWeather(@PathVariable("id") int id) {
        BreweriesGeocode geocode = geocode_service.getGeocode(id);
        Breweries brewerie = breweries_service.getBrewerieById(id);

        double latitude = geocode.getLatitude();
        double longitude = geocode.getLongitude();
        String url = "https://api.openweathermap.org/data/2.5/weather?lat="+latitude+"&lon="+longitude+"&appid=4a1f5501b2798f409961c62d384a1c74";

        // Getting instance of Rest Template
        // Passing true becuase the url is a HTTPS url
        RestTemplate restTemplate = customRestTemplate.getRestTemplate(true);

        //Calling OpenWeather API
        ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

        String output = response.getBody();

        return output;
    }
}

You can write a Http Error Handler for the RestTemplate reponses if reponse code is not a success code.

1
votes

I tested the URL in postman, it returns the correct response. Check the below screen maybe you're doing something different. Postman response

Make sure there are no spaces in url, i see the url you used in Postman had space after the ":"