I've seen many different examples of using HttpURLConnection + InputStream, and closing them (or not closing them) after use. This is what I came up with to make sure everything is closed after finished, whether there's an error or not. Is this valid?:
HttpURLConnection conn = null;
InputStream is = null;
try {
URL url = new URL("http://example.com");
// (set connection and read timeouts on the connection)
conn = (HttpURLConnection)url.openConnection();
is = new BufferedInputStream(conn.getInputStream());
doSomethingWithInputStream(is);
} catch (Exception ex) {
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (conn != null) {
conn.disconnect();
}
}
Thanks
Yep.. Doing the end part in finally would be best idea because if code fails somewhere, program won't reach till .close(), .disconnect() statements that we keep before catch statements...
If the code fails somewhere and exception is thrown in between of the program, still finally get executed regardless of exception thrown...
There is also the new (with Java 7) 'try()' technique
try (OutputStream os = http.getOutputStream()) {
os.write(out);
}
Basically, it will auto-close anything in the try() statement, regardless of whether it is successful or not.
Related
I have defined Output stream like below
OutputStream os=new FileOutputStream(file);
Tried to close the resource like below
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}}
Still sonarlint showing "Use try-with-resources or close this "FileOutputStream" in a "finally" clause."
If you are doing the operations in the same method it's important to put the close in a finally statement of a try that envolves the open part of the stream. This ensures that in case of failure (Exception) the stream is allways closed if required
Bad sonar code:
OutputStream os=new FileOutputStream(file);
... // your code operations with os
// If something is going really bad here and ends in exception the
// stream will never be closed
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Better code:
OutputStream os = null;
try{
os = new FileOutputStream(file);
... // your code operations with os
} finally{
// The stream is allways closed at the end of the method execution
if(os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The best code (in case of Java 1.7 or upper)
try (OutputStream os = new FileOutputStream(file)){
... // your code operations with os
// The stream is allways closed at the end of the try block
}
Try this instead. You do not do a close when using try with resources, that is automatically handled... i.e.
"The try-with-resources statement ensures that each resource is closed
at the end of the statement."
try( OutputStream os=new FileOutputStream(file) ) {
....
}
Any resources declared within the brackets are closed automatically once the program flow has completed whether an exception is thrown or not..
Examples here : https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
I'm trying to connect a java application to an external api for GuildWars2.
The link I am trying to test is:
http://api.guildwars2.com/v2/commerce/listings
A list of int IDs are returned when navigating to that page within a browser.
As a learning practice, I am trying to get that list of id's when running my java application.
I use the following code (hopefully it formats correct, currently on my phone, trying to program remotely to my desktop):
public class GuildWarsAPI
{
public static void main(String[] args)
{
GuildWarsAPI api = new GuildWarsAPI();
api.getAPIResponse("http://api.guildwars2.com/v2/commerce/listings");
}
public void getAPIResponse(String URLString)
{
URL url = null;
try {
url = new URL(URLString);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) url.openConnection();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (connection != null)
{
System.out.println("connection success");
connection.setRequestProperty("Accept", "application/json");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setReadTimeout(10000);
connection.setConnectTimeout(10000);
try {
/*BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder input = new StringBuilder();
String nextLine = null;
while ((nextLine = in.readLine()) != null)
{
System.out.println("adding output");
input.append(nextLine);
}*/
InputStream in = new BufferedInputStream(connection.getInputStream());
int b = 0;
while ((b = in.read()) != -1)
{
System.out.println("byte:" + b);
}
System.out.println("done");
}
catch (Exception e) {
e.printStackTrace();
}
finally {
connection.disconnect();
System.out.println("closed");
}
}
}
}
Upon running my class, it immediately prints out connection success, done, closed. It definitely isnt waiting for the timeouts, and i've been trying to play with that, the request header, and the DoInput/DoOutput. I stepped through it, and it appears as if it connects, and just doesnt receive any bytes of information back. (doesnt go into the while loop)
So, while my ultimate question is: How do I get the id's back like I expect?, my other question is: how can I figure out how to get the other id's back like I expect?
Your code is getting response code 302 Found. It should follow the Location: header to the new location, as followRedirects is true by default, but it isn't. The server is however returning a Location: header of https://api.guildwars2.com/v2/commerce/listings. I don't know why HttpURLConnection isn't following that, but the simple fix is to use https: in the original URL.
You're setting doOutput(true) but you aren't sending any output.
Your code is poorly structured. Code that depends on the success of code in a prior try block should be inside that same try block. I would have the method throw MalformedURLException and IOException and not have any internal try/catch blocks at all.
In my experience, wrestling with HttpUrlConnection is more trouble than it's worth.
It's hard to debug, hard to use, and provides very little support for complex http operations.
There are a bunch of better options.
My default choice is Apache HttpConponents Client (http://hc.apache.org/). It's not necessarily any better than all the other options, but it's quite well documented and widely used.
I'm new to BlackBerry application development. I have one silly error while during HttpConnection in httpcon.getResponseCode() method giving source not found error.
Please, can any one figure out this error?
Here is my method:
net.rim.device.api.io.transport.ConnectionFactory cf = new net.rim.device.api.io.transport.ConnectionFactory();
httpConn = (HttpConnection) cf.getConnection(url).getConnection();
httpConn.setRequestMethod(HttpConnection.POST);
httpConn.setRequestProperty("User-Agent",
"Profile/MIDP-2.0 Confirguration/CLDC-1.0");
httpConn.setRequestProperty("Accept_Language", "en-US");
httpConn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
httpConn.setRequestProperty("Content-Length",
Integer.toString(postData.length));
os = httpConn.openOutputStream();
os.write(("LoginID=yahoo#sol.com&Password=yah123")
.getBytes("UTF-8"));
os.flush();
os.close();
try {
responseCode = httpConn.getResponseCode();
} catch (IOException ex1) {
//check if it's eof, if yes retrieve code again
if (-1 != ex1.getMessage().indexOf("EOF")) {
try {
responseCode = httpConn.getResponseCode();
} catch (IOException ex2) {
System.out.println(ex2.getMessage());
// handle exception
}
} else {
System.out.println(ex1.getMessage());
// handle exception
}
}
int status = httpConn.getResponseCode();
if (status == HttpConnection.HTTP_OK) {
InputStream input = httpConn.openInputStream();
byte[] bytes = IOUtilities.streamToBytes(input);
StringBuffer raw = new StringBuffer(new String(bytes));
raw.insert(0, "bytes received]\n");
raw.insert(0, bytes.length);
raw.insert(0, '[');
url = raw.toString();
input.close();
} else {
url = "response code = " + status;
}
httpConn.close();
} catch (IOCancelledException e) {
System.out.println(e.toString());
return "";
} catch (IOException e) {
return "";
}
return "";
}
Update: I am not trying to step into getResponseCode(). Eclipse is stopping execution at that point, and showing the Source Not Found error.
#Nate yes we are step into method that time only we are getting Run Time Error.Error is displayed When Getresponsecode() is called
Does your eclipse error look like this?
getResponseCode() is a method in the HttpConnection class. This is RIM's code, not yours. You normally shouldn't need to step into that code. Just step over that line while debugging. The only thing you should want to see is the result of that method, not what happens inside.
Even if net_rim_api.jar is included in your project, that simply gives you the binary version of RIM's classes, including HttpConnection. It doesn't provide the Java source code for that class. In order to step into a method, you would need to have the source code, too.
I have found my mistake.When calling HttpConnection. getResponseCode() in that URL String we have to add deviceside=true then only getresponsecode() will be called without throwing any http exceptions.
For Example:
httpClient ht = new httpClient();
String str = ht.getHttpClientResponse("https://www.google.co.in;deviceside=true",post);
Note:
(From #Nate Comment)
we don't always want deviceside=true in your connection strings. It depends on whether you're running on a device or a simulator, and what kind of network's available.
I'm writing a program that connects to a servlet thanks to a HttpURLConnection but I stuck while checking the url
public void connect (String method) throws Exception {
server = (HttpURLConnection) url.openConnection ();
server.setDoInput (true);
server.setDoOutput (true);
server.setUseCaches (false);
server.setRequestMethod (method);
server.setRequestProperty ("Content-Type", "application / xml");
server.connect ();
/*if (server.getResponseCode () == 200)
{
System.out.println ("Connection OK at the url:" + url);
System.out.println ("------------------------------------------- ------- ");
}
else
System.out.println ("Connection failed");
}*/
I got the error :
java.net.ProtocolException: Cannot write output after reading input.
if i check the url with the code in comments but it work perfectly without it
unfortunately, I need to check the url so i think the problem comes from the getResponseCode method but i don t know how to resolve it
Thank you very much
The HTTP protocol is based on a request-response pattern: you send your request first and the server responds. Once the server responded, you can't send any more content, it wouldn't make sense. (How could the server give you a response code before it knows what is it you're trying to send?)
So when you call server.getResponseCode(), you effectively tell the server that your request has finished and it can process it. If you want to send more data, you have to start a new request.
Looking at your code you want to check whether the connection itself was successful, but there's no need for that: if the connection isn't successful, an Exception is thrown by server.connect(). But the outcome of a connection attempt isn't the same as the HTTP response code, which always comes after the server processed all your input.
I think the exception is not due toprinting url. There should some piece of code which is trying to write to set the request body after the response is read.
This exception will occur if you are trying to get HttpURLConnection.getOutputStream() after obtaining HttpURLConnection.getInputStream()
Here is the implentation of sun.net.www.protocol.http.HttpURLConnection.getOutputStream:
public synchronized OutputStream getOutputStream() throws IOException {
try {
if (!doOutput) {
throw new ProtocolException("cannot write to a URLConnection"
+ " if doOutput=false - call setDoOutput(true)");
}
if (method.equals("GET")) {
method = "POST"; // Backward compatibility
}
if (!"POST".equals(method) && !"PUT".equals(method) &&
"http".equals(url.getProtocol())) {
throw new ProtocolException("HTTP method " + method +
" doesn't support output");
}
// if there's already an input stream open, throw an exception
if (inputStream != null) {
throw new ProtocolException("Cannot write output after reading
input.");
}
if (!checkReuseConnection())
connect();
/* REMIND: This exists to fix the HttpsURLConnection subclass.
* Hotjava needs to run on JDK.FCS. Do proper fix in subclass
* for . and remove this.
*/
if (streaming() && strOutputStream == null) {
writeRequests();
}
ps = (PrintStream)http.getOutputStream();
if (streaming()) {
if (strOutputStream == null) {
if (fixedContentLength != -) {
strOutputStream =
new StreamingOutputStream (ps, fixedContentLength);
} else if (chunkLength != -) {
strOutputStream = new StreamingOutputStream(
new ChunkedOutputStream (ps, chunkLength), -);
}
}
return strOutputStream;
} else {
if (poster == null) {
poster = new PosterOutputStream();
}
return poster;
}
} catch (RuntimeException e) {
disconnectInternal();
throw e;
} catch (IOException e) {
disconnectInternal();
throw e;
}
}
I have this problem too, what surprises me is that the error is caused by my added code System.out.println(conn.getHeaderFields());
Below is my code:
HttpURLConnection conn=(HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
configureConnection(conn);
//System.out.println(conn.getHeaderFields()); //if i comment this code,everything is ok, if not the 'Cannot write output after reading input' error happens
conn.connect();
OutputStream os = conn.getOutputStream();
os.write(paramsContent.getBytes());
os.flush();
os.close();
I had the same problem.
The solution for the problem is that you need to use the sequence
openConnection -> getOutputStream -> write -> getInputStream -> read
That means..:
public String sendReceive(String url, String toSend) {
URL url = new URL(url);
URLConnection conn = url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.sets...
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(toSend);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String receive = "";
do {
String line = in.readLine();
if (line == null)
break;
receive += line;
} while (true);
in.close();
return receive;
}
String results1 = sendReceive("site.com/update.php", params1);
String results2 = sendReceive("site.com/update.php", params2);
...
It seems to me that there is some kind of limitation in socket creation in MIDP.
I need to make lots of connections to a server (none concourrent) and in the forth or fith try my app crashes. It crashes in the simulator and in my real device as well.
To isolate any possibility of it being influenced by my code, I isolated the following code:
try {
StreamConnection c;
StringBuffer sb = new StringBuffer();
c = (StreamConnection) Connector.open(
"http://www.cnn.com.br/", Connector.READ_WRITE);
InputStreamReader r = new InputStreamReader(c.openInputStream(), "UTF-8");
System.out.println(r.read());
c.close();
} catch (IOException ex) {
ex.printStackTrace();
}
This code crashes in the 13th try.
I've tryed to add a sleep of 10 seconds inside a while loop and, it crashes at the 13th try too.
The crash message is:
java.io.IOException: Resource limit exceeded for TCP client sockets
- com.sun.midp.io.j2me.socket.Protocol.open0(), bci=0
- com.sun.midp.io.j2me.socket.Protocol.connect(), bci=124
- com.sun.midp.io.j2me.socket.Protocol.open(), bci=125
While c.close() inside the try should be adequate, I am wondering if you have other issues that are triggering this. The code really should be closing the connection AND inputstream inside of a finally. Something like this:
StreamConnection c = null;
InputStream is = null;
try {
StringBuffer sb = new StringBuffer();
c = (StreamConnection) Connector.open(
"http://www.cnn.com.br/", Connector.READ_WRITE);
is = c.openInputStream();
InputStreamReader r = new InputStreamReader(is, "UTF-8");
System.out.println(r.read());
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (Exception ex) {
System.out.println("Failed to close is!");
}
}
if (c != null) {
try {
c.close();
} catch (Exception ex) {
System.out.println("Failed to close conn!");
}
}
}
The reason, why the c.close() did not actually close was because the inputstream was not closed. Some devices require that both the stream and the connection be closed. Also the connections do not close immediately, on some devices, when the close() method is called. You might have to do a gc too