Read API return on a Jsonobject in case of errors in the URL

Asked

Viewed 560 times

2

I am trying to consume a weather forecast API (https://openweathermap.org/current) in Java but I have a question regarding the return of JSONObject.

I’m using the following code to generate the JSONObject:

 JSONObject obj = new JSONObject(IOUtils.toString(new URL(url), Charset.forName("UTF-8")));

And when I put a valid URL (https://api.openweathermap.org/data/2.5/weather?q=sao+paulo&appid=ccad5d6394c0ebed411edff3fccecb67&lang=pt&units=metric) it works, I can manipulate without problems.

But when I use an invalid URL (https://api.openweathermap.org/data/2.5/weather?q=ABCD&appid=ccad5d6394c0ebed411edff3fccecb67&lang=pt&units=metric) the API returns me a JSON with the 404 code information, but in the browser it accuses the following error:

There was an unexpected error (type=Internal Server Error, status=500).

And in the IDE the following error:

java.io.FileNotFoundException: http://api.openweathermap.org/data/2.5/weather?q=ABCD&appid=ccad5d6394c0ebed411edff3fccecb67&lang=pt&units=metric
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1890) ~[na:1.8.0_191]
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492) ~[na:1.8.0_191]
at java.net.URL.openStream(URL.java:1045) ~[na:1.8.0_191]
at org.apache.commons.io.IOUtils.toString(IOUtils.java:1153) ~[commons-io-2.5.jar:2.5]

The question is, instead of giving the status 500 (Internal Server Error) error, shouldn’t I return the JSON with the 404 error information? How can I get around this problem by getting error 404 of not found in order to deal with the code?

  • I may be completely wrong, but I believe that since the browser only "displays" what java sent the errors generated by the browser are other.

  • It is actually a server created with Spring and Maven, so when I request it, it represents the server error in the browser, so I think doing the check with Conn.getResponseCode() I’ll be able to handle the requisition before I even execute the Conn.getInputStream()

1 answer

2


Accessing the invalid URL in Chrome, the return was JSON:

{"cod":"404","message":"city not found"}

But if we look at Developer Tools (squeeze F12), on the flap Network, we will see that the URL returns the HTTP code 404:

inserir a descrição da imagem aqui

And the IOUtils throws exception when it receives some error code. The solution, in this case, would be to check the error code first and use the stream correct according to their value:

public void readUrl(String url) {
    HttpsURLConnection conn = null;
    try {
        conn = (HttpsURLConnection) new URL(url).openConnection();
        // verificar o código de retorno
        InputStream in;
        if (conn.getResponseCode() == 200) {
            in = conn.getInputStream();
        } else {
            // se deu erro, ler do error stream
            in = conn.getErrorStream();
        }
        JSONObject obj = new JSONObject(IOUtils.toString(in, Charset.forName("UTF-8")));
        System.out.println(obj);
    } catch (IOException e) {
        // tratar erros de conexão
    } finally {
        if (conn != null) {
            conn.disconnect();
        }
    }
}

Testing:

// URL válida
readUrl("https://api.openweathermap.org/data/2.5/weather?q=sao+paulo&appid=ccad5d6394c0ebed411edff3fccecb67&lang=pt&units=metric");
// URL inválida
readUrl("https://api.openweathermap.org/data/2.5/weather?q=ABCD&appid=ccad5d6394c0ebed411edff3fccecb67&lang=pt&units=metric");

The exit is:

{"visibility":10000,"timezone":-10800,"main":{"temp":12.04,"temp_min":11,"humidity":87,"pressure":1027,"temp_max":15},"clouds":{"all":75},"sys":{"country":"BR","sunrise":1563443236,"sunset":1563482272,"id":8394,"type":1,"message":0.0077},"dt":1563449497,"coord":{"lon":-46.64,"lat":-23.55},"weather":[{"icon":"04d","description":"nuvens quebradas","main":"Clouds","id":803}],"name":"Sao Paulo","cod":200,"id":3448439,"base":"stations","wind":{"deg":90,"speed":5.1}}
{"cod":"404","message":"city not found"}

If you want, you can choose not to read from error stream and take some other action, it’s up to you.


Note the use of finally to ensure that the connection is closed at the end of the method execution (you could also have closed the InputStream, the difference is that disconnect does not allow the connection to be reused later).

  • 1

    Thank you, it was exactly what I needed, so in case of the mistake, the right one would be to try to read with getInputStream(), use the getErrorStream() to get feedback and treat this way. I will implement in my code and do the treatment, thanks again!

  • @I made a change to the code, I forgot to close the connection...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.