Search code examples
javaioexceptionhttp-status-code-400

HttpURLConnection : Unable to retrieve the correct error message


I am calling REST service using java HttpURLConnection object.

When the HTTP server returns any business error, I am not able to retrieve the error properly.

For example, when I call the REST service through SoapUI, I get below error

<exception>
    <errors>
    <error>
    <diagnostic>Matching item with shortCode = 1089992001234 found</diagnostic>
    <field>shortCode</field>
    <message>The Shortcode/CSG combination must be unique.</message>
    <objectFailingValidationClass>com.axiossystems.assyst.dto.organisationConfiguration.SectionDto</objectFailingValidationClass>
    <rule>isUniqueShortCodeWithCSG</rule>
    </error>
    </errors>
    <message>A complex validation error has been detected by the application.</message>
    <type>ComplexValidationException</type>
    </exception>

But in the java code I getting below error, the request message format is correct

java.io.IOException: Server returned HTTP response code: 400 for URL: https://it-test.ihc.eu/assystREST/v2/sections
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
        at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1676)
        at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1674)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1672)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1245)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
        at RestCaller.execute(RestCaller.java:59)
        at RestCaller.main(RestCaller.java:18)

Can anyone let me know how to capture business error returned form server? Like the one received in SoapUI

Below is my code

try
    {
    url = new URL(targetURL);
    connection = (HttpURLConnection) url.openConnection();

    connection.setRequestProperty("accept", "application/xml");
    String userpassword = username + ":" + password;
    String authStringEnc = new String(Base64.encodeBase64(userpassword.getBytes()));

    connection.setRequestProperty("Authorization", "Basic "+authStringEnc);
    if (HttpMethod == "POST") 
    {
    connection.setRequestMethod("POST");
    //connection.setRequestProperty("Content-Length","" + Integer.toString(urlParameters.getBytes().length));
    connection.setRequestProperty("Content-Type", "application/xml");
    connection.setRequestProperty("Content-Language", "en-US");
    connection.setUseCaches(false);
    connection.setDoInput(true);
    connection.setDoOutput(true);
    OutputStream os = connection.getOutputStream();
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
    writer.write(payLoad);
    writer.flush();
    writer.close();
    os.close();
    }
    int statusCode = connection.getResponseCode();


    System.out.println("--------000----------" + statusCode);           

    InputStream is = connection.getInputStream();
    System.out.println("--------111----------");            
    BufferedReader rd = new BufferedReader(new InputStreamReader(is));
    System.out.println("--------222----------");            
    String line;
    System.out.println("--------333----------");            
    StringBuffer response = new StringBuffer();
    System.out.println("--------444----------");            

    while ((line = rd.readLine()) != null) 
    {
    response.append(line);
    response.append('\r');
    }

    rd.close();
    return response.toString();
    }
    catch (Exception e) 
    {
    System.out.println("--------exception----------");          
    e.printStackTrace();
    return "";
    }

Solution

  • In case of error (i.e., httpStatusCode other than 200), you might have to read errorStream of HttpUrlConnection as below. After you read errorMessage, you could to deserialize it to the DTO that matches the xml output you pasted. Please note readErrorString() below is incomplete and expect you to use it for reference only

    if (statusCode != 200) {
      InputStream errorStream = connection.getErrorStream();
      String errorMessage = (errorStream != null) ? readErrorString(errorStream) : connection
                    .getResponseMessage();
    }
    private void readErrorString(InputStream is) {
      String responseString = null;
      BufferedInputStream bis = null;
      try {
        StringBuilder sb = new StringBuilder();
        bis = new BufferedInputStream(inputStream);
        byte[] byteContents = new byte[4096];
        int bytesRead;
        String strContents;
        while ((bytesRead = bis.read(byteContents)) != -1) {
            strContents = new String(byteContents, 0, bytesRead, "UTF-8"); // You might need to replace the charSet as per the responseEncoding returned by httpurlconnection above
                sb.append(strContents);
        }
        responseString = sb.toString();
    } finally {
        if (bis != null) {
            bis.close();
            }
        }
    }
    

    return responseString;