Blocking operations in URLConnection - java

Running the following code snippet:
URL url = new URL(uri);
URLConnection urlconn = url.openConnection();
urlconn.connect();
urlconn.getContentLength();
I get the dead-lock sometimes, usually at two lines: urlconn.connect() and urlconn.getContentLength(). Also, when I do
InputStream is = urlconn.getInputStream();
// doing some reading
is.close();
I also get blocking at is.close(). I want to ask why such blocking happens. It is clueless to me from the Java API.

Related

POST request is not sent

I have a short Android-Java client program which sends a basic information to bottle-python server with POST method. In the first version of code, server does not show anything. However, In the second version it works but I cannot understand what this additional line do because it has anything to do with posting content. I really appreciate if someone helps me figure this out.(There is nothing wrong with the server code since I can properly send request with python requests and my browsers).
This is the first version of client code:
String url = "http://192.168.1.23:8080/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
PrintStream myPusher = new PrintStream(os );
myPusher.print("param1=hey");
Second version:
String url = "http://192.168.1.23:8080/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
PrintStream myPusher = new PrintStream(os );
myPusher.print("param1=hey");
InputStream in= con.getInputStream(); //Nothing changed but only this additional line
Bottle(python) server:
#app.route('/', method="POST")
def hello():
print("it works")
name = request.forms.get("param1")
print(name)
return name
#app.route('/')
def hello():
i=0
print("it works")
run(app, host="192.168.1.23", port=8080)
With first client code server shows nothing.
With second code server shows:
it works
hey
192.168.1.24 - - [31/Dec/2018 17:10:28] "POST / HTTP/1.1" 200 3
Which is as I expected.
With your first code snippet the output stream is still open. So the server does not know if it got the complete request. Probably just closing the stream would work as well.
However, I would make at least a call to getResponseCode to see the outcome of the request.
Your java code seems incomplete for sending a post request.
I think by using this code, you can make it work for yourself.
The PrintStream is a buffered type, this means you should add a flush operation after each print(), or use println() instead.

HttpURLConnection connect() , getInputStream() , getContent() , HttpGet

I use the class HttpURLConnection , but Iam confused with some methods
assume the HttpURLConnection object name is "c"
removing c.connect() will result in a success connection and it will retrieve the connection result without any problem
the output of c.getInputStream() and (InputStream) c.grtContent() are identical , so what is the difference betqween them
using HttpGet will reach the same approach as HttpURLConnection , so what is the difference between the two methods
what are the extra benefits for HttpURLConnection on URLConnection
c = (HttpURLConnection) (URL).openConnection();
c.connect(); //adding or removing makes the same result , so what is the usage of this method
InputStream stream= c.getInputStream();
InputStream stream2 = (InputStream) c.getContent();
//stream and stream2 are identical , so what is the differece between getInputStream() and getContent()
//============================
HttpGet c= new HttpGet(url);
HttpResponse response = c.execute(httpGet)
InputStream stream3 = response.getEntity().getContent();
//also stream3 is the same as stream & stream2 ; so how dose it different between HttpGet & HttpURLConnection
From Android documentation:
[HttpURLConnection is] A URLConnection with support for HTTP-specific features.
For instance, from an HttpURLConnection you can retrieve the HTTP method or the HTTP status code, which are HTTP-specific.
The URLConnection class, instead, is:
The abstract class URLConnection is the superclass of all classes that represent a communications link between the application and a URL
The normal usage is:
Create a URL object
Get a URLConnection by calling url.openConnection(). The returned object can be casted to an HttpURLConnection
get an InputStream by calling the connection.getInputStream() method
Close the connection (disconnect() method) (see #EJP comments)
Concerning the connect() method, from the Oracle documentation:
You are not always required to explicitly call the connect method to initiate the connection. Operations that depend on being connected, like getInputStream, getOutputStream, etc, will implicitly perform the connection, if necessary.
The difference between the HttpGet and HttpURLConnection is that they belong to 2 different libraries, but functionally they are more or less the same (now HttpGet has been deprecated and removed, so you won't find it in the standard Android APIs)

Using HttpURLConnection to POST in Java

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.
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();
}
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);

How do I add cookies in a post request in Java?

I was trying to get a certain page through java, but with this page I didn't succeed.
Now in my browser it does work, but when I disable Cookies in the settings, it doesn't anymore.
So I probably need to add cookies to my post request in java.
So I went searching the interwebs, but unfortunately I couldn't really find anything useful. mostly it was vague, scattered or irrelevant.
So now my question :
Could anyone show me how to do it (mentioned above^^), or point me to a clear site?
Here's a simple example of setting a cookie in a POST request with URLConnection:
URL url = new URL("http://example.com/");
String postData = "foo bar baz";
URLConnection con = url.openConnection();
con.setDoOutput(true);
con.setRequestProperty("Cookie", "name=value");
con.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
con.connect();
OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
out.write(postData);
out.close();
You probably need to pass a cookie from a previous request, see this answer for an example. Also consider using Apache HttpClient to make things easier.
URL url = new URL("http://hostname:80");
URLConnection conn = url.openConnection();
conn.setRequestProperty("Cookie", "name1=value1; name2=value2");
conn.connect();

Sometimes HttpURLConnection.getInputStream executes too slowly

We have next code.
Sometimes we should wait 10-20-40 seconds on the last line.
What can be the problem?
Java 1.4
URL url = ...;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.connect();
OutputStream out = conn.getOutputStream();
ObjectOutputStream outStream = new ObjectOutputStream(out);
try
{
outStream.writeObject(objArray);
}
finally
{
outStream.close();
}
InputStream input = conn.getInputStream();
UPDATED:
Next code fixes the problem IN ECLIPSE.
But it still DOES NOT WORK via Java WebStart:(
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
System.setProperty("http.keepAlive", "false"); //<---------------
conn.connect();
But why?
UPDATED one more time!
Bug was fixed! :)
We worked with connections not in one class but in two.
And there is following line in the second class:
URL url = ...
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Content-Length", "1000"); //<------------
conn.connect();
Note:
setRequestProperty("Content-Length", "1000") is root cause of the problem.
'We had a similar issue which is caused by buggy keep-alive in old Java. Add this before connect to see if it helps,
conn.setRequestProperty("Connection", "close");
or
System.setProperty("http.keepAlive", "false");
Had the same problem, found out it was caused by IPv6.
You Disable it from code using:
System.setProperty("java.net.preferIPv4Stack" , "true");
You can also disable it via the command line using : g-Djava.net.preferIPv4Stack=true
Try it with an IP address. To see if it's a DNS problem.
I had same problem, so i change to HTTPClient from Apache, follow a example:
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost request = new HttpPost("www.myurl-to-read");
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(8000)
.setConnectTimeout(10000)
.setConnectionRequestTimeout(1000)
.build();
request.setConfig(requestConfig);
request.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, "UTF-8");
The problem can be something from network sub layer... Should be hard to find it.
But what about the setReadTimeOut() with low value and a while loop?
One thing I would guess is that your DNS server isn't responding well.
Can you experiment with changing symbolic domain names to numeric IP addresses before you start? Or can you do each request twice (just for experimentation) and see if the first request is significantly slower than the second?
Google has put up a DNS server at (among others) 8.8.8.8 . They claim it's faster than most other DNS servers. Give that a try!

Categories

Resources