POST to Google Cloud Messaging with Retrofit - java

I am using HttpURLConnection for POST message to GCM like:
try {
URL url = new URL(GCM_SERVER_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key=" + apiKey);
conn.setDoOutput(true);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream());
mapper.writeValue(dataOutputStream, content);
dataOutputStream.flush();
dataOutputStream.close();
// Get the response
int responseCode = conn.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
And now i want to use Retrofit for POST message to GCM
I tried:
#Headers("Content-Type: application/json")
#FormUrlEncoded
#POST("/")
public GCMObject GCMAuthorization(#Header("Authorization") String apiKey,
#Body String data
);
I sent json string in data, But it always failed with this error:
#Body parameters cannot be used with form or multi-part encoding.
I did't found any solution, how can i fix it?

#FormUrlEncoded is used when you want to send form parameters. These parameters are encoded as the body, you can have your own. It does not look like you are using and form parameters, so remove #FormUrlEncoded. Also, I recommend using GSON to convert your POJO to JSON for the #Body. It looks like you are using retrofit 1 and trying to send a raw String. Retrofit will try to JSON encode that for you, which means you'll end up with the object you send wrapped in "...". If you want to send a raw string, take a look at this answer for your options in retrofit 1.

Related

How to get device Access token and perform multiple HTTP POST Request

I'm currently working on a project using an IoT platform " Thingsboard " where I've have created multiple devices, and I want to send data to each one of the devices from a JSON File, I'm using Rest Api to perform this request, but I've struggling for a while how to get the access token of my devices and parse each one of them in my request as a header param. I was just doing manually by getting them with Curl, but I want now to do it automatically. I know that Thingsboard has a Rest client Api written in java (https://thingsboard.io/docs/reference/rest-client/) so I've tried to use that in my script but I's not working. I'm new to working with Rest Api so if anybody can gie me a clue it would be so helpful.
here's a part of my code for the requests :
private static String token;
public String getToken() {
return token;
}
String paramValue = "param\\with\\backslash";
String yourURLStr = "http://host.com?param=" + java.net.URLEncoder.encode(paramValue, "UTF-8");
URL url2 = new URL("https://demo.thingsboard.io/api/v1/token/telemetry?token=$JWT_TOKEN");
HttpsURLConnection conn = (HttpsURLConnection) url2.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty(JWT_TOKEN_HEADER_PARAM, "Bearer" +token);
conn.setDoOutput(true);
OutputStream outStream = conn.getOutputStream();
OutputStreamWriter outStreamWriter = new OutputStreamWriter(outStream, "UTF-8");
outStreamWriter.write(list.toString());
outStreamWriter.flush();
outStreamWriter.close();
outStream.close();
String response = null;
System.out.println(conn.getResponseCode());
System.out.println(conn.getResponseMessage());
DataInputStream input1 = null;
input1 = new DataInputStream (conn.getInputStream());
while (null != ((response = input1.readLine()))) {
System.out.println(response);
input1.close ();
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
If you are trying to get the JWT-token to authenticate the following java should work:
Request request = Request.Post("http://THINGSBOARD_URL/api/auth/login");
String body = "{\"username\":\"tenant#thingsboard.org\", \"password\":\"tenant\"}";
request.bodyString(body,ContentType.APPLICATION_JSON);
request.setHeader("Content-Type", "application/json");
request.setHeader("Accept", "application/json");
HttpResponse httpResponse = request.execute().returnResponse();
System.out.println(httpResponse.getStatusLine());
if (httpResponse.getEntity() != null) {
String html = EntityUtils.toString(httpResponse.getEntity());
System.out.println(html);
}
Don't get confused with JWT-Token for tenant authentication and Access-Token for Device Authentication.

Send request body with GET request using HttpURLConnection in java

Kindly don't confuse my question with sending body with POST request using HttpURLConnection.
I want to send body with GET request using HttpURLConnection. Here is code i am using.
public static String makeGETRequest(String endpoint, String encodedBody) {
String responseJSON = null;
URL url;
HttpURLConnection connection;
try {
url = new URL(endpoint);
connection = (HttpURLConnection) url.openConnection();
connection.setInstanceFollowRedirects(true);
connection.setDoOutput(true);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.connect();
OutputStream outputStream = connection.getOutputStream();
outputStream.write(encodedBody.getBytes());
outputStream.flush();
Util.log(connection,connection.getResponseCode()+":"+connection.getRequestMethod());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String responseChunk = null;
responseJSON = "";
while ((responseChunk = bufferedReader.readLine()) != null) {
responseJSON += responseChunk;
}
bufferedReader.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
Util.log(e, e.getMessage());
}
return responseJSON;
}
what happens is that the request type is identified automatically depending on the connection.getInputStream() and connection.getOutPutStream().
when you call connection.getOutPutStream() the request type is automatically set to POST even if you have explicitly set request type to GET using connection.setRequestMethod("GET").
The problem is that i am using 3rd party Web Service(API) which accepts request parameters as body with GET request
<get-request>
/myAPIEndPoint
body = parameter1=value as application/x-www-form-urlencoded
<response>
{json}
I am well aware that most of the case GET don't have request body but many of the web service often uses GET request with parameters as body instead of query string. Kindly guide me how i can send GET request with body in android without using any 3rd party library(OkHttp,Retrofit,Glide etc)
use this code you will need to do a little modification but it will get the job done.
package com.kundan.test;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class GetWithBody {
public static final String TYPE = "GET ";
public static final String HTTP_VERSION = " HTTP/1.1";
public static final String LINE_END = "\r\n";
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 8080); // hostname and port default is 80
OutputStream outputStream = socket.getOutputStream();
outputStream.write((TYPE + "<Resource Address>" + HTTP_VERSION + LINE_END).getBytes());//
outputStream.write(("User-Agent: Java Socket" + LINE_END).getBytes());
outputStream.write(("Content-Type: application/x-www-form-urlencoded" + LINE_END).getBytes());
outputStream.write(LINE_END.getBytes()); //end of headers
outputStream.write(("parameter1=value&parameter2=value2" + LINE_END).getBytes()); //body
outputStream.flush();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
StringBuilder builder = new StringBuilder();
String read = null;
while ((read = bufferedReader.readLine()) != null) {
builder.append(read);
}
String result = builder.toString();
System.out.println(result);
}
}
this the Raw HTTP Request Dump
GET <Resource Address> HTTP/1.1
User-Agent: Java Socket
Content-Type: application/x-www-form-urlencoded
parameter1=value&parameter2=value2
Note : This is for http request if you want https Connection Please refer to the link SSLSocketClient

Java: read data sent by HTTP POST (Android AVD)

I use a simple WebServer from http://www.java2s.com/Code/Java/Network-Protocol/AverysimpleWebserverWhenitreceivesaHTTPrequestitsendstherequestbackasthereply.htm
and Android code from Sending json object via http post method in android
In my main Activity:
AsyncT asyncT = new AsyncT();
asyncT.execute();
Class:
class AsyncT extends AsyncTask<Void,Void,Void>{
#Override
protected Void doInBackground(Void... params) {
try {
URL url = new URL(""); //Enter URL here
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setDoOutput(true);
httpURLConnection.setRequestMethod("POST"); // here you are telling that it is a POST request, which can be changed into "PUT", "GET", "DELETE" etc.
httpURLConnection.setRequestProperty("Content-Type", "application/json"); // here you are setting the `Content-Type` for the data you are sending which is `application/json`
httpURLConnection.connect();
JSONObject jsonObject = new JSONObject();
jsonObject.put("para_1", "arg_1");
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
wr.writeBytes(jsonObject.toString());
wr.flush();
wr.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
The connection is established without any errors ("HostConnection::get() New Host Connection established"). However, I am not able to get in my Java server any information from the request. When I read from input stream
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
System.out.println(in);
I get java.io.BufferedReader#4d7hge12
And this outputs nothing:
String line;
while ((line = in.readLine()) != null) {
if (line.length() == 0)
break;
System.out.println(line);
}
Don't re-invent the wheel and use a library for this.
For example okhttp:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
If you want to call a REST-API you can use retrofit (which is build ontop of okhttp)
Assuming you're doing this as a learning exercise, so using another library isn't what you're looking for, I would suggest a couple of things:
(1) install Wireshark and see what the actual response coming back the server is, does it look sensible?
(2) break that line of code out into separate lines, is the InputStream / InputStreamReader null?

Setting custom header using HttpURLConnection

I am simply making a GET request to a Rest API using HttpURLConnection.
I need to add some custom headers but I am getting null while trying to retrieve their values.
Code:
URL url;
try {
url = new URL("http://www.example.com/rest/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// Set Headers
conn.setRequestProperty("CustomHeader", "someValue");
conn.setRequestProperty("accept", "application/json");
// Output is null here <--------
System.out.println(conn.getHeaderField("CustomHeader"));
// Request not successful
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new RuntimeException("Request Failed. HTTP Error Code: " + conn.getResponseCode());
}
// Read response
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuffer jsonString = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
jsonString.append(line);
}
br.close();
conn.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
What am I missing?
It is a good idea to send
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("CustomHeader", token);
instead of
// Set Headers
conn.setRequestProperty("CustomHeader", "someValue");
conn.setRequestProperty("accept", "application/json");
Both the type value and header should be changed.
it works in my case.
The conn.getHeaderField("CustomHeader") returns the response header not the request one.
To return the request header use: conn.getRequestProperty("CustomHeader")

Java Post Request Not Working

Why does this not work? I have also tried using HttpURLConnection class however this did not work either. The php page cannot find the posted data.
Note: im new to post requests with java.
public static String GetURL(String inUrl, String post) {
String inputLine = "";
try {
if (!inUrl.contains("http")) {
throw new Exception("Invalid URL");
} else {
Log.writeLog(inUrl);
URL url = new URL(inUrl);
//send post
URLConnection connection = url.openConnection();
//connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
connection.connect();
OutputStream wr = connection.getOutputStream();
wr.write(post.getBytes());
wr.flush();
wr.close();
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
inputLine = in.readLine();
in.close();
}
} catch (Exception ex) {
ex.printStackTrace();
Log.writeLog("Error getting url.");
}
return inputLine;
}
Since you didn't specify the error, it is hard for me to see where you went wrong.
However, I think it would be a lot easier to use an abstraction like HttpClient. Your code would look like this:
URI uri = new URIBuilder()
.setURI(inUrl)
.addHeader("Accept-Charset", "UTF-8")
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(post);
Much cleaner than dealing with the low-level details of streams and connections.

Categories