1

I've read lots and tried lots relating to HTTP POSTS using HttpURLConnection and almost everything I come across has a similar structure which starts with these 3 lines:

  url = new URL(targetURL);
  connection = (HttpURLConnection)url.openConnection();
  connection.setRequestMethod("POST");

When I try this I always get a "Connection Already Established" exception when calling setRequestMethod, which makes perfect sense as I'm clearly calling openConnection before setting the request type. Although reading the docs openConnection doesn't actually open the connection in theory.

There are several posts about this problem on SO such as this and this. I don't understand however why every piece of advice about how to write this code has these 3 lines in this order.

I'm guessing this code must work in most instances as someone must have tested it, so why doesn't this code work for me? How should I be writing this code?

I am aware these are other libraries I can use out there, I'm just wondering why this doesn't work.

8
  • @scrappedcola I've read that. The question is why doesn't this code work for me, and how should I be writing this code? How do I create the connection without a call to openConnection? And if this is wrong, why is it what everyone advises? Commented Nov 14, 2014 at 23:24
  • @scrappedcola I've read the docs. How do I create the connection without a call to openConnection? Commented Nov 14, 2014 at 23:43
  • @scrappedcola One more point is that the docs state: "It should be noted that a URLConnection instance does not establish the actual network connection on creation. This will happen only when calling URLConnection.connect()." So openConnection does not actually connect. Commented Nov 15, 2014 at 7:18
  • There's no other order in which these three lines can possibly appear. That's why they always appear in this order. There's no reason why the request method can't be set after the connection is established, as long as the request hasn't been sent yet. I have all kinds of working code that does this. Is this your real code? Commented Nov 15, 2014 at 8:44
  • 1
    @scrappedcola The 'first post', or rather the accepted answer to it, is nonsense. You can't possibly call HttpURLConnection.setRequestMethod() before you have an HttpURLConnection. Commented Nov 16, 2014 at 9:06

2 Answers 2

3

Why the suspect code in the question has been duplicated all over the internet is something I can't answer. Nor can I answer why it seems to work for some people and not others. I can however answer the other question now, mainly thanks to this link that Luiggi pointed me to.

The key here is understanding the intricacies of the HttpURLConnection class. When first created the class defaults to a "GET" request method, so nothing needs to be changed in this instance. The following is rather unintuitive, but to set the request method to "POST" you should not call setRequestMethod("POST"), but rather setDoOutput(true) which implicitly sets the request method to post. Once you've done that you're good to go.

Below, I believe, is what a post method should look like. This is for posting json, but can obviously be altered for any other content type.

public static String doPostSync(final String urlToRead, final String content) throws IOException {
    final String charset = "UTF-8";
    // Create the connection
    HttpURLConnection connection = (HttpURLConnection) new URL(urlToRead).openConnection();
    // setDoOutput(true) implicitly set's the request type to POST
    connection.setDoOutput(true);
    connection.setRequestProperty("Accept-Charset", charset);
    connection.setRequestProperty("Content-type", "application/json");

    // Write to the connection
    OutputStream output = connection.getOutputStream();
    output.write(content.getBytes(charset));
    output.close();

    // Check the error stream first, if this is null then there have been no issues with the request
    InputStream inputStream = connection.getErrorStream();
    if (inputStream == null)
        inputStream = connection.getInputStream();

    // Read everything from our stream
    BufferedReader responseReader = new BufferedReader(new InputStreamReader(inputStream, charset));

    String inputLine;
    StringBuffer response = new StringBuffer();

    while ((inputLine = responseReader.readLine()) != null) {
        response.append(inputLine);
    }
    responseReader.close();

    return response.toString();
}
Sign up to request clarification or add additional context in comments.

1 Comment

@EJP There's nothing incorrect about this as far as I'm aware. It the question that contains the incorrect code.
0

As per https://stackoverflow.com/a/3324964/436524, you need to call connection.setDoOutput(true) for it to expect a POST request.

This makes your code like this:

  url = new URL(targetURL);
  connection = (HttpURLConnection)url.openConnection();
  connection.setDoOutput(true);

3 Comments

I still get the same exception calling setDoOutput(true) first.
@LuiggiMendoza Thanks for the interesting link. That states that calling setDoOutput(true) implicitly sets the request type to POST so there's no need to call setRequestMethod. I don't understand how the same incorrect code can be duplicated in so many places.
setDoOutput(true) implies setRequestMethod("POST"). There's no need to call them both.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.