I've followed the UA tutorials and got my APID , and successfully recieved test push message on my android device.
Now the next thing that I like to do is to target my device using JAVA and send push messaged.
From what I've seen so far the best way to achieve this is using their web API.
However When I'm trying to send a post message I always get the following error :
java.io.IOException: Server returned HTTP response code: 401 for URL: https://go.urbanairship.com/api/push/
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at com.Sender.Sender.main(Sender.java:56)
This is the code that I use :
package com.Sender;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class Sender {
/**
* #param args
*/
public static void main(String[] args) {
try {
String responseString = "";
String outputString = "";
String username = "MWMoRVhmRXOG6IrvhMm-BA";
String password = "ebsJS2iXR5aMJcOKe4rCcA";
MyAuthenticator ma= new MyAuthenticator(username, password);
Authenticator.setDefault(ma);
URL url = new URL("https://go.urbanairship.com/api/push/");
URLConnection urlConnection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) urlConnection;
ByteArrayOutputStream bout = new ByteArrayOutputStream();
String APID = "23eef280-19c8-40fc-b798-788f50e255a2";
String postdata = "{\"android\": {\"alert\": \"Hello from JAVA!\"}, \"apids\": [\""+APID+"\"]}";
byte[] buffer = new byte[postdata.length()];
buffer = postdata.getBytes("UTF8");
bout.write(buffer);
byte[] b = bout.toByteArray();
httpConn.setRequestProperty("Content-Length",
String.valueOf(b.length));
httpConn.setRequestProperty("Content-Type", "application/json");
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
OutputStream out = httpConn.getOutputStream();
out.write(b);
out.close();
InputStreamReader isr = new InputStreamReader(
httpConn.getInputStream());
BufferedReader in = new BufferedReader(isr);
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
System.out.println(outputString);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
Can you help me please ?
HTTP 401 represent Unauthorized access. In your code even though your created Authenticator, you didn't provide it as part of post request header. Here is tutorial on how to set authenticator for a URLConnection.
Related
Looked through stackoverflow for resolutions, and found this but that didn't help.
Getting this exception
java.net.ProtocolException: Server redirected too many times (20)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1932)
at java.base/sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1520)
at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:250)
at GetMailStatus.main(GetMailStatus.java:27)
for this block of code that's trying to access an InformedDelivery url with credentials
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.*;
import java.util.Base64;
public class GetMailStatus {
public static void main(String[] args) {
try {
URL url = new URL ("https://informeddelivery.usps.com/.........");
String encoding = Base64.getEncoder().encodeToString(("xxxx:yyyy").getBytes("UTF-8"));
CookieManager msCookieManager = new java.net.CookieManager(null, CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(msCookieManager);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty ("Authorization", "Basic " + encoding);
InputStream content = (InputStream)connection.getInputStream();
BufferedReader in =
new BufferedReader (new InputStreamReader (content));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
The code was modified based on the referenced stackoverflow discussion. I'm assuming I'm still not managing cookies correctly. Any suggestions?
Overview of goals: (1) save XML file to a string element in IntelliJ (2) send the request XML to an http endpoint (3) get the response XML from the http endpoint
So far I have been able to read the XML response but keep receiving errors on my attempts to send a request. I have working methods not implementing the REST methods but would prefer to use those for my project. It's a bit of a rudimentary approach as I am still learning so any tips are greatly appreciated. Would like to be closer to the
My attempts so far have been to set the xml request as a string to send to the endpoint and then read the response from that same endpoint. Below is the code I have attempted that does not yet rely heavily on the REST method. Whenever I try to send the request, I get an error that this method is not allowed. Are there suggestions on my current code I can edit to get this request working?
package com.tests.restassured;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class VIVPXMLResponseTest {
public static void main(String[] args) {
VIVPXMLResponseTest vivpXMLResponseTest = new VIVPXMLResponseTest();
vivpXMLResponseTest.getXMLResponse("Success");
}
public void getXMLResponse(String responseCode) {
String wsURL = "http://localhost:8080/hello/Hello2You";
URL url = null;
URLConnection connection = null;
HttpURLConnection httpConn = null;
String responseString = null;
String outputString = "";
ByteArrayOutputStream bout = null;
OutputStream out = null;
InputStreamReader isr = null;
BufferedReader in = null;
String xmlInputRequest = "<pasteXMLrequestHere>";
try {
url = new URL(wsURL); // create url object using our webservice url
connection = url.openConnection(); // create a connection
httpConn = (HttpURLConnection) connection; // cast it to an http connection
byte[] buffer = new byte[xmlInputRequest.length()]; // xml input converted into a byte array
buffer = xmlInputRequest.getBytes(); // put all bytes into buffer
String SOAPAction = "";
//Set the appropriate HTTP parameters
httpConn.setRequestProperty("Content-Length", String
.valueOf(buffer.length));
httpConn.setRequestProperty("Content-Type",
"text/xml; charset=utf-8");
httpConn.setRequestProperty("SOAPAction", SOAPAction);
httpConn.setRequestMethod("POST");
//httpConn.setRequestMethod("GET");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
out = httpConn.getOutputStream();
out.write(buffer); // write buffer to output stream
out.close();
//Read response from the server and write it to standard out
isr = new InputStreamReader(httpConn.getInputStream()); //use same http connection, call getInputStream
in = new BufferedReader(isr);
while ((responseString = in.readLine()) != null) //read each line
{
outputString = outputString + responseString; //put into string -- may need to change if long file
}
System.out.println(outputString); //print out the string
System.out.println(" ");
//Get response from the web service call
Document document = parseXmlFile(outputString); //parse the XML - gets back raw XML - returns as document object model
NodeList nodeLst = document.getElementsByTagName("ns:Code"); //where success / failure response is written
NodeList nodeLst2 = document.getElementsByTagName("ns:Reason"); //where success / failure response is written
String webServiceResponse = nodeLst.item(0).getTextContent();
String webServiceResponse2 = nodeLst2.item(0).getTextContent();
System.out.println("*** The response from the web service call is : " + webServiceResponse);
System.out.println("*** The reason from the web service call is: " + webServiceResponse2);
} catch (Exception e) {
e.printStackTrace();
}
}
private Document parseXmlFile(String in) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); //get document builder factory
DocumentBuilder db = dbf.newDocumentBuilder(); //create new document builder
InputSource is = new InputSource(new StringReader(in)); //pass in input source from string reader
return db.parse(is);
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
} catch (SAXException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
I'd like to be closer to this format
#Test
#RestAssuredMethod(config = "src/test/resources/config/sampleRest.json")
public void getResponse() throws IOException {
Response response3 = given().log().all()
.when().get("updateFiles/")
.then().assertThat()
.statusCode(HttpStatus.SC_OK) //SC_OK = 200
.body("status[0].model", equalTo("Success"))
.header("Content-Type", containsString("application/json"))
.log().all(true)
.extract().response();
String firstResponse = response3.jsonPath().get("status[0].model");
asserts.assertEquals(firstResponse, "SUCCESS", "Response does not equal SUCCESS");
List allResponses = response3.jsonPath().getList("status[0].model");
System.out.println("**********" + favoriteModels);
asserts.assertTrue(allResponses.contains("Success"), "There are no success responses");
}
Edit: Here is my working send / receive response that I am trying to integrate into using full REST methods:
package com.chillyfacts.com;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class Send_XML_Post_Request {
public static void main(String[] args) {
try {
String url = "<enterEndpointHere>";
URL obj = new URL(url);
HttpURLConnection HTTPConnection = (HttpURLConnection) obj.openConnection();
HTTPConnection.setRequestMethod("POST");
HTTPConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
HTTPConnection.setDoOutput(true);
String xml = "<pasteXMLRequestHere>"
DataOutputStream writeRequest = new DataOutputStream(HTTPConnection.getOutputStream());
writeRequest.writeBytes(xml);
writeRequest.flush();
writeRequest.close();
String responseStatus = HTTPConnection.getResponseMessage();
System.out.println(responseStatus);
BufferedReader in = new BufferedReader(new InputStreamReader(
HTTPConnection.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println("\n **** RESPONSE FROM ENDPOINT RECEIVED ****: \n\n" + response.toString() + "\n\n *************** END OF RESPONSE *************** \n");
} catch (Exception e) {
System.out.println(e);
}
}
}
I'm working on an Android app for a client, and I'm calling their API to get the info for various parts of my app. There is one call that results on SocketTimeoutException if I set a timeout, or infinitely hangs if I don't; however, it works just fine on the web client(React), so it can't be the server.
Code:
package io.voluntu.voluntu;
import android.os.AsyncTask;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
public class SendApproveHours extends AsyncTask<Bundle, Void, String>{
private StringBuilder sb = new StringBuilder();
private String result;
private ApproveHours approveHours;
public SendApproveHours(ApproveHours approveHours){
this.approveHours = approveHours;
}
protected String doInBackground(Bundle... params){
Bundle b = params[0];
String jwt = b.getString("JWT");
System.out.println(jwt);
boolean approve = b.getBoolean("APPROVE");
int[] id = b.getIntArray("ID");
try {
URL url = new URL("http://voluntu.io/api/hour/update");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(2500 /* milliseconds */); //if i don't do this, it will hang indefinitely
httpURLConnection.setReadTimeout(1500 /* milliseconds */);
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Host", "voluntu.io");
httpURLConnection.setRequestProperty("Origin", "http://voluntu.io");
httpURLConnection.setRequestProperty("Referer", "http://voluntu.io/hours/approve");
httpURLConnection.setRequestProperty("Cookie", "sessionJWT=" + jwt);
httpURLConnection.connect();
JSONObject jsonObject = new JSONObject();
jsonObject.put("approveOrReject", approve);
jsonObject.put("hourIDs", Arrays.toString(id));
System.out.println(jsonObject);
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
wr.writeBytes(jsonObject.toString());
wr.flush();
wr.close();
int HttpResult = httpURLConnection.getResponseCode(); //hangs here
System.out.println("HTTP RESULT: " + HttpResult);
if(HttpResult == HttpURLConnection.HTTP_OK){
BufferedReader in = new BufferedReader(new InputStreamReader(
httpURLConnection.getInputStream(), "utf-8"
));
String line;
while((line = in.readLine()) != null){
sb.append(line);
}
in.close();
}
System.out.println("RESPONSE: " + sb.toString());
httpURLConnection.disconnect();
}
catch (MalformedURLException e){
e.printStackTrace();
}
catch (IOException e){
e.printStackTrace();
}
catch (JSONException e){
e.printStackTrace();
}
return sb.toString();
}
protected void onPostExecute(String result){
approveHours.refreshHours();
}
}
It hangs on getting the HTTP response code for some reason. I checked the headers and body and they are identical to what the web version is sending, so I have no idea why it's not working. Also, calling other parts of their API works just fine, and in fact this code is mostly copy pasted from other parts of my app that call the API. Help is appreciated!
I fixed it. Instead of an array, you must use JSONArray, or the array gets wrapped in quotes when it gets put in the JSON object.
My url as given by the shopify is in this format
https://apikey:password#hostname/admin/orders.json
So when trying to get the orders using HttpURLConnection, I am getting 401 unauthorised error. Here is my code
import java.io.*;
import java.net.*;
import java.util.Properties;
/**
* Created by admin on 22/8/15.
*/
public class Hello {
// This method should be removed in production
static void setProxy(){
Properties systemProperties = System.getProperties();
systemProperties.setProperty("http.proxyHost","lotus");
systemProperties.setProperty("http.proxyPort", "8080");
}
public static void main(String [] args)
{
try
{
setProxy();
URL url = new URL("https://apikey:password#go-frugal.myshopify.com/admin/orders.json");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("user-agent","Mozilla/5.0");
connection.setRequestProperty("Content-Type","application/json");
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String urlString = "";
String current;
while((current = in.readLine()) != null)
{
urlString += current;
}
System.out.println(urlString);
}catch(IOException e)
{
e.printStackTrace();
}
}
}
Here is the error
java.io.IOException: Server returned HTTP response code: 401 for URL: https://apikey:password#go-frugal.myshopify.com/admin/orders.json
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1313)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
at Hello.main(Hello.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Process finished with exit code 0<br>
getErrorStream returns this
{"errors":"[API] Invalid API key or access token (unrecognized login or wrong password)"}
try this ... your call sequence is wrong. hope this help.
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import org.jboss.util.Base64;
public class test9 {
public static void main(String[] args) {
URL url;
URLConnection urlConn = null;
HttpURLConnection htcon = null;
InputStream is = null;
StringBuffer sb = new StringBuffer();
String authStr = "apikey:password";
String authStringEnc = Base64.encodeBytes(authStr.getBytes());
//String authStringEnc = new String(Base64Encoder.encode(authString.getBytes()));
try {
url = new URL("https:go-frugal.myshopify.com/admin/orders.json");
urlConn = url.openConnection();
urlConn.setRequestProperty("Authorization", "Basic " + authStringEnc);
urlConn.setRequestMethod("GET");
urlConn.setRequestProperty("user-agent","Mozilla/5.0");
urlConn.setRequestProperty("Content-Type","application/json");
htcon = (HttpURLConnection) urlConn;
is = htcon.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
int numCharsRead;
char[] charArray = new char[1024];
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
System.out.println("sb: "+sb);
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is an oversight in the way Java handles authorization at the connection level. Took me a good long time to debug; it works in the browser, so why doesn't it work in Java?
Turns out that web browsers will automatically encode the authorization token for any URLs with a user info space. Java doesn't do this by default, so you have to do it yourself:
URI uri = new URL("http://username:password#protected.domain.example/resource").toURI();
String userInfo = uri.getRawUserInfo();
if(userInfo != null && userInfo.length() > 0)
userInfo = Base64.getEncoder().encodeToString(userInfo.getBytes());
HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
if(userInfo != null && userInfo.length() > 0)
connection.setRequestProperty("Authorization", "Basic " + userInfo);
connection.connect();
A few notes:
You can try using URL#getUserInfo() or URI#getUserInfo(), but there's a small chance that it won't encode passwords with legal special characters correctly.
This should work for all HTTP URLs, even if they don't have a user info segment.
I am getting a couple errors I cannot seem to fix... This is example code, so I'm confused what's going on. The error's are commented to the side of the lines where they show up.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
public class Connect {
URL url;
URLConnection urlConnection;
DataOutputStream outStream;
DataInputStream inStream;
// Build request body
String body = "fname=" + URLEncoder.encode("Atli", "UTF-8"); //Syntax error on token ";", { expected after this token
// Create connection
url = new URL("http://192.168.1.68/test/POST/post.php");
urlConnection = url.openConnection();
((HttpURLConnection)urlConnection).setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.setRequestProperty("Content-Length", ""+ body.length());
// Create I/O streams
outStream = new DataOutputStream(urlConnection.getOutputStream());
inStream = new DataInputStream(urlConnection.getInputStream());
// Send request
outStream.writeBytes(body);
outStream.flush();
outStream.close();
// Get Response
// - For debugging purposes only!
String buffer;
while((buffer = inStream.readLine()) != null) {
System.out.println(buffer);
}
// Close I/O streams
inStream.close();
outStream.close();
}
giving an error of:
Syntax error, insert "}" to complete ClassBody
Anybody see something obvious that I don't?
On a side note, if the php echoes back html code, upon running this class, is java capable of understanding the html code?
You can't put code directly in the class body - you have to wrap it inside a member function.
If this is intended to be a standalone program that member function should be:
public static void main(String[] args) {
...
}
If you want that code to be executed on construction of an instance of "Connect" you should put it in the constructor. This also fixes all of your errors.
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
public class Connect {
URL url;
URLConnection urlConnection;
DataOutputStream outStream;
DataInputStream inStream;
#SuppressWarnings("deprecation")
public Connect() {
// Build request body
try {
String body = "fname=" + URLEncoder.encode("Atli", "UTF-8");
// Create connection
url = new URL("http://192.168.1.68/test/POST/post.php");
urlConnection = url.openConnection();
((HttpURLConnection) urlConnection).setRequestMethod("POST");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
urlConnection.setRequestProperty("Content-Length", "" + body.length());
// Create I/O streams
outStream = new DataOutputStream(urlConnection.getOutputStream());
inStream = new DataInputStream(urlConnection.getInputStream());
// Send request
outStream.writeBytes(body);
outStream.flush();
outStream.close();
// Get Response
// - For debugging purposes only!
String buffer;
// DataInputStream.readLine is deprecated
// use the BufferedReader class instead
while ((buffer = inStream.readLine()) != null) {
System.out.println(buffer);
}
// Close I/O streams
inStream.close();
outStream.close();
} catch (IOException iOException) {
// there are many methods that can throw errors in this code,
// you should catch those errors
}
}
}