How to make a PUT request using HttpURLConnection with query parameters?
I am trying to consume a third party REST API using HttpURLConnection but when I try to pass the parameters in the URL, it doesn't work and throw an error as shown below:
The REST API Url could not be found in the mappings registry
This is the code block that doesn't work for me as of now:
URL url;
StringBuffer response = new StringBuffer();
try
{
url = new URL(" http://thirdparty.com/party/api/v2/ksp/12/ks");
HttpURLConnection httpURL = (HttpURLConnection) url.openConnection();
httpURL.setDoOutput(true);
httpURL.setRequestMethod("PUT");
StringBuilder sbUrl = new StringBuilder("parameter1_id=");
sbUrl.append(getParameter1Value())
.append("¶meter2_id=")
.append(getParameter2Value());
final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(httpURL.getOutputStream()));
writer.write(sbUrl.toString());
writer.flush();
writer.close();
// throw the exception here in case invocation of web service
if (httpURL.getResponseCode() != 200)
{
// throw exception
}
else
{
//SUCCESS
}
}
catch (IOException e)
{
}
When I provide these parameters in the Body as form-data parameters, the REST API seems provide the response.
My question here is that how do I make this work with HttpURLConnection?
What have I tried till now?
I have tried to modify the above to something like below, but it doesn't work.
try
{
url = new URL(" http://thirdparty.com/party/api/v2/ksp/12/ks");
HttpURLConnection httpURL = (HttpURLConnection) url.openConnection();
httpURL.setDoOutput(true);
httpURL.setRequestMethod("PUT");
httpURL.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + "----WebKitFormBoundarydklhfklsdfhlksh");
dataOutputStream = new DataOutputStream(urlConnection.getOutputStream());
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"parameter1_id\"");
dataOutputStream.writeBytes("\r\n" + "parameter1Value" +"\r\n");
dataOutputStream.writeBytes("--" + "----WebKitFormBoundarydklhfklsdfhlksh");
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"parameter2_id\"");
dataOutputStream.writeBytes("\r\n" + "parameter2Value" + "\r\n");
dataOutputStream.writeBytes("--" + "----WebKitFormBoundarydklhfklsdfhlksh" + "--");
dataOutputStream.flush();
dataOutputStream.close();
urlConnection.connect();
// throw the exception here in case invocation of web service
if (httpURL.getResponseCode() != 200)
{
// throw exception
}
else
{
//SUCCESS
}
}
catch (IOException e)
{
}
EDIT: It throws an error with response code as 500
EDIT: Just to clarify, I'm not trying to upload a file but trying to send the parameters inside the BODY (like Query parameters instead of being sent as URL parameters).
Any pointers or suggestions on this are very much appreciated.
You talk about 'query parameters' and 'parameters in the URL', but neither of the approaches you show does any such things. Both your approaches (try to) send parameters in the request body, aka 'entity', not in the URL. Although body contents may be involved in an application-level query, they are NOT query string aka query parameters at the HTTP level. You also ask 'how do I make this work with HttpURLConnection' as if that were a change or difference when both your attempts already use it.
Your first attempt looks almost correct. It should work if
you .setRequestProperty("Content-type", "application/x-www-form-urlencoded") (which is not automatic) and your values either are URLencoded or don't need it (no reserved characters) (depending on the server it may be enough to have no ampersand or equalsign)
Your second attempt also is fairly close. You need to write a boundary before the first part as well, and for each part after Content-disposition: form-data; name="blah" you need one CRLF to end that header line and a second CRLF to end the header block. (MIME multipart format allows multiple header lines in general, although in this case only one is needed.) And the end boundary should be followed by a CRLF (after the extra --).
Both only if you have the URL correct, of course. Nothing will work without the correct URL.
Best Method to Call WebService with HttpUrlConnection PUT Method
ApiListener apilistener=null;
public void updateWorker()
{
progressDialog = ProgressDialog.show(myContext, "Message",
progressDialog.setCancelable(false);
progressDialog.setCanceledOnTouchOutside(false);
Thread runThread = new Thread(new Runnable() {
#Override
public void run() {
HttpAppRequest http = new HttpAppRequest();
try {
JSONObject paramObject = new JSONObject();
JSONObject dataObject = new JSONObject();
dataObject.put("id", csId);
}
paramObject.put("data", dataObject);
Log.e(AppConstants.TAG, "Param = " + paramObject.toString());
AppResponse response = http.putJSONData(BASE_URL + "/updateapi", paramObject.toString(), true);
if (response.getStatusCode() == 200) {
String csUpdateResult = response.getContentData();
Log.e(AppConstants.TAG, csUpdateResult);
JSONObject updateObject = new JSONObject(csUpdateResult);
Message completeMessage = handler.obtainMessage(1, updateObject);
completeMessage.sendToTarget();
} else {
handler.sendEmptyMessage(-1);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String csMessage = myContext.getResources().getString(R.string.id_network_response_failure);
Message completeMessage = handler.obtainMessage(0, csMessage);
completeMessage.sendToTarget();
}
}
});
runThread.start();
}
/*******************************************************************************************************/ Handler Api Response Here
Handler handler= new Handler() {
#Override
public void handleMessage(Message inputMessage) {
progressDialog.dismiss();
if (inputMessage.what == 1) {
try {
JSONObject msgObject = (JSONObject) inputMessage.obj;
if (msgObject.has("result")) {
JSONObject resultObject = msgObject.getJSONObject("result");
if (resultObject.has("status")) {
String csStatus = resultObject.getString("status");
if (csStatus.equalsIgnoreCase("success")) {
apilistener.onUpdate(resultObject.getString("msg"));
}
} else {
if(resultObject.has("status"))
{
apilistener.onFailed(resultObject.getString("reason"));
}
}
}
} catch (JSONException e) {
CommonMethods.showMessageBox("", e.getMessage(), myContext);
}
} else if (inputMessage.what == 0) {
String csMessage = (String) inputMessage.obj;
CommonMethods.showMessageBox("", csMessage, myContext);
}
}
};
//CallBack Listener to parent Activity/Fragment
//User listener like this
public interface ApiListener extends EventListener
{
void onSuccess(String msg);
void onFaiulure(String msg);
}
public void setListener(ApiListener listener)
{
apilistener=listener;
}
}
Related
So my question is how can I create a DELETE Request to an URL in Android Studio Java. I already have an Async Task which GET json from URL. So my question now is how can I create a DELETE request
EDIT:
So right now I got this code:
int pos = arrlist.get(info.position).getId();
URL_DELETE = "http://testserver/test/tesst.php?id=" + pos + "&username=" + username + "&password=" + password;
URL url = null;
try {
url = new URL(URL_DELETE);
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setDoOutput(true);
httpCon.setRequestProperty(
"Content-Type", "application/x-www-form-urlencoded" );
httpCon.setRequestMethod("DELETE");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
To understand the content of the given URL should be deleted. But if I run the code nothing happens.
You need to call connect() on the HttpURLConnection. Right now you're not actually making a connection to the server.
Based on your comments on the other answer, you're also trying to run this code on the main (UI) thread - you'll need to change your code to run on a background thread.
If you're using OkHttp:
Request request = new Request.Builder().delete().url(url).build();
Response rawResponse = null;
try {
rawResponse = new OkHttpClient().newCall(request).execute();
} catch (IOException e) {
System.err.println(e.getMessage());
}
String responseAsString = rawResponse.body().string();
I have write a simple method to post data to URL and consume the output. I hava tried multiple ways to consume the out put but no success yet:
public void postToUrl(final String theurl, final String query, final Callable<Void> myMethod){
String urlData="";
new Thread(new Runnable() {
#Override
public void run() {
try {
String urlData="";
String url=baseurl+ theurl + "/?" +query;
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true);
connection.connect();
InputStream response = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(response));
String line="";
while ((line = reader.readLine()) != null) {
urlData += line;
}
reader.close();
// How to consume urlData here?
// myMethod.call(); not accepts parameter
try {
myMethod.call(urlData);
}catch (Exception e){
e.printStackTrace();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}}
).start();
}
I have to wrap the method inside a runnable and can not expect a runnable method to return a value.
I tried to consume the output when it is ready inside the runnable but I need to call a third party method to pass the output. I found callable but it does not accept parameters.
I have read the accepted answer here but it needs to define a new class for every method.
I have read this Q/A but it suggest to define an interface instead of method that I believe is not the proper use of interface.
If this method is not the proper way to call and consume a url, how do you manage multiple client-server request in an application? Do you rewrite the codes above for every type of request? Do you really define a new class or new interface for every clien-server interactions?
I'm building a project in which I want a method to make a simple http GET request in order to send two variables to an website via URL.
In a normal java project I would likely use java.net or apache and solve the issue in a matter of minutes. In JavaME, due to my lack of experience I'm not really being able to fulfill the task.
Basically what I want to do is having an url like google.com/index.php?v1=x&v=y
being able to do a get request in order to send those variables via URL.
Any tips?
Here's an example of how you could do something like that.
HttpConnection connection = null;
InputStream inputstream = null;
String url = null;
StringBuffer dataReceived = null;
url = "http://www.google.com/index.php?v1=x&v=y";
dataReceived = new StringBuffer();
try {
connection = (HttpConnection) Connector.open(url);
connection.setRequestMethod(HttpConnection.GET);
connection.setRequestProperty("Content-Type", "text/plain");
connection.setRequestProperty("Connection", "close");
if (connection.getResponseCode() == HttpConnection.HTTP_OK) {
inputstream = connection.openInputStream();
int ch;
while ((ch = inputstream.read()) != -1 ) {
dataReceived.append((char) ch);
}
} else {
// Connection not ok
}
} catch (Exception e) {
// Something went wrong
} finally {
if (inputstream != null) {
try {
inputstream.close();
} catch (Exception e) {
}
}
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
}
}
}
Note: I didn't test this specific code. I just edited some code I had lying around from a previous project of mine, so you may need to fix a few errors.
I have an android app that most of its feature consumes an API. My client complained that the retrieving of data from the web api is very slow. I wonder what's causing this.
Here's a basic structure of how I do my calls:
String returnString = "";
token = tokenBuilder.generateToken("Customers/All");
try {
HttpGet request = new HttpGet(apiUrl + "CustomerRewards/All?customerId=" + id);
request.setHeader(HTTP.CONTENT_TYPE, "application/json");
request.setHeader("AccountId", headerAccountId);
request.setHeader("StoreId", headerStoreId);
request.setHeader("AppKey", headerAppKey);
request.setHeader("Token", token);
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(request);
String responseString = EntityUtils.toString(response.getEntity());
Log.i("Api Message", responseString);
returnString = responseString;
} catch (Exception e) {
returnString = e.getMessage();
}
return returnString;
I'm calling this method from a progress dialog in order to display a loader while, retrieving data from the web API. Is there a better way to do this? Or is somewhat my android code affects its performance?
Here's the code on the calling progress dialog.
rewardsErrorMessage = "";
progressBar = new ProgressDialog(this);
progressBar.setCancelable(true);
progressBar.setMessage("Loading info ...");
progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressBar.setProgress(0);
progressBar.setMax(100);
progressBar.setCancelable(false);
progressBar.show();
apiLoadStatus = false;
new Thread(new Runnable() {
public void run() {
while (!apiLoadStatus) {
apiLoadStatus = RewardApi();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (apiLoadStatus) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
progressBar.dismiss();
}
}}).start();
progressBar.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
SetValues();
}
});
And here's the method that actually calls the api class that connects to the web api
ApiConnection api = new ApiConnection();
try {
Log.i("CustomerId", customerInfos.getString("customer_id", ""));
transactionMessage = api.GetTransactions(customerInfos.getString("customer_id", ""));
availableRewardsMessage = api.GetCustomerRewards(customerInfos.getString("customer_id", ""));
try
{
if(transactionMessage.contains("Timestamp"))
{
Log.i("Transaction", "Success");
GetPoints(transactionMessage);
}
if(!availableRewardsMessage.equals("[]") && !availableRewardsMessage.equals("[]"))
{
JSONObject rewardsJson = new JSONObject(availableRewardsMessage);
availableRewardsMessage = rewardsJson.getString("AvailableRewards");
hasRewards = true;
}
return true;
}
catch(Exception e)
{
rewardsErrorMessage = transactionMessage.replace('[', ' ').replace(']', ' ').replace('"', ' ');
}
} catch(Exception e) {
e.printStackTrace();
rewardsErrorMessage = e.getMessage();
return true;
}
return true;
As you notice, I have two api calls here.
I really would like to speed up the retrieving of data. Or is the api I'm consuming that slow? Any ideas guys? Thanks!
As you're probably aware, there are a number of factors that can affect HTTP service calls, of which the client code is only one:
Network speed and latency
Server availability and load
Size of data payload
Client device resources
Client code
You really need to determine where the bottleneck(s) are in order to know where to try to optimize. Additionally, you should make sure that the server is using Gzip to compress the payload and add the following to your client code:
request.setHeader("Accept-Encoding", "gzip");
I am trying to write a Java program that should automatically download text from a website if and only if it gets updated. The problem I am running into is using only one HTTPURLConnection to do that because if i don't there will be billions of HTTPURLConnections to the web server since I am using a while(true) loop. Here is my work-in-progress, the getMsg() method receives a url and opens an HTTPURLConnection. Currently I am starting a new connection every time I have to read a line, which is not the most efficient way I am sure. How do I keep reading the same line with the same HTTPURLConnection?
// Starts a new URLConnection to "localhost/currentmsg.dat"
// Receives JSON string from the URLConnection
// Sets up a different variable for each object received from the URL for eg. if delete=1 means that the admin is requesting to delete a message from the screen.
import java.io.*;
import java.net.*;
import org.json.*;
import java.io.*;
import java.util.Scanner;
public class jListenerURL {
// Current arguments retrieved from the URL
private static int msgID = 0;
private static int aptID = 1; // Apartment ID of current device
private static int unitID = 3; // Unit ID of current device
static String message; // Message received from admin
static int delete; // Delete a message?
static int dmsgID; // What message to delete?
public static void jListener() {
URL url;
boolean keepGoing = true;
String msg = "";
try {
url = new URL("http://www.lotussmoke.com/msgtest/currentmsg.dat");
while (keepGoing) {
msg = getMsg(url);
JSONObject jObj = null;
try {
jObj = new JSONObject(msg);
}
catch (JSONException je) {
System.out.println("JSON Exception for message, try restarting terminal.");
}
int current = jObj.getInt("msgID");
int targetaptID = jObj.getInt("aptID");
int targetunitID = jObj.getInt("unitID");
// Keep listening, if the message changes meaning a different msgID then print that message
if (current!=msgID && targetaptID == aptID && targetunitID == unitID) {
msgID = jObj.getInt("msgID");
message = jObj.getString("message");
delete = jObj.getInt("delete");
dmsgID = jObj.getInt("dmsgID");
if (delete==1) {
// Delete a message
System.out.println("Delete msg ID? " + dmsgID);
continue;
}
System.out.println("Message ID: " + msgID);
System.out.println("Apartment ID: " + aptID);
System.out.println("Unit ID: " + unitID);
System.out.println("Message: " + message);
}
}
}
catch (MalformedURLException e) {
System.err.println();
}
}
public static void main(String args[]) throws Exception {
jListener();
}
private static String getMsg(URL url) {
HttpURLConnection con = null;
try {
con = (HttpURLConnection) url.openConnection();
} catch (IOException e1) {
e1.printStackTrace();
}
BufferedReader in = null;
String msg = "";
try {
in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String received;
while((received = in.readLine()) != null) {
//System.out.println(received);
msg = received;
}
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
return msg;
}
}
Why don't you simply declare your HttpURLConnection object outside of your while loop ? It will then not open a connection at each call inside the loop.
HttpURLConnection cannot be reused, but it can reuse an open connection to the same server internally by setting the header Connection: keep-alive. It doesn't make sense if you connect to different servers, obviously.
One way to efficiently test whether there are changes, is to use If-Modified-Since header or the like If-Unmodified-Since, If-None-Match or If-Match (see HTTP Headers). In this case the web-server decides to deliver a new document if there are changes or just sends the response code 304 Not Modified without a body.
One last thing regarding the use of members (and especially static members): I'd refactor this code and the only item which would be left as static is static void main(). You can see the static members as some kind of global variables. Observing something like 'the connection is returning the same message' might be a effect of inappropriate exception handling and usage of static members.