FileNotFoundException on getInputStream from GAE address - java

I'm doing an Android app with an API with Python. The API is on a Google App Engine cloud and everything works fine when I tested it with Postman.
I'm trying to do a Login with a POST method. That method returns json with the user information I keep getting that error: FileNotFoundException
Here is some of my code:
try{
String account = params[0].get(0);
String password = params[0].get(1);
URL url = new URL("http", WEB_SERVICE_URL, PORT, REST_LOGIN);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(CONNECTION_TIMEOUT);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Accept", "application/json");
JSONObject json = jsonParser.serialJsonLogin(nomCompte, motPasse);
osw = new OutputStreamWriter(httpURLConnection.getOutputStream(),"UTF-8");
osw.write(json.toString());
osw.flush();
String body = readStream(httpURLConnection.getInputStream());
osw.close();
Log.i(TAG, "Return : " + body);
user = jsonParser.deserializeJsonUser(body);
}catch (Exception e) {
mException = e;
}finally {
if (mHttpURLConnection != null) {
mHttpURLConnection.disconnect();
}
}
return user;
At: String body = readStream(httpURLConnection.getInputStream()); I'm getting a java.io.FileNotFoundException: http://10.0.2.2:8080/login
My readStream method is fine, I tested it. If I look in my Google App Engine logs, I can see that there is no 404, or anything wrong. If I find the user I get a 201 if not a 403. So even if the error says FileNotFound, I see status code which means that actually the URL is right.
UPDATE: My API was giving me a 201 and getInputStream apparently doesn't work on 201 status. Changed my return status to 200 in my API and it works fine.

Related

How to properly post url in android with java using HttpURLConnection

I try to use HttpURLConnection to send a post request to my local (xampp) server with an url like this http://xxx.xxx.0.3/Company/index.php/booking/c200/p-205/2025-02-09 8:2 , the server php file take param in url and send data to mysql database .
The url works fine on postman agent , and even another get method request works smooth in the android application .
Yet when i try the post method with following code :
public void postOrder() {
TextView tv = findViewById(R.id.tv1);
Thread t = new Thread( new Runnable() {
#Override
public void run() {
HttpURLConnection conn = null;
try {
String link = "http://xxx.xxx.0.3/Company/index.php/booking/c200/p-205/2025-02-09 8:2";
URL url = new URL(link);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setReadTimeout(10000 /*ms*/);
conn.setConnectTimeout(15000 /*ms*/);
conn.connect();
}
catch (IOException e) {
Log.d("HTTP error: ", e.toString());
}
finally {
conn.disconnect();
}
}
} );
t.start();
}
It never sent the url and thus no data is stored to database .
And with 6 hours of trial and error , google and searching , i added this line of code :
InputStream is = conn.getInputStream();
And it finally works .
Please answer me why it only works after adding this line of code , what does it do ? I thought the url is triggered right after conn.connect();
Calling connect() only connects, but it doesn't send anything yet. Call getResponseCode() to force the request to be sent. That method is safer than getInputStream() which will throw an exception if the response is not a 2xx (in which case you'd need getErrorStream()).

Getting "java.io.IOException: Server returned HTTP response code: 403 for URL: " in java code

I am trying to validate the linkedIn profile of 100K person and wrote a dummy code but its giving "java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.linkedin.com/in/test.user"
I have tried setting different setRequestProperty but not working.
public static void main(final String[] args) {
String output = "";
int TIMEOUT_VALUE = 99999999;
HttpURLConnection conn = null;
BufferedReader br = null;
String urlEndPoint = "";
String authUser = "";
String authPwd = "";
try {
long start = System.nanoTime();
urlEndPoint = "https://www.linkedin.com/in/test.user";
authUser = "linkedin-username";
authPwd = "linkedin-password";
URL url = new URL(urlEndPoint);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("username", authUser);
conn.setRequestProperty("password", authPwd);
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Keep-Alive", "header");
conn.setRequestProperty("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
conn.setConnectTimeout(TIMEOUT_VALUE);
conn.setReadTimeout(TIMEOUT_VALUE);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Language", "en-US,en;q=0.9,mt;q=0.8");
conn.setRequestProperty("Accept-Encoding", "gzip,deflate,br");
conn.setRequestProperty("Host", "www.linkedin.com");
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36");
conn.setRequestProperty("http.agent", "Chrome/71.0.3578.80 (Windows NT 10.0; Win64; x64)");
conn.setDoOutput(true);
String userPassword = authUser + ":" + authPwd;
String encoding = Base64Encoder.encode(userPassword);
conn.setRequestProperty("Authorization", "Basic " + encoding);
OutputStream os = conn.getOutputStream();
os.flush();
conn.connect();
br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
while ((output = br.readLine()) != null) {
System.out.println(output);
}
if (br != null) {
br.close();
}
if (os != null) {
os.close();
}
long elapsed = System.nanoTime() - start;
} catch (MalformedURLException e) {
//this.logger.error("Error occurred during processPartyTerrRelationship ", e);
e.printStackTrace();
} catch (IOException e) {
//this.logger.error("Error occurred during processPartyTerrRelationship ", e);
e.printStackTrace();
} catch (Exception e) {
//this.logger.error("Error occurred during processPartyTerrRelationship ", e);
e.printStackTrace();
} finally {
try {
if (conn != null) {
conn.disconnect();
}
} catch (Exception e) {
//this.logger.error("Error occurred during processPartyTerrRelationship ", e);
e.printStackTrace();
}
}
//logger.info("processPartyTerrRelationship called ends");
}
The outcode of above code is :
java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.linkedin.com/in/test.user
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1894)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
at ValidateLinkedInProfiles.main(ValidateLinkedInProfiles.java:57)
The HTTP error code 403 is an error related to the authorization to the requested resource:
HTTP 403 provides a distinct error case from HTTP 401; while HTTP 401 is returned when the client has not authenticated, and implies that a successful response may be returned following valid authentication, HTTP 403 is returned when the client is not permitted access to the resource for some reason besides authentication
It's hard to understand how you're working. The LinkedIn link requires login. But you indeed need to debug it somehow and need a raw real output to the server with the correct one otherwise you will not complete it. If you have Java example program, see if they or you have a typo, but again without screenshot or text from LinkedIn I cannot debug it. Maybe try to add the examples and I will try to help you (just make me login with my public profile to other places). Also make sure there is your real password and your user account in the correct fields of course (authUsr,authPwd shall not be copy paste unlike everything else).
HTTP 403 is a legitimate response from a server. So the behavior is valid. However, I would recommend to use some HTTP client utility rather then writing your own code to make Http request. This will reduce the chance of a problem caused by your own code. As some Http clients I would suggest Apache Http Client or OK Http client or MgntUtils Http Client (see MgntUtils HttpClient javadoc here, Full MgntUtils library on github is here and Maven repository is here). Disclaimer: MgntUtils library is written by me
HTTP 403 is a standard HTTP status code communicated to clients by an HTTP server to indicate that the server understood the request, but will not fulfill it. There are a number of sub-status error codes that provide a more specific reason for responding with the 403 status code.
You either do not have access to the site(try logging in from a browser and try to run the script from the same browser, if your access is shared across different tabs of the same browser that is also fine, but make sure you're authorized) or the request to the link contains sensitive information which the site doesn't want to share.

GCM Push Notifications are not delivered to devices

We (Panos and Rainer - see the comments down) have a server and several Android devices.
We want to send push notifications from our server via GCM to the Android devices.
Now we make a post request to the GCM server. The GCM server response is that all is fine (success==1 and even the message-id)!
BUT the push notification(s) are never delivered to the devices.
If we use the same data and the Chrome addon Postman - the notifications are delivered immediately.
We tried all lot of different solutions. We get always the feedback of the GCM server that all is ok - but the push notifications aren't send.
We also tried this one:
https://github.com/googlesamples/google-services/blob/master/android/gcm/gcmsender/src/main/java/gcm/play/android/samples/com/gcmsender/GcmSender.java
You might also post the URL you use. There is a new GCM enpoint which looks like the following:
https://gcm-http.googleapis.com/gcm/send
I am not yet sure what's causing the issues on your side. But the following is tested and working:
public class Main {
public static void main(String[] args) {
// write your code here
try {
String url = "https://gcm-http.googleapis.com/gcm/send";
URL obj = new URL(url);
HttpsURLConnectionImpl conn = (HttpsURLConnectionImpl) obj.openConnection();
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty ("Authorization", "key=***");
String title = "Short title";
String body = "A body :D";
String token = "****";
String data = "{ \"notification\": { \"title\": \"" + title +"\", \"body\": \"" + body + "\" }, \"to\" : \"" + token + "\", \"priority\" : \"high\" }";
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(data);
out.close();
String text = getText(new InputStreamReader(conn.getInputStream()));
System.out.println(text);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getText(InputStreamReader in) throws IOException {
StringBuilder sb=new StringBuilder();
BufferedReader br = new BufferedReader(in);
String read;
while((read=br.readLine()) != null) {
sb.append(read);
}
br.close();
return sb.toString();
}
}
This is the data used for the Postman request which is working without any problem.
Rainer already mentioned that we tried several implementations on the Java side and it seems that we are always able to communicate with the service and receive a response which seems to look correct so far:
{
"multicast_id":7456542468425129822,
"success":1,
"failure":0,
"canonical_ids":0,
"results":
[{
"message_id":"0:1457548597263237%39c590d7f9fd7ecd"
}]
}
Not sure if I'm on the right track but do you mean downstream HTTP messages (plain text)?
Tried to send the following JSON to the service (from Postman) which results again in a positive response but this time the notification did not reach the device (just to make that clear, at the moment there is no app on the device listening actively for incoming notifications -> first of all we just want to ensure that they generally arrive on the device):
{
"data":
{
"score": "5x1",
"time": "15:10"
},
"to" : "SECRET-DEVICE-TOKEN"
}
Thanks to all of you trying to help here but to be honest, this issue is really frustrating. Communicating with an interface\service which seems not to be able to return a useful response in case the request contains maybe evil stuff which will finally prevent GCM from sending the push notification to the device, feels like a pain in the ass. If Postman would also fail I would say ok, you can not be so stupid :-)
Here are some quick'n dirty implementations we have already used.
Example
try
{
URL url = new URL(apiUrl);
HttpsURLConnection conn = (HttpsURLConnection);//also tried HttpURLConnection
url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key="+apiKey);
conn.setDoOutput(true);
String json = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
OutputStream os = conn.getOutputStream();
os.write(json.getBytes());
os.flush();
}
catch(Exception exc)
{
System.out.println("Error while trying to send push notification: "+exc);
}
Example
HttpClient httpClient = HttpClientBuilder.create().build();
try
{
HttpPost request = new HttpPost(apiUrl);
StringEntity params =new StringEntity("{\"priority\":\"high\",\"notification\":{\title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}");
request.addHeader("Content-Type", "application/json");
request.addHeader("Authorization", "key="+apiKey);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// check response
System.out.println(response.getStatusLine().toString());
}catch (Exception exc) {
System.out.println("Error while trying to send push notification: "+exc);
} finally {
httpClient.getConnectionManager().shutdown(); //Deprecated
}
Example
try
{
String charset = "UTF-8";
URLConnection connection = new URL(apiUrl).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/json;charset=" + charset);
connection.setRequestProperty("Authorization", "key="+apiKey);
String param = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
try (OutputStream output = connection.getOutputStream())
{
output.write(param.getBytes(charset));
}
InputStream response = connection.getInputStream();
}
catch(Exception exc)
{
System.out.println("Error while trying to send push notification: "+exc);
}
Example
try
{
// prepare JSON
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("message", "{ \"data\": {\"score\": \"5x1\",\"time\": \"15:10\"},\"to\" : \""+deviceToken+"\"}");
jGcmData.put("to", deviceToken);
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + apiKey);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
// Read GCM response.
InputStream inputStream = conn.getInputStream();
String resp = IOUtils.toString(inputStream);
System.out.println(resp);
} catch (IOException e) {
System.out.println("Unable to send GCM message. "+e);
}
Mike, with your example it's working also on our side. After comparing your implementation with the on eon our side, the only real difference I found is the used URL!!
Somehow the URL used in our Java implementation was https://android.googleapis.com/gcm/send
Seems that https://gcm-http.googleapis.com/gcm/send is the right one which by the way was also used for our Postman tests.
But why on hell is the URL from our failed tests still somehowe valid and returns a response!?
Setting the priority to high in the json resolved the issue for me.
'registration_ids' => $id,
'priority' => 'high',
'data' => $load
For our case, the clients Android devices had intermittent internet connection issue, that is, network dropouts thus causing notification delivery failed. We resolved the reliability issue with the following JAVA GCM code:
gcmPayload.setTime_to_live(messageExpiryTime); //in seconds. Set notification message expiry to give user time to receive it in case they have intermittent internet connection, or phone was off
gcmPayload.setPriority("high");
and APNS code:
ApnsService apnsService = APNS.newService().withCert(certificateStream, configurations.getApnPassword()).withProductionDestination().build();
PayloadBuilder payloadBuilder = APNS.newPayload();
...
payloadBuilder.instantDeliveryOrSilentNotification(); //same as content-available=true
String payload = payloadBuilder.build();
Integer now = (int)(new Date().getTime()/1000);
//use EnhancedApnsNotification to set message expiry time
for(String deviceToken : deviceTokens) {
EnhancedApnsNotification notification = new EnhancedApnsNotification(EnhancedApnsNotification.INCREMENT_ID() /* Next ID */,
now + messageExpiryTime /* Expiry time in seconds */,
deviceToken /* Device Token */,
payload);
apnsService.push(notification);
}
Also, remember to consider time zone if your backend server time is different to the client mobile app time.

How to login to server and then hit a url on the same server to get JSON in return

Whenever I try to hit a url using java it will redirect me to login page. How can I first login then hit a specific url to get JSON in return ?
Here what I tried so far:
try {
URL url = new URL(GET_EXPENSE_FOR_VENDOR_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
String response;
System.out.println("Output from Server .... \n");
while ((response = br.readLine()) != null) {
System.out.println(response);
Gson gson = new Gson();
gson.fromJson(response, ExpenseAllocationDTO[].class);
Type collectionType = new TypeToken<Collection<ExpenseAllocationDTO>>() {
}.getType();
expenseAllocationList = gson.fromJson(response, collectionType);
expenseAllocationDTODataModel = (new ExpenseAllocationDTODataModel(expenseAllocationList));
if (expenseAllocationList.isEmpty() || expenseAllocationList == null) {
expenseExists = true;
}
conn.disconnect();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The problem
I believe the initial request is missing some headers. Only the Accept header is set.
How to solve it ?
Option #1
In order to discover the missing headers, open your favorite browser and browse to GET_EXPENSE_FOR_VENDOR_URL. Before browsing, open the webdeveloper toolbar in order to see headers sent by the browser.
Here is a sample screenshot of the webdeveloper toolbar under Chrome on Windows.
.
Option #2
If your browser doesn't have such a toolbar, you can use a tool like Fiddler for finding the missing headers.
Option #3
You can also use a tool like hurl.it in order to test the headers expected by the target server as you discover them. IMO, this tool can be more straight forward than Fiddler during the debugging phase.
Get back to your code
Once you have identified the missing headers, add them to your Java code like this:
URL url = new URL(GET_EXPENSE_FOR_VENDOR_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Missing-Header-1", "...");
conn.setRequestProperty("Missing-Header-2", "...");

Http POST in BlackBerry

Greetings,
I am trying to setup a server connection from my BlackBerry Application . I was able to get a response code on the status of the server. Now i have a few values which i have to POST to the server
Its like a registration page values(username, password, age ) have to be sent to the server .
ConnectionFactory connFact = new ConnectionFactory();
ConnectionDescriptor connDesc;
connDesc = connFact.getConnection(url);
if (connDesc != null)
{
HttpConnection httpConn;
httpConn = (HttpConnection)connDesc.getConnection();
try
{
final int iResponseCode = httpConn.getResponseCode();
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
Dialog.alert("Response code: " + Integer.toString(iResponseCode));
}
});
}
catch (IOException e)
{
System.err.println("Caught IOException: " + e.getMessage());
}
}
Thats the code i used to get the response code.
I would appreciate it if someone could help me how i can make a POST request to the server..
the server url for status was company.com/app/version/stats
when it for register it would be
company.com/app/register
Thank you
What type of a POST do you use? If you are just passing key-value pairs, then it should be a POST of a "application/x-www-form-urlencoded" content-type.
So, what lacks youe code is:
1). Set a proper content-type on your connection:
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
2). Prepare the content to be sent to the server via the POST:
URLEncodedPostData encPostData = new URLEncodedPostData("UTF-8", false);
encPostData.append("username", username);
encPostData.append("password", password);
encPostData.append("age", age);
byte[] postData = encPostData.toString().getBytes("UTF-8");
3). Set content-length for the connection (this step may be optional - try without this first, probably the BB OS is smart enough to set this automatically):
httpConn.setRequestProperty("Content-Length", String.valueOf(postData.length));
4). Open an OutputStream and write the content to it (the code is simplified):
OutputStream os = httpConn.openOutputStream();
os.write(postData);
os.flush();
...
httpConn = (HttpConnection)connDesc.getConnection();
httpConn.setRequestMethod(HttpConnection.POST);
httpConn.setRequestProperty("username",name);
httpConn.setRequestProperty("password",pass);
....

Categories