Java program gets stuck while making HttpGet requests in a loop - java

I have to hit the public function(downloadDataQUANDL) about 1500 times in a loop to download data.
But my program after running for about 50-100 network calls, gets stuck randomly on one url.
Not sure why it is getting stuck as there is a maximum number of retries defined. So after exhausting all the attempts the program should skip and move to the next url.
Any ideas to fix the issue? please help
public List<Record> downloadDataQUANDL(String symbol){
List<Record> records = new ArrayList<Record>();
Calendar fromdate = Calendar.getInstance();
fromdate.add(Calendar.DATE, -365);
Date todate = new Date();
String url = getFeederURLQuandl(symbol, new Date(fromdate.getTimeInMillis()), todate);
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try{
HttpResponse response = retryQuandl(url);
if(response.getStatusLine().getStatusCode() == 200){
inputStreamReader = new InputStreamReader(response.getEntity().getContent());
bufferedReader = new BufferedReader(inputStreamReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
if (!Character.isDigit(line.charAt(0))) {
continue;
}
String[] values = line.split(",");
Date date = (Date) new SimpleDateFormat("yyyy-MM-dd").parse(values[0]);
records.add(new Record(date, Double.parseDouble(values[1]),
Double.parseDouble(values[2]), Double.parseDouble(values[3]),
Double.parseDouble(values[5]), Double.parseDouble(values[6])));
}
}else{
System.out.println("Data fetch failed for " + symbol);
return null;
}
}catch(Exception e){
System.out.println("Data fetch failed for " + symbol);
return null;
}
return records;
}
private HttpResponse retryQuandl(String url){
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30*1000).setConnectTimeout(30*1000).build();
HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
HttpGet request = new HttpGet(url);
System.out.println(url);
int responsecode=0;
int nooftries = 1;
HttpResponse response=null;
while(responsecode != 200 && nooftries <= 5){
try{
response = client.execute(request);
responsecode = response.getStatusLine().getStatusCode();
}catch(Exception e){}
try {
Thread.sleep(nooftries * 1000);
} catch (InterruptedException e) {}
nooftries++;
}
return response;
}

Related

Reading multiple lines from server

I'm open for other ways to do this, but this is my code:
public class Client {
public static void main (String [] args) {
try(Socket socket = new Socket("localhost", 7789)) {
BufferedReader incoming = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter outgoing = new PrintWriter(socket.getOutputStream(),true);
StringBuilder sb = new StringBuilder();
Scanner scanner = new Scanner(System.in);
String send = "";
String response = "";
while (!send.equals("logout")){
System.out.println("Enter Command: ");
send = scanner.nextLine();
outgoing.println(send);
while ((response = incoming.readLine()) != null) {
System.out.println(response);
sb.append(response);
sb.append('\n');
}
}
} catch (IOException e) {
System.out.println("Client Error: "+ e.getMessage());
}
}
}
I do get response from the server, but the program is getting stuck in the inner while loop while ((response = incoming.readLine()) != null), so i can't enter a second command. how do i break the loop if the incoming response is done ?
The problem is that incoming.readLine() will only return null if the socket is closed, otherwise it will block and wait for more input from the server.
If you can change the server, you could add some marking that the request was fully processed and then check it like this while ((response = incoming.readLine()) != "--finished--").
If you cannot, try this:
while(response.isEmpty()){
if(incoming.ready()){ //check if there is stuff to read
while ((response = incoming.readLine()) != null){
System.out.println(response);
sb.append(response);
sb.append('\n');
}
}
}

BufferedReader java.io.IOException: stream is closed

I'm calling a BufferedReader to get a HTTP response body (if it exists) and stick it in one long string variable. Sometimes when I attempt to do this I get the error java.io.IOException: stream is closed sometimes when the while loop below starts to execute. I don't understand why. I'd like to make sure the object isn't null and that is has a response body before reading in the object.
BufferedReader readBuffer = null;
if (connection.getResponseCode() >= 200 && connection.getResponseCode() <= 299) {
readBuffer = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else {
readBuffer = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}
if(readBuffer != null) {
// Get the response body output from the server
StringBuilder calculatedOutput = new StringBuilder();
String rawOutputLine;
while ((rawOutputLine = readBuffer.readLine()) != null) {
calculatedOutput.append(rawOutputLine);
}
Logger.debug(String.format("BODY: %s", calculatedOutput.toString()));
readBuffer.close();
Try this to read the response:
BufferedReader readBuffer = null;
try {
if (connection.getResponseCode() >= 200 && connection.getResponseCode() <= 299) {
readBuffer = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else {
readBuffer = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}
// Get the response body output from the server
StringBuilder calculatedOutput = new StringBuilder();
String rawOutputLine;
while ((rawOutputLine = readBuffer.readLine()) != null) {
calculatedOutput.append(rawOutputLine);
}
Logger.debug(String.format("BODY: %s", calculatedOutput.toString()));
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
readBuffer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Try this code:
BufferedReader readBuffer = null;
if (connection.getResponseCode() >= 200 && connection.getResponseCode() <= 299) {
readBuffer = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else {
readBuffer = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}
if(readBuffer != null) {
// Get the response body output from the server
StringBuilder calculatedOutput = new StringBuilder();
String rawOutputLine;
if(readBuffer.ready()) {
while ((rawOutputLine = readBuffer.readLine()) != null) {
calculatedOutput.append(rawOutputLine);
}
}
Logger.debug(String.format("BODY: %s", calculatedOutput.toString()));
readBuffer.close();

Zlib decompression in java not working

I am compressing a string in PHP 5.4.4-14+deb7u7 using
$cdat = gzcompress($dat, 9);
http://php.net/manual/en/function.gzcompress.php
Then in android/java I want to decompress it, from here:
Android: decompress string that was compressed with PHP gzcompress()
I am using:
public static String unzipString(String zippedText) {
String unzipped = null;
try {
byte[] zbytes = zippedText.getBytes("ISO-8859-1");
// Add extra byte to array when Inflater is set to true
byte[] input = new byte[zbytes.length + 1];
System.arraycopy(zbytes, 0, input, 0, zbytes.length);
input[zbytes.length] = 0;
ByteArrayInputStream bin = new ByteArrayInputStream(input);
InflaterInputStream in = new InflaterInputStream(bin);
ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
int b;
while ((b = in.read()) != -1) {
bout.write(b);
}
bout.close();
unzipped = bout.toString();
} catch (IOException e) {
}
return unzipped;
}
But when I tried it, it decompressed into an empty string, when the downloaded compressed string in android was really long.
The downloaded string was like
x�͜{o�8�a`�= �!�����[��K!(6c�E�$��]�)�HF��F\!����ə���L�LNnH]Lj٬T��M���f�'�u#�*_�7'�S^�w��*kڼn�Yޚ�I��e$.1C��~�ݟ��F�A�_Mv_�R͋��ܴ�Z^L���sU?A���?�׮�ZVmֽ6��>�B��C�M�*����^�sٸ�j����������?�"_�j�ܣY�E���h0�g��w[=&�D �oht=>�l�?��Po";`.�e�E�E��[���������sq��0���i]��������zUL�O{П��ժ�k��b�.&7��-d1_��ۣ�狝�y���=F��K!�rC�{�$����c�&9ޣH���n�x�
Does anyone know what the problem is?
Thanks.
public static Pair<String,Integer> GetHTTPResponse(String url, List<NameValuePair> urlparameters) {
String responseVal = null;
int responseCode = 0;
try {
HttpParams httpParameters = new BasicHttpParams();
int timeoutConnection = TIMEOUT_SECONDS * 1000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
int timeoutSocket = TIMEOUT_SECONDS * 1000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpClient client = new DefaultHttpClient(httpParameters);
HttpPost httppost = new HttpPost(url);
httppost.setEntity(new UrlEncodedFormEntity(urlparameters));
HttpResponse response = client.execute(httppost);
responseCode = response.getStatusLine().getStatusCode();
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
responseVal = Common.GetStringFromBufferedReader(rd);
Log.d("SERVER", responseVal);
}
catch (Exception e) {
responseCode = 0;
}
if (responseVal != null) {
responseVal = Common.unzipString(responseVal);
}
return new Pair<String, Integer>(responseVal, responseCode);
}
You can't use
BufferedReader rd =
new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
responseVal = Common.GetStringFromBufferedReader(rd);
As InputStreamReader's Javadoc notes,
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset.
Instead, you could use HttpEntity.writeTo(OutputStream) and a ByteArrayOutputStream like
ByteArrayOutputStream baos = new ByteArrayOutputStream();
response.getEntity().writeTo(baos);
byte[] content = baos.toByteArray();
Then you can directly pass the content to your function in that byte[], and never silently swallow an Exception.
public static String unzipString(byte[] zbytes) {
String charsetName = "ISO-8859-1";
String unzipped = null;
try {
// Add extra byte to array when Inflater is set to true
byte[] input = new byte[zbytes.length + 1];
System.arraycopy(zbytes, 0, input, 0, zbytes.length);
input[zbytes.length] = 0;
ByteArrayInputStream bin = new ByteArrayInputStream(input);
InflaterInputStream in = new InflaterInputStream(bin);
ByteArrayOutputStream bout = new ByteArrayOutputStream(512);
int b;
while ((b = in.read()) != -1) {
bout.write(b);
}
bout.close();
unzipped = bout.toString(charsetName);
} catch (IOException e) {
e.printStackTrace();
}
return unzipped;
}

Reading data from an API

I have written a function to read some data from an external API. What my function does is , it calls that API while reading a file from the disk. I want to optimize my code for large size of a file (35000 records). Could you please suggest me on this.
Following is my code.
public void readCSVFile() {
try {
br = new BufferedReader(new FileReader(getFileName()));
while ((line = br.readLine()) != null) {
String[] splitLine = line.split(cvsSplitBy);
String campaign = splitLine[0];
String adGroup = splitLine[1];
String url = splitLine[2];
long searchCount = getSearchCount(url);
StringBuilder sb = new StringBuilder();
sb.append(campaign + ",");
sb.append(adGroup + ",");
sb.append(searchCount + ",");
writeToFile(sb, getNewFileName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
private long getSearchCount(String url) {
long recordCount = 0;
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(
"api.com/querysearch?q="
+ url);
getRequest.addHeader("accept", "application/json");
HttpResponse response = httpClient.execute(getRequest);
if (response.getStatusLine().getStatusCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatusLine().getStatusCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(response.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null) {
try {
JSONObject json = (JSONObject) new JSONParser()
.parse(output);
JSONObject result = (JSONObject) json.get("result");
recordCount = (long) result.get("count");
System.out.println(url + "=" + recordCount);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
httpClient.getConnectionManager().shutdown();
} catch (Exception e) {
e.getStackTrace();
}
return recordCount;
}
Since remote calls are slower than local disk access, you'll want to in some way parallelize or batch your remote calls. If you can't make batch calls to the remote API, but it allows multiple concurrent reads, then perhaps you want to use something like a thread pool to make the remote calls:
public void readCSVFile() {
// exception handling ignored for space
br = new BufferedReader(new FileReader(getFileName()));
List<Future<String>> futures = new ArrayList<Future<String>>();
ExecutorService pool = Executors.newFixedThreadPool(5);
while ((line = br.readLine()) != null) {
final String[] splitLine = line.split(cvsSplitBy);
futures.add(pool.submit(new Callable<String> {
public String call() {
long searchCount = getSearchCount(splitLine[2]);
return new StringBuilder()
.append(splitLine[0]+ ",")
.append(splitLine[1]+ ",")
.append(searchCount + ",")
.toString();
}
}));
}
for (Future<String> fs: futures) {
writeToFile(fs.get(), getNewFileName());
}
pool.shutdown();
}
Ideally, though, you'd really want to make a single batch read from the remote API if at all possible.

Can't POST data to site using HttpURLConnection on Android

I'm essentially trying to mimic what's been done here through the Android app but for some reason data doesn't get returned as soon as it attempts to post data (it returns fine when I delete the writer.write(finalResult) line).
All I want right now is to be able to search for a user's data once I've sent the username.
Here's my code below:
try {
URL u = new URL(url);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("POST");
c.setRequestProperty("Content-length", "0");
c.setConnectTimeout(timeout);
c.setReadTimeout(timeout);
c.setDoInput(true);
c.setDoOutput(true);
//Attempting to send data!
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("username", paramValue));
OutputStream os = c.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
String finalResult = getQuery(params);
Log.d("params", finalResult);
writer.write(finalResult);
writer.close();
os.close();
c.connect();
int status = c.getResponseCode();
switch (status) {
case 200:
case 201:
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
result = sb.toString();
}
} catch (MalformedURLException ex) {
Log.e("log_tag", "Error converting result ");
} catch (IOException ex) {
Log.e("log_tag", "Error in http connection ");
}
//json code!
//parse json data
try{
JSONArray jArray = new JSONArray(result);
//for each object in our json array
for(int i =0; i < jArray.length(); i++){
JSONObject json_data =jArray.getJSONObject(i);
String address = "";
//Checks for missing data in address - Need a class for all fields
if (json_data.isNull("address")){
address = "N/A";
}
else
{
address = json_data.getString("address");;
}
//read one line of the response
myListView.setText("Username: "+json_data.getString("username")
+" / " + "Name: " + json_data.getString("name")
+" / " + "E-mail: " + json_data.getString("email")
+" / " + "Address: " + address);
}
}
catch(JSONException e){
Log.e("log_tag", "Error parsing data"+e.toString());
}
}
private String getQuery(List<NameValuePair> params) throws UnsupportedEncodingException
{
StringBuilder result = new StringBuilder();
boolean first = true;
for (NameValuePair pair : params)
{
if (first)
first = false;
else
result.append("&");
result.append(URLEncoder.encode(pair.getName(), "UTF-8"));
result.append("=");
result.append(URLEncoder.encode(pair.getValue(), "UTF-8"));
}
return result.toString();
}
And here is my php script:
<?php
$searchuser = $_GET["username"];
$databasehost = databasehost;
$databasename = database;
$databaseusername = username;
$databasepassword = password;
$con = mysql_connect($databasehost, $databaseusername, $databasepassword) or die(mysql_error());
mysql_select_db($databasename) or die(mysql_error());
$query = "SELECT * FROM testusers";
$sth = mysql_query($query);
if (mysql_errno()) {
header("HTTP/1.1 500 Internal Server Error");
echo $query."\n";
echo mysql_error();
}
else
{
$rows = array();
while ($r = mysql_fetch_assoc($sth)){
$rows[] = $r;
}
print json_encode($rows);
}
?>
Since you set the header Content-Length to be 0, the server doesn't even read your content... So anything you send isn't received. You should set Content-Length to finalResult.length().
remove this,
c.setRequestProperty("Content-length", "0");

Categories

Resources