I am to ask your kind help for a problem I cannot solve...
I have the following code:
String https_url = "https://...";
try {
HttpsURLConnection connection = (HttpsURLConnection) new URL(https_url).openConnection();
String query = "api_key=1234&portal_id=1234&username="+username;
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Length", String.valueOf(query.length()));
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
DataOutputStream output = new DataOutputStream(connection.getOutputStream());
output.writeBytes(query);
output.close();
DataInputStream input = new DataInputStream( connection.getInputStream() );
String ret = "";
for( int c = input.read(); c != -1; c = input.read() ) {
ret += (char)c ;
}
input.close();
int code = connection .getResponseCode();
String message = connection .getResponseMessage();
System.out.println("Resp Code:"+code);
System.out.println("Resp Message:"+ message);
//...
This code has been running for a couple of years, and until some weeks ago, it has worked fine, then suddenly, it started to got a
java.net.SocketException: Connection reset
soon after the line
output = new DataOutputStream(connection.getOutputStream());
This code runs into a Java web application, and it is called after the click on a button of a web page.
I don't know if something has changed on server side, but the strange thing is that if I put this code into a main method of a stand alone class, export the class on an executable jar file, and launch the jar from the same environment where the web application is deployed, this code still works and I don't get any exception.
Any suggestions? Thank you again
Step
Related
I want to run php-file on a server from Android Studio. The file will add a string to the database and return the value 'success' if successful. I don’t see the point in uploading php-file – it processes a POST request. There are absolutely no errors in it. At first I made this code in the console and it worked perfectly. But when I copied it to Android Studio, it turned out that "D/NetworkSecurityConfig: No Network Security Config specified, using platform default". This is strange because I just ran the same code in the console and there were no errors. But now the most interesting thing: if you replace the cycle that reads the input stream by reading one line, the error disappears. How it works? I thought that there was a request limitation on the server, but everything works from the console application. Maybe this is a feature of Android Studio?
try {
URL url = new URL("https://educationapps.site/hello.php");
String postData = "username=" + username + "&email=" + email +
"&password=" + password + "&func=" + func;
byte[] postDataBytes = postData.getBytes(StandardCharsets.UTF_8);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length",
String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream(),
StandardCharsets.UTF_8));
// This code does not work ↓↓↓
/*
for (int c; (c = in.read()) >= 0;)
System.out.print((char)c);
*/
// But this one works ↓↓↓
String c = in.readLine();
System.out.println(c);
} catch (Throwable throwable) {
System.out.println(throwable.getMessage());
}
Given your comments, I think this will fix the problem.
for (int c; (c = in.read()) >= 0;)
System.out.print((char) c);
System.out.println();
// and get rid of the 2 statements after this.
The problem appears to be that System.out is not being flushed. System.out is a PrintStream, and a PrintStream can be configured to "autoflush" when line terminator is written.
In your version with a println(c) you were adding a line terminator.
When you ran the code from the command line, System.out was probably being flushed when main returned.
The Android Studio console behavior is ... well ... whatever it is. But it is not a good idea for your code to make assumptions about how the console / console emulator is going to work. Terminate your lines, or explicitly flush() or close() the output stream when you want to be sure that the data goes where it needs to go.
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.
Today I started developing a new Android app which is based on the Windows Azure Mobile Services.
I've tried to use the SDK provided by Microsoft for the whole day, without any success. Every time the app performs a web request, this one returns a 400, BAD REQUEST code.
I go to a lower level, with the following code.
URL url = new URL("https://xxxx.azure-mobile.net/api/contents"); //host obscured
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
//I obscure the authentication and app key, but they are correct in the program
conn.addRequestProperty("AUTHORIZATION", "Basic xxxxxxxxxxxxxxx");
conn.addRequestProperty("X-ZUMO-APPLICATION", "xxxxxxxxxxxxxxxx");
conn.addRequestProperty("ACCEPT", "application/json");
//connect
conn.connect();
int code = conn.getResponseCode(); //400 in the emulator, 200 in a standard java code
String message = conn.getResponseMessage();
InputStream is = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String read = null;
StringBuilder sb = new StringBuilder();
do {
//Read the content
read = br.readLine();
sb.append(read);
} while(read != null);
//print the content
System.out.println(sb.toString());
//Close the buffers
br.close();
isr.close();
is.close();
System.out.println("Status Code: "+code);
System.out.println(message);
conn.disconnect();
It works perfectly in a standard java application, but in the emulator I still get 400 BAD REQUEST. I really do not understand why!
Maybe an issue of the emulator?
I was running an Android Emulator with API 10.
I'd like to try the code on a real device, but the mac does not recognize it... And the device worked until yesterday since I debugged an application with it.
If you know what I am doing wrong, please help me.
EDIT 20-03-2014:
I made some other attempts. I tried with the HttpClient API. No luck.
I'm still getting 400 as response code and Bad Request as response Message.
The thrown Exception is UnknownHostException... But the InetAddress.getByName(); successfully get an IP address for my web service.
The app still work with Android version greater than 4, I have not tried with Android 3.
I'm very sad and frustrated...
Thank you for your time,
Rik.
SOLVED
Oddly, the problem was in the AUTHENTICATION header.
I computed the header with the following code:
public setHeader(String code, String username)
{
StringBuilder sb = new StringBuilder(username);
sb.append(":");
sb.append(code);
sb = new StringBuilder(Base64.encodeToString(sb.toString().getBytes(), Base64.DEFAULT));
sb.insert(0, "Basic ");
auth = sb.toString();
}
The Base64.encodeToString() method adds a \n at the end of the line. .__.
By adding a trim() in the last line, I threw away the new line and everything went fine in both 2.3.3 and 4 Android versions.
My httpURLConnection fails with 404 - Resource not Found error. The same URL works on my firefox poster and returns 200/ok. Both the applications(webapp and the URL-app) are located on the same machine. I found from another thread that I need to add below 2 lines to make it work when the same URL works from browser-
urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
urlConnection.setRequestProperty("Accept","/");
Unfortunately adding above lines didn't fix the problem. Am I doing anything wrong in the code below ? Any useful suggestions will be much appreciated.
{
String computerName = InetAddress.getLocalHost().getHostName();
url = new URL("http://"+computerName+":8080"+"/cerprovider/devices");
urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDefaultUseCaches(false);
urlConnection.setUseCaches(false);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Content-Length", Integer.toString(Integer.MAX_VALUE));
urlConnection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
urlConnection.setRequestProperty("Accept","*/*");
urlConnection.setConnectTimeout(500);
// Create I/O streams
outStream = new DataOutputStream(urlConnection.getOutputStream());
//inStream = new DataInputStream(urlConnection.getInputStream());
// Send request
outStream.writeBytes(<blah>.toString());
outStream.flush();
outStream.close();
BufferedReader in = null;
String responseErrorString = "";
_tracer.info("Response code --"+urlConnection.getResponseCode());
InputStream error = urlConnection.getErrorStream();
_tracer.info("Error from the connection --"+error.toString());
StringBuilder buf = new StringBuilder();
for(int c = -1; (c = error.read()) != -1; )
buf.append((char)c);
responseErrorString = new String (buf);
_tracer.info("responseErrorString--"+responseErrorString);
}
try to send request again. In my project I am using Apache HttpClient to send request & many times the 404 error resolve by sending request again. (but not all the time)
Also use httpfox plugin on firefox to check what exactly happening when u send request.
404 error is supposed to b for 'resource temporarily not available'.
I'm have created an application which sends GET requests to a URL, and then downloads the full content of that page.
The client sends a GET to e.g. stackoverflow.com, and forwards the response to a parser, which has the resposibility to find all the sources from the page that needs to be downloaded with subsequent GET requests.
The method below is used to send those GET requests. It is called many times consecutively, with the URLs returned by the parser. Most of those URLs are located on the same host, and should be able to share the TCP connection.
public static void sendGetRequestToSubObject(String RecUrl)
{
URL url = new URL(recUrl.toString());
URLConnection connection = url.openConnection ();
InputStreamReader isr = new InputStreamReader(connection.getInputStream());
}
Each time this method is called, a new TCP connection is created (with a TCP 3-way handshake) and the GET is then sent on that connection. But I want to reuse the TCP connections, to improve performance.
I guess that since I create a new URL object each time the method is called, this is the way it going to work...
Maybe someone can help me do this in a better way?
Thanks!
HttpURLConnection will reuse connections if it can!
For this to work, several preconditions need to be fulfilled, mostly on the server side. Those preconditions are described in the article linked to above.
Found the problem! I was not reading the input stream properly. This caused the input stream objects to hang, and they could not be reused.
I only defined it, like this:
InputStreamReader isr = new InputStreamReader(connection.getInputStream());
but I never read from it :-)
I changed the read method as well. Instead of a buffered reader I stole this:
InputStream in = null;
String queryResult = "";
try {
URL url = new URL(archiveQuery);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.connect();
in = httpConn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int read = 0;
int bufSize = 512;
byte[] buffer = new byte[bufSize];
while(true){
read = bis.read(buffer);
if(read==-1){
break;
}
baf.append(buffer, 0, read);
}
queryResult = new String(baf.toByteArray());
} catch (MalformedURLException e) {
// DEBUG
Log.e("DEBUG: ", e.toString());
} catch (IOException e) {
// DEBUG
Log.e("DEBUG: ", e.toString());
}
}
From here: Reading HttpURLConnection InputStream - manual buffer or BufferedInputStream?