1

I am trying to perform a get request using Groovy using the below code:

String url = "url of endpoint" def responseXml = new XmlSlurper().parse(url)

If the endpoint returns status as 200 then everything works good but there is one case where we have to validate the error response like below and status returned is 400:

    <errors>
    <error>One of the following parameters is required: xyz, abc.</error>
    <error>One of the following parameters is required: xyz, mno.</error>
    </errors>

In this case parse method throws :


    java.io.IOException: Server returned HTTP response code: 400 for URL: "actual endpoint throwing error"
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1900)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
        at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:646)
        at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:150)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:831)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:796)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:142)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1216)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:644)
        at groovy.util.XmlSlurper.parse(XmlSlurper.java:205)
        at groovy.util.XmlSlurper.parse(XmlSlurper.java:271)
    
Can anyone pls suggest how to handle if server give error message by throwing 400 status code?

3 Answers3

1

In the question since we are getting 400 status code for GET request. So in built XmlSlurper().parse(URI) method does not work as it throw io.Exception. Groovy also support HTTP methods for api request and response and the below worked for me:

def getReponseBody(endpoint) {     
    URL url = new URL(endpoint)
    HttpURLConnection get = (HttpURLConnection)url.openConnection()
    get.setRequestMethod("GET")
    def getRC = get.getResponseCode()

    BufferedReader br = new BufferedReader(new InputStreamReader(get.getErrorStream()))
    StringBuffer xmlObject = new StringBuffer()
    def eachLine
    while((eachLine = br.readLine()) !=null){
        xmlObject.append(eachLine)
    }
    get.disconnect()
    return new XmlSlurper().parseText(xmlObject.toString())
}
Andronicus
  • 25,419
  • 17
  • 47
  • 88
  • Just a few comments on groovy conventions here that might help make your code a bit more readable. (1) groovy has dynamic dispatch, so casting to `HttpURLConnection` is not really needed. (2) just about all your "getter" and "setter" invocations can be reduced to property expressions, e.g.: `get.setRequestMethod("GET")` could be `get.requestMethod = "GET"`. (3) groovy extensions for the `Reader` class (of which `BufferedReader` is a subclass) allow you to reduce lines 8 thru 12 to `String xmlObject = br.text`. – BalRog May 09 '22 at 16:01
  • (4) Or you could just use the `Reader` overload of `XmlSlurper.parse` and replace lines 8 thru 14 with `return new XmlSlurper().parse(br)`. – BalRog May 09 '22 at 16:06
1

You should check the return code and than obtain the error stream from http request instance in case of an error. The problem itself has nothing to do with JsonSlurper, as no instance of "input stream" is returned from http request instance if service returns not successfull return codes (400, 401, 500 etc.) POST example can be seen below:

http= new URL("yourUrl").openConnection() as HttpURLConnection
http.setRequestMethod('POST')
http.setDoOutput(true)
http.setRequestProperty("Content-Type", 'application/json')
http.setRequestProperty("Accept", 'application/json')
http.setRequestProperty("Authorization", "Bearer $yourTokenVariable")
http.outputStream.write(data.getBytes("UTF-8"))
http.connect()
 
if(http.getResponseCode() != 200 && http.getResponseCode() != 201){ 
     throw new InvalidInputException("There was an error: " + http.getErrorStream().getText("UTF-8"))
} else {
    //You can take input stream here
}
metzelder
  • 655
  • 2
  • 15
  • 35
0

Getting the response text from the HttpURLConnection class rather than implicitly through XmlSlurper allows you much more flexibility in handling unsuccessful responses. Try something like this:

def connection = new URL('https://your.url/goes.here').openConnection()
def content = { ->
    try {
        connection.content as String
    } catch (e) {
        connection.responseMessage
    }
}()

if (content) {
    def responseXml = new XmlSlurper().parseText(content)
    doStuffWithResponseXml(responseXml)
}

Even better would be to use an actual full-featured HTTP client, like the Spring Framework's HttpClient or RestTemplate classes.

BalRog
  • 3,216
  • 23
  • 30
  • Not working with this, says parseText() does not take closure as argument because content variable returns a closure. I have also tried with http methods but still getting the same when i try to parse the response. Any other way out of this pls suggest? – Ashtesh Divakar May 04 '22 at 09:08
  • Do you have the `()` at the end of the closure definition? That should invoke the closure and return the content string. – BalRog May 05 '22 at 04:01
  • Did you see my response? I hope it works for you. Please let me know if it does not. – BalRog May 05 '22 at 19:26
  • 1
    the above answer partially helped me and later I have found a solution working for me on https://stackoverflow.com/questions/25011927/how-to-get-response-body-using-httpurlconnection-when-code-other-than-2xx-is-re . And the reason for parse failing was method getInputStream() instead use getErrorStream() when status is other than 2XX – Ashtesh Divakar May 06 '22 at 07:39
  • @AshteshDivakar Could you post sample code of your ultimate solution (in the question text or as an alternate answer; and yes, answering your own question is allowed)? It might help other people down the line, and I can guarantee at least one upvote. – BalRog May 06 '22 at 14:27