I use following code to read data form http request.
In general cases it works good, but some time "httpURLConnection.getResponseCode()" throws java.net.BindException: Address already in use: connect
............
URL url = new URL( strUrl );
httpURLConnection = (HttpURLConnection)url.openConnection();
int responseCode = httpURLConnection.getResponseCode();
char charData[] = new char[HTTP_READ_BLOCK_SIZE];
isrData = new InputStreamReader( httpURLConnection.getInputStream(), strCharset );
int iSize = isrData.read( charData, 0, HTTP_READ_BLOCK_SIZE );
while( iSize > 0 ){
sbData.append( charData, 0, iSize );
iSize = isrData.read( charData, 0, HTTP_READ_BLOCK_SIZE );
}
.................
finally{
try{
if( null != isrData ){
isrData.close();
isrData = null;
}
if( null != httpURLConnection ){
httpURLConnection.disconnect();
httpURLConnection = null;
}
strData = sbData.toString();
}
catch( Exception e2 ){
}
The code running on Java 1.6, Tomcat 6.
Thank you
Get rid of the disconnect() and close the Reader instead. You are running out of local ports, and using disconnect() disables HTTP connection pooling which is the solution to that.
You need to close() the Reader after completely reading the stream. This will free up underlying resources (sockets, etc) for future reuse. Otherwise the system will run out of resources.
The basic Java IO idiom for your case is the following:
Reader reader = null;
try {
reader = new InputStreamReader(connection.getInputStream(), charset);
// ...
} finally {
if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
}
See also:
Java IO tutorial
How to use URLConnection?
Related
I have a list of 100k users. I have to loop through the list and make an API call to the server to get the result. Every time I create a new URL connections and making the APi call then closing the connection once I read the input stream, but it is taking too much time.
Is there any optimized way to do it, like using the same instance of URL connection multiple times instead of closing it? or going for another third-party library will improve the speed of execution?
I am calling the below method in my loop to get the output.
private String getOutput(String loginName) {
String responseStatus = null;
HttpURLConnection connection = null;
try {
URL url= new URL(<<https://api.junk.123.com/output>>);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("apikey", "authentication key");
connection.setUseCaches(false);
connection.setDoOutput(true);
//Send request
try(DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())){
JsonObject jsonParam = new JsonObject();
jsonParam.putString("loginName", "loginName");
outputStream.writeBytes(jsonParam.toString());
outputStream.flush();
}
//Get response
InputStream inputStream;
if(connection.getResponseCode() == HttpURLConnection.HTTP_OK){
inputStream = connection.getInputStream();
} else {
inputStream = connection.getErrorStream();
}
if(null == inputStream){
return String.valueOf(connection.getResponseCode());
}
StringBuilder response = new StringBuilder();
try (BufferedReader inputBuffer = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while (null != (line = inputBuffer.readLine())) {
response.append(line);
response.append("\r");
}
}
JsonObject jsonObject = new JsonObject(response.toString());
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
responseStatus = "success";
} else {
responseStatus = String.valueOf(connection.getResponseCode()) + jsonObject.getString("errorMessage") ;
}
} catch (MalformedURLException e) {
logger.error("Malformed URL exception occurred while calling the API", entry.getKey(), e);
} catch (IOException e) {
logger.error("Creation of connection failed while calling the API", entry.getKey(), e);
} catch (Exception e) {
logger.error("Error occurred while calling the API", entry.getKey(), e);
} finally {
if (null != connection){
connection.disconnect();
}
}
return responseStatus;
}
This Q&A explains that HTTP persistent connections are implemented behind the scenes by HttpURLConnection:
Persistent HttpURLConnection in Java
However, that may not be sufficient. If you use a single client-side thread to do the fetching you are limited by the round trip time for the requests; i.e. you can't start a second request until the result of the first one has been returned to you. You can remedy this ... up to a point ... by using multiple client-side threads.
However (#2) sending multiple requests in parallel also has its limits. Beyond a certain point you will saturate the client, the server or the network. In addition, some servers have throttling mechanisms to cap the number of requests that a client can make.
The way to get maximum throughput would be to redesign the API so that a single request can get information for multiple users.
everyone. I'm coding a function that connects to a server by using Class HttpURLConnection. In the code, I establish a connection, call getOutputStream() and getInputStream() methods in order. Then I disconnect the connection. After this, I try to get data which has been obtained by getInputStream() method, but the compiler reminds NullPointerException.
Code in below:
DataOutputStream out = null;
InputStreamReader inStrReader = null;
BufferedReader reader = null;
HttpURLConnection connection = null;
try {
URL postUrl = new URL(null, url, new sun.net.www.protocol.https.Handler());
connection = (HttpURLConnection) postUrl.openConnection();
...//some setting methods
connection.connect();
out = new DataOutputStream(connection.getOutputStream());
out.writeBytes(JSONObject.toJSONString(param));
out.flush();
out.close();
inStrReader = new InputStreamReader(connection.getInputStream(), "utf-8");
reader = new BufferedReader(inStrReader);
connection.disconnect(); //<--HERE, release the connection
StringBuilder stringBuilder = new StringBuilder();
for (String line = reader.readLine(); line != null; line = reader.readLine()) { //<--null pointer
stringBuilder.append(line);
}
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inStrReader != null) {
try {
inStrReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
After debug attempts, When I move the disconnection line to the last line in finally module, everything will be ok. But I'm confused, which happens when I already assgined the 'inputstream' value to 'reader'.
Thanks a lot.
Assigning isn't equal to reading, reader.readLine() start read from connection.
InputStreamReader is using the connection to read bytes, you disconnect before it read the bytes using the connection
An InputStreamReader is a bridge from byte streams to character
streams: It reads bytes and ...
Remember it is an "stream". You need to have an active connection to read from stream. Close the connection only after you have retrieved your data from stream.
You're doing everything in the wrong order. It doesn't make sense.
You're disconnecting and then expecting to be able to read from the connection. Total nonsense here. Normally you shouldn't disconnect at all, as you interfere with HTTP connection pooling. Just remove it, or, if you must have it, do it after all the closes.
You're closing in the wrong order, but you don't need to close inStrReader at all. Closing the BufferedReader does that. Just remove all the code for inStrReader.close().
You're closing out twice. Don't do that.
connect() happens implicitly. You don't need to call it yourself.
new URL(url) is sufficient. You haven't needed to provide the HTTPS Handler since about 2003.
I'm trying to invoke a webservice call and get a response. When I tried it first time it worked perfectly and printed the response. But after that one run, how many ever times I run it, i throws me
Exception in thread "main" java.lang.IllegalStateException: Already connected
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(Unknown Source)
at SOAPClient4XG.main(SOAPClient4XG.java:72)
I have tried various solutions provided for similar problem (like connect / disconnect) but nothing seems to make it work. I understand that it tries to perform an operation on already existing connection, but not sure how to fix. I'm fairly new to all this and I need help.
Below is my code
import java.io.*;
import java.net.*;
public class SOAPClient4XG
{
private static HttpURLConnection httpConn;
public static void main(String[] args) throws Exception {
String SOAPUrl = args[0];
String xmlFile2Send = args[1];*/
String SOAPUrl = "http://10.153.219.88:8011/celg-svcs-soap/business/ApplicantEligibility";
String xmlFile2Send =
"C:\\Users\\dkrishnamoorthy\\workspace\\SOAPUI_Automation\\src\\ApplicantElligibilty.xml";
String SOAPAction = "";
if (args.length > 2)
SOAPAction = args[2];
// Create the connection where we're going to send the file.
URL url = new URL(SOAPUrl);
URLConnection connection = url.openConnection();
//URLConnection connection = new URLConnection(url);
httpConn = (HttpURLConnection) connection;
if(httpConn.getResponseCode()==500)
{
System.out.println("Error Stream for 500 : "+httpConn.getErrorStream());
}
// Open the input file. After we copy it to a byte array, we can see
// how big it is so that we can set the HTTP Cotent-Length
// property. (See complete e-mail below for more on this.)
FileInputStream fin = new FileInputStream(xmlFile2Send);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
// Copy the SOAP file to the open connection.
copy(fin,bout);
fin.close();
byte[] b = bout.toByteArray();
// Set the appropriate HTTP parameters.
httpConn.setRequestProperty( "Content-Length",
String.valueOf( b.length ) );
httpConn.setRequestProperty("Content-Type","text/xml; charset=utf-8");
httpConn.setRequestProperty("SOAPAction",SOAPAction);
httpConn.setRequestMethod( "POST" );
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
// httpConn.connect();
// Everything's set up; send the XML that was read in to b.
OutputStream out = httpConn.getOutputStream();
out.write( b );
out.close();
// Read the response and write it to standard out.
InputStreamReader isr =
new InputStreamReader(httpConn.getInputStream());
BufferedReader in = new BufferedReader(isr);
String inputLine;
System.out.println("Printing the Response ");
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
public static void copy(InputStream in, OutputStream out)
throws IOException {
synchronized (in) {
synchronized (out) {
byte[] buffer = new byte[256];
while (true) {
int bytesRead = in.read(buffer);
if (bytesRead == -1) break;
out.write(buffer, 0, bytesRead);
}
}
}
}
}
If you use eclipse version just restart it. I met the same issue and I sorted out by doing that .
I solved this because I had a forgotten watch for connection.getResponseCode() in my debugging interface in NetBeans. Hope it might help others making the same mistake.
If you have any watch relative to the response value of the request, such as getResponseCode(), getResponseMessage(), getInputStream() or even just connect(), you will get this error in debugging mode.
All of the previous methods implicitly call connect() and fire the request. So when you reach setDoOutput, the connection is already made.
Some times work throuw the proxy server and reading prom buffer content my program to think so more time... until i close them. How set program code that from some seconds if do not have any answer from server to take another server?
URL url = new URL(linkCar);
String your_proxy_host = new String(proxys.getValueAt(xProxy, 1).toString());
int your_proxy_port = Integer.parseInt(proxys.getValueAt(xProxy, 2).toString());
Proxy proxy = null;
// System.out.println(proxys.getValueAt(xProxy, 3).toString());
// if (proxys.getValueAt(xProxy, 3).toString().indexOf("HTTP") > 0)
// {
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(your_proxy_host, your_proxy_port));
// } else {
// proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(your_proxy_host, your_proxy_port));
// }
HttpURLConnection connection = (HttpURLConnection)url.openConnection(proxy);
connection.setConnectTimeout(1000);
connection.connect();
String line = null;
StringBuffer buffer_page = new StringBuffer();
BufferedReader buffer_input = new BufferedReader(new InputStreamReader(connection.getInputStream(),"cp1251"));
int cc = 0;
//this is thinking place!!!
while ((line = buffer_input.readLine()) != null && cc < 7000) {
buffer_page.append(line);
cc++;
}
doc = Jsoup.parse(String.valueOf(buffer_page));
connection.disconnect();
i tried to use counter but it not work... What exception i can use to catch this situation by my control?
You need to use URLConnection.setReadTimeout. From the specification,
Sets the read timeout to a specified timeout, in milliseconds. A non-zero value specifies the timeout when reading from Input stream when a connection is established to a resource. If the timeout expires before there is data available for read, a java.net.SocketTimeoutException is raised. A timeout of zero is interpreted as an infinite timeout.
As you can see, reads that time-out will throw SocketTimeoutException, which you can catch appropriately, e.g.
try (BufferedReader buffer_input = new BufferedReader(
new InputStreamReader(connection.getInputStream(), "cp1251"))) {
String line;
while ((line = buffer_input.readLine()) != null) {
buffer_page.append(line);
}
} catch (SocketTimeoutException ex) {
/* handle time-out */
}
Note that you need to be careful when using readLine as above -- this will strip all \r and \n from the input.
I am trying to connect to a webservice from my blackberry project in eclipse. My code for URLConnector is the following
import java.io.InputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;
import net.rim.device.api.ui.component.Dialog;
public class URLConnector
{
HttpConnection con = null;
InputStream is = null;
public URLConnector() {
try
{
Dialog.inform("1");
String url = new String("https://webserviceBlahBlah");
Dialog.inform(con.toString());
int responseCode = con.getResponseCode();
Dialog.inform("3");
if (responseCode != HttpConnection.HTTP_OK) {
Dialog.inform("3.5");
System.out.println(responseCode);
}
is = con.openInputStream();
byte[] responseData = new byte[10000];
int length = 0;
Dialog.inform("4");
StringBuffer rawResponse = new StringBuffer();
while (-1 != (length = is.read(responseData))) {
Dialog.inform("5");
rawResponse.append(new String(responseData, 0, length));
}
final String result = rawResponse.toString();
System.out.println(result);
Dialog.inform("6");
}
catch (Exception ex)
{
Dialog.inform("ex.getMessage()");
System.out.println(ex.getMessage());
}
finally
{
try {
is.close();
is = null;
con.close();
con = null;
Dialog.inform("8");
}
catch(Exception e){
Dialog.inform("e");
}
}
}
The application hangs on the con.getReponse() call. It is running on the blackberry 9800 simulator. Any help would be super appreciated because I am very stuck
getResponseCode() shouldn't be causing it to get stuck, as it simply reads the response that it got after making the connection. My guess is its actually the connection attempt that is hanging. If you're developing for 5.0 or higher, take a look at the ConnectionFactory class to make sure your connection is being created properly.
James, I'm assuming after you turned the MDS Simulator on, you discovered that you also had a problem because you never opened the connection?
Anyway just to give a final working solution:
HttpConnection con = null;
InputStream is = null;
try {
System.out.println("1");
String url = new String("http://myserver.com/index.html");
//I added these two lines to your code and tested it with my own server and got a 200 RC.
net.rim.device.api.io.transport.ConnectionFactory cf = new net.rim.device.api.io.transport.ConnectionFactory();
con = (HttpConnection)cf.getConnection(url).getConnection();
System.out.println(con.toString());
int responseCode = con.getResponseCode();
System.out.println("3 responseCode = " + responseCode);
if (responseCode != HttpConnection.HTTP_OK) {
System.out.println("3.5");
System.out.println(responseCode);
}
Also if you have to support BBJava 5.0 minus, you can have a look at : http://www.versatilemonkey.com/HttpConnectionFactory.java . It's not prefect but its a good place to start with creating connections for pre 5.0 platforms.
Maybe try adding ;deviceside=true at the very end of the URL? Helped in my case.