2

I am creating an HttpsUrlConnection from a URL class. I am adding some header fields in the connection using the setRequestPropety method as demonstrated in following code.

URL url = new URL(address);
HttpURLsConnection connection = (HttpsURLConnection) url.openConnection();
connection.disconnect();
connection.setRequestProperty("Accept", "application/json");

I am getting exception, java.lang.IllegalStateException: Cannot set request property after connection is made upon execution of setRequestMethod. I even tried disconnection the connection as indicated in code above.

Thank you in advance.

NOTE: I also tried replacing setRequestProperty with addRequestProperty but no difference in exception.

NOTE: The stack trace is as below

10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime: Process: com.MYCOM.po, PID: 29470
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime: java.lang.RuntimeException: An error occured while executing doInBackground()
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at android.os.AsyncTask$3.done(AsyncTask.java:300)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at java.lang.Thread.run(Thread.java:818)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:  Caused by: java.lang.IllegalStateException: Cannot set request property after connection is made
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.setRequestProperty(HttpURLConnectionImpl.java:496)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.setRequestProperty(DelegatingHttpsURLConnection.java:258)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.android.okhttp.internal.http.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:25)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.MYCOM.po.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:386)
10-27 13:53:40.352 29470-30420/com.MYCOM.po E/AndroidRuntime:     at com.MYCOM.po.LoginActivity$UserLoginTask.doInBackground(LoginActivity.java:364)

NOTE: I am using the LoginActivity template, provided by Studio; to connect application to a RESTful web service.

The doInBackground method is as below

    @Override
    protected Boolean doInBackground(Void... params) {

        try {

            URL url = new URL(address);// Stored as a field in AsyncTask

            HttpURLConnection connection;
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("REST-API-Key", "HEXKEY");
            connection.setRequestProperty("Accept", "application/json");
            StringBuilder paramBuilder = new StringBuilder();
            paramBuilder.append("PARAM1=");
            paramBuilder.append("VALUE1");
            paramBuilder.append("&");
            paramBuilder.append("PARAM2=VALUE2");
            paramBuilder.append("&");
            paramBuilder.append("PARAM3=");
            paramBuilder.append("VALUE3");
            connection.setDoOutput(true);
            OutputStreamWriter outputWriter = new OutputStreamWriter(connection.getOutputStream());
            outputWriter.write(paramBuilder.toString());
            outputWriter.flush();
            if(connection == null) {
                Thread.sleep(2000);
                return false;
            }
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            if(responseReader == null){
                throw new IOException("Null Response");
            }
            StringBuilder sb = new StringBuilder();
            String line;
            while((line = responseReader.readLine())!=null){
                sb.append(line+"\n");
            }
            String resp = sb.toString();
            connection.disconnect();


        } catch (InterruptedException|IOException e) {
            return false;
        }


        // TODO: register the new account here.
        return true;
    }
Simon.Hermit
  • 89
  • 2
  • 7
  • Have you tried the request with RestAPI tools like Postman or RestClient? You should see [this](http://stackoverflow.com/a/2793153/3532826) for complete information about URLConnection – JavaGhost Oct 27 '15 at 20:07
  • @JavaGhost the api works fine, I tested it on cURL. Problem is in the HttpURLConnection. – Simon.Hermit Oct 27 '15 at 20:18
  • Move `connection.setDoOutput(true);` next to `connection = (HttpURLConnection) url.openConnection();` – JavaGhost Oct 30 '15 at 18:55
  • @JavaGhost that will throw NullPointerException. – Simon.Hermit Nov 05 '15 at 14:11
  • extremely sorry, I dint notice the package of Exception classes before. It seems that you have [OkHttp](http://square.github.io/okhttp/) library in your project. With OkHttp, you cannot use `HttpURLConnetion`. You will have to follow the builder pattern specified in as in the example section of the link above. OkHttp implementation does not allow setting request headers after the connection is opened (with builder pattern, you set all necessary fields and parameters before actually using the object for its specific need) Hope it helps. – JavaGhost Nov 05 '15 at 17:53

3 Answers3

1

Strange, But I removed all the break points, except the last one to check the result and It worked. I guess the delays,caused by breakpoints; was the problem. I still don't get it why it is getting connected even if connection.connect() was not getting executed. The solution was not to interrupt network operations.

Simon.Hermit
  • 89
  • 2
  • 7
-1

Please remove the connection.disconnect() from your code.

The typical usage pattern is:

HttpUrlConnection ucon = (HttpUrlConnection) url.openConnection();
ucon.setRequestProperty("name", "value");
...
InputStream is = null; 
try {
  is = ucon.getInputStream();
  // read inputstream. ideally wrapping it in a BufferedReader.
} finally {
  if (is != null) is.close();
}
Nagesh Susarla
  • 1,505
  • 9
  • 10
  • I tried both with and without disconnect. The problem is HttpUrlConnection is not allowing me to set headers after the initial connection is made, that's the reason I tried disconnect() to check if it would allow me to set it. – Simon.Hermit Oct 27 '15 at 17:35
  • Also which library or android version are you using? Are you embedding it in your app or using the default version – Nagesh Susarla Oct 27 '15 at 17:45
  • can you also post the stack trace? – Nagesh Susarla Oct 27 '15 at 17:46
  • I am using the java.net inside AsyncTask. – Simon.Hermit Oct 27 '15 at 17:50
  • Is it at all possible that you are calling any of the method that end up calling connect before calling setRequestProperty? such as getContentLength(), getInputStream(), getResponseCode(). Or is the same instance ever reused for making a new connect? – Nagesh Susarla Oct 27 '15 at 18:23
  • No. The address is only defined in AsyncTask and not anywhere else, so there is no chance of getting it executed outside it. – Simon.Hermit Oct 27 '15 at 18:43
  • can you paste the full code that's in AsyncTask.doInBackground() – Nagesh Susarla Oct 27 '15 at 19:07
-1

You should at lease set header before disconnect the connection.

URL url = new URL(address);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Accept", "application/json");

try {
     InputStream in = new BufferedInputStream(connection.getInputStream());
     readStream(in);
finally {
     connection.disconnect();
}
Zephyr
  • 5,408
  • 31
  • 32