I am attempting to send a user update to valance and I am looking for an example of how to do a put, specifically, a put to update a user.
I have looked around but do not see an example of how to use the UserContext to send a json block using Java.
Any pointers to documentation would be appreciated.
After tinkering with this, and with a great number of suggestions from my colleague (Who I am not sure wants to be identified so i will just call him Bill). We came up with the following Java method(should really be split into separate methods but it is understandable)
private static String getValanceResult(ID2LUserContext userContext,
URI uri, String query, String sPost, String sMethod, int attempts) {
String sError = "Error: An Unknown Error has occurred";
if (sMethod == null) {
sMethod = "GET";
}
URLConnection connection;
try {
URL f = new URL(uri.toString() + query);
//connection = uri.toURL().openConnection();
connection = f.openConnection();
} catch (NullPointerException e) {
return "Error: Must Authenticate";
} catch (MalformedURLException e) {
return "Error: " + e.getMessage();
} catch (IOException e) {
return "Error: " + e.getMessage();
}
StringBuilder sb = new StringBuilder();
try {
// cast the connection to a HttpURLConnection so we can examin the
// status code
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod(sMethod);
httpConnection.setConnectTimeout(20000);
httpConnection.setReadTimeout(20000);
httpConnection.setUseCaches(false);
httpConnection.setDefaultUseCaches(false);
httpConnection.setDoOutput(true);
if (!"".equals(sPost)) {
//setup connection
httpConnection.setDoInput(true);
httpConnection.setRequestProperty("Content-Type", "application/json");
//execute connection and send xml to server
OutputStreamWriter writer = new OutputStreamWriter(httpConnection.getOutputStream());
writer.write(sPost);
writer.flush();
writer.close();
}
BufferedReader in;
// if the status code is success then the body is read from the
// input stream
if (httpConnection.getResponseCode() == 200) {
in = new BufferedReader(new InputStreamReader(
httpConnection.getInputStream()));
// otherwise the body is read from the output stream
} else {
in = new BufferedReader(new InputStreamReader(
httpConnection.getErrorStream()));
}
String inputLine;
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
in.close();
// Determine the result of the rest call and automatically adjusts
// the user context in case the timestamp was invalid
int result = userContext.interpretResult(
httpConnection.getResponseCode(), sb.toString());
if (result == ID2LUserContext.RESULT_OKAY) {
return sb.toString();
// if the timestamp is invalid and we haven't exceeded the retry
// limit then the call is made again with the adjusted timestamp
} else if (result == userContext.RESULT_INVALID_TIMESTAMP
&& attempts > 0) {
return getValanceResult(userContext, uri, query, sPost, sMethod, attempts - 1);
} else {
sError = sb + " " + result;
}
} catch (IllegalStateException e) {
return "Error: Exception while parsing";
} catch (FileNotFoundException e) {
// 404
return "Error: URI Incorrect";
} catch (IOException e) {
}
return sError;
}
There is a php code snippet I can share from a project that uses the api (same rough logic with java). The User context just prepares the url and the framework of the specific environment (java runtime, or php library) is used to do the post and retrieve the results (in this case it is using php CURL).
$apiPath = "/d2l/api/le/" . VERSION. "/" . $courseid . "/content/isbn/";
$uri = $opContext->createAuthenticatedUri ($apiPath, 'POST');
$uri = str_replace ("https", "http", $uri);
curl_setopt ($ch, CURLOPT_URL, $uri);
curl_setopt ($ch, CURLOPT_POST, true);
$response = curl_exec ($ch);
$httpCode = curl_getinfo ($ch, CURLINFO_HTTP_CODE);
$contentType = curl_getinfo ($ch, CURLINFO_CONTENT_TYPE);
$responseCode = $opContext->handleResult ($response, $httpCode, $contentType);
$ret = json_decode($response, true);
if ($responseCode == D2LUserContext::RESULT_OKAY)
{
$ret = "$response";
$tryAgain = false;
}
elseif ($responseCode == D2LUserContext::RESULT_INVALID_TIMESTAMP)
{
$tryAgain = true;
}
elseif (isset ($ret['Errors'][0]['Message']))
{
if ($ret['Errors'][0]['Message'] == "Invalid ISBN")
{
$allowedOrgId[] = $c;
}
$tryAgain = false;
}
A sample of a trace of a post message is:
PUT https://valence.desire2learn.com/d2l/api/lp/1.0/users/3691?x_b=TwULqrltMXvTE8utuLCN5O&x_a=L2Hd9WvDTcyiyu5n2AEgpg&x_d=OKuPjV-a0ZoSBuZvJkQLpFva2D59gNjTMiP8km6bdjk&x_c=UjCMpy1VNHsPCJOjKAE_92g1YqSxmebLHnQ0cbhoSPI&x_t=1336498251 HTTP/1.1
Accept-Encoding: gzip,deflate
Accept: application/json
Content-Type: application/json
{
"OrgDefinedId": "85033380",
"FirstName": "First",
"MiddleName": "Middle",
"LastName": "Last",
"ExternalEmail": "me#somehostname.com",
"UserName": "Username",
"Activation": {
"IsActive": true
}
}
Related
I am trying to make api call every 60 mins which returns json response like below:
[{
"queryId" : uniqueID,
"state": "FINISHED | FAILED | RUNNING"
},
{
"queryId" : uniqueID,
"state": "FINISHED | FAILED | RUNNING"
},
]
I want to run first time and prepare each document and store and for the next api call i want to compare current response with previous response with below condition:
1: if same queryId exit in previous response and state as FINISHED | FAILED don't consider to store.
So idea is to get every 60 secs new queryID which is running in system and store it for further analysis.
Below is my sample snipeet:
#Override
public void run() {
stopRequested = false;
while (!stopRequested)
{
try {
System.setProperty("javax.net.ssl.trustStore","");
System.setProperty("javax.net.ssl.trustStorePassword","");
Authenticator.setDefault (new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication ("", "".toCharArray());
}
});
URL url = new URL("");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
conn.connect();
int responsecode = conn.getResponseCode();
if (responsecode != 200) {
throw new RuntimeException("HttpResponseCode: " + responsecode);
}
try(BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine = null;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
JSONArray array = new JSONArray(response.toString());
System.out.println(array.length());
JSONArray presResponse = array;
for(int i=0; i < array.length(); i++)
{
JSONObject object = array.getJSONObject(i);
// Query
String queryId = object.getString("queryId");
String state = object.getString("state");
if (checkQryExit(queryId, state, presResponse)) {
String strResponse = String.format // metric return in json
("{\"queryId\":\"%s\"," + "\"state\":\"%s\"}", queryId, state);
System.out.println(strResponse);
}
}
} catch (Exception e) {
e.printStackTrace();
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I am calling a PHP script from a function like this:
public static String XSSignUp(String username, String password, String email, String signInWith) {
// Paramenters
Map<String, Object> params = new LinkedHashMap<>();
params.put(USERS_USERNAME, username);
params.put(USERS_PASSWORD, password);
params.put(USERS_EMAIL, email);
params.put("signInWith", signInWith);
params.put(USERS_IOS_DEVICE_TOKEN, IOS_DEVICE_TOKEN);
params.put(USERS_ANDROID_DEVICE_TOKEN, ANDROID_DEVICE_TOKEN);
StringBuilder postData = new StringBuilder();
for (Map.Entry<String, Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
try { postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
} catch (UnsupportedEncodingException e) { e.printStackTrace(); }
postData.append('=');
try { postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
} catch (UnsupportedEncodingException e) { e.printStackTrace(); }
}
byte[] postDataBytes;
postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
URL url;
url = new URL(TABLES_PATH + "m-signup.php?");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(20000);
conn.setReadTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
// Get response
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream responseStream = new BufferedInputStream(conn.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null) { stringBuilder.append(line).append("\n"); }
responseStreamReader.close();
String response = stringBuilder.toString();
responseStream.close();
conn.disconnect();
Log.i(TAG, "XSSignUp -> RESPONSE: " + response + "\n-----------------\n");
if (response.equals("e_101")) { return E_101;
} else if (response.equals("e_102")) { return E_102;
} else { return response; }
// error
} else { return "Something went wrong. Try again."; }
} catch (IOException e) { e.printStackTrace(); return e.getMessage(); }
}
This is how I call that function:
final String sup = XSSignUp(usernameTxt.getText().toString(), passwordTxt.getText().toString(), emailTxt.getText().toString(), "");
Log.i(TAG, "SUP: " + sup);
// errors
if (sup.matches("e_101")) {
hideHUD();
simpleAlert(E_101, ctx);
} else if (sup.matches("e_102")) {
hideHUD();
simpleAlert(E_102, ctx);
} else {
Log.i(TAG, "YES, SIGN UP!");
}
So, if I run my app and fill a signup form using johndoe as username, my PHP script returns a response string as "e_101" (username already exists), and it prevents the script to add records to my database. I get this message in the Logcat:
I/log-: XSSignUp -> RESPONSE: e_101
I/log-: SUP: e_101
I/log-: YES, SIGN UP!
Which is wrong, because I shouldn't get the last line: I/log-: YES, SIGN UP!.
This compromises my app because instead of firing an alert dialog (simpleAlert(E_101, ctx);), it goes on and skips that part.
I don't really understand why the IF statement doesn't work, because I've also tried to do this:
final String sup = XSSignUp(usernameTxt.getText().toString(), passwordTxt.getText().toString(), emailTxt.getText().toString(), "");
sup = "e_101"; <-- FORCING THE sup STRING TO BE "e_101"!
// errors
if (sup.matches("e_101")) {
hideHUD();
simpleAlert(E_101, ctx);
} else if (sup.matches("e_102")) {
hideHUD();
simpleAlert(E_102, ctx);
} else {
Log.i(TAG, "YES, SIGN UP!");
}
and then it works! But it doesn't make any sense to me since the sup string is the same as the one that my function returns from the PHP script, as you can see by the Logcat messages...
I've also tried using equals():
sup.equals("e_101")
No positive result, so what am I doing wrong?
Your response contains extra new line \n, that's why if not work.
The problem is in here:
stringBuilder.append(line).append("\n");
Try to change it like below:
int i = 0;
while ((line = responseStreamReader.readLine()) != null) {
if(i != 0)
stringBuilder.append("\n");
stringBuilder.append(line);
i++;
}
Or
....
stringBuilder.replace(stringBuilder.lastIndexOf("\n"), stringBuilder.length(),"");
String response = stringBuilder.toString();
Beside this as you change the CASE of your response to upper inside XSSignUp and compare with lower CASE outside, you have to use equalsIgnoreCase instead of equals like
sup.equalsIgnoreCase("e_101")
Hi where to convert a json using node.js, to do it using body-parser with the code entered below: I am generated the error below. What is this error due to? how can I solve it? At the bottom I added the front-end java code for sending the json! The strange thing is that the -Note- field is not displayed in the request.body
Error --> console.log(request.body):
'{"Articoli":':
{ '{"Codice":"VAS-100","Descrizione":"SCHEDA DI ANALISI AD 1 INGRESSO \/ 1 USCITA ALLARME","Prezzo":"35.0"}': '' } }
Error SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
Node.js:
const express = require("express");
const myParser = require("body-parser");
const http = require('http');
const app = express();
app.use(myParser.json());
app.use(myParser.urlencoded({ extended: true }));
//port
const RunPort=8989;
//server run on port
app.listen(RunPort, function () {
console.log("Server run on Port: ",RunPort);
})
app.post("/rapportini/generarapportino", async function (request, response) {
try {
console.log(request.body);
var data = JSON.parse(Object.keys(request.body)[0]);
const ret = await RapportiniController.GeneraRapportino(data.Note);
response.setHeader('Content-Type', 'application/json');
response.send(JSON.stringify({
return: ret
}));
} catch (err) {
console.log("Error ", err)
}
});
JSON:
{
"Note": "some note",
"Articoli":[{
"Codice": "CodiceValue 1",
"Descrizione": "DescrizioneValue 1",
"Presso": "Prezzo 1"
},
{
"Codice": "CodiceValue 2",
"Descrizione": "DescrizioneValue 2",
"Presso": "Prezzo 2"
}]
}
Front-End Java Code(Android):
Generate JSON:
String ret = "";
try {
JSONObject obj = new JSONObject();
obj.put("Note", note);
JSONArray objarticoli = new JSONArray();
int size = articoli.size();
int i = 0;
System.out.println("\n Size of articoli: " + size);
for (i = 0; i <
size; i++) {
JSONObject artItem = new JSONObject();
artItem.put("Codice", articoli.get(i).GetCodice().toString());
artItem.put("Descrizione", articoli.get(i).GetDescrizione().toString());
artItem.put("Prezzo", articoli.get(i).GetPrezzo().toString());
objarticoli.put(artItem);
}
obj.put("Articoli", objarticoli);
try {
Database db = new Database();
ret = db.RequestArray("/rapportini/generarapportino", obj, true);
} catch (Exception ex) {
System.out.println("\n Errore login Model");
}
} catch (Exception ex) {
ErrorManagement.SendError("Errore: Generazione Rapportino: " + ex);
}
return ret;
Send of JSON:
String response = "";
System.out.println("\n Sono in GetResponse con JSONOject: "+object);
try {
URL url = new URL("/rapportini/generarapportino");
byte[] postDataBytes = object.toString().getBytes("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);
Reader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder();
for (int c; (c = in.read()) >= 0; ) {
sb.append((char) c);
}
response = sb.toString();
} catch (Exception ex) {
System.out.println("\n Errore funzione GetResponse class JSONRequest: "+ex);
}
return response;
First Use JSON.stringify then parse it to get desired output
var req={ '{"Articoli":': { '{"Codice":"KSI4101000.300","Descrizione":"gemino Bus Scheda GSM\/GPRS (solo PCBA) solo per KS-BUS","Prezzo":"163.35"}': '' } }
var data = JSON.parse(JSON.stringify(req));
You need to set correct Content-Type in Android application that is application/json
conn.setRequestProperty("Content-Type", "application/json");
and then accept in NodeJS application
app.post("/rapportini/generarapportino", async function (request, response) {
try {
const ret = await RapportiniController.GeneraRapportino(request.body.Note);
response.json({
return: ret
});
} catch (err) {
console.log("Error ", err)
}
});
I'm trying to connect an Android app to a restful server with HttpURLConnection. The GET requests are successful but the PUT requests aren't. Every PUT request arrives at the server as a GET request.
#Override
protected Boolean doInBackground(Method... params) {
Boolean result = false;
try {
URL url = new URL("http://server.com/api");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
switch (params[0]) {
case PUT:
connection.setDoOutput(true);
connection.setRequestMethod("PUT");
Log.d(TAG, "Method: " + connection.getRequestMethod()); // Correctly "Method: PUT"
OutputStreamWriter out = new OutputStreamWriter(
connection.getOutputStream());
out.write("Message");
out.close();
break;
case GET:
connection.setRequestMethod("GET");
connection.connect();
break;
default:
connection.setRequestMethod("GET");
connection.connect();
break;
}
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream in = connection.getInputStream();
JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("state")) {
result = true;
if (reader.nextInt() == 1) {
state = true;
Log.d(TAG, "state: 1");
} else {
state = false;
Log.d(TAG, "state: -1");
}
} else if (name.equals("method")) {
method = reader.nextString(); // Server respone is "Method: GET"
}
}
reader.endObject();
in.close();
} else {
Log.d(TAG, "Connection failed");
}
connection.disconnect();
} catch (Exception e) {
Log.e("Exception", e.toString());
e.printStackTrace();
}
return result;
}
The request method is correctly set to PUT before connection.connect();. What am I missing? I don't want to send data. The PUT request changes a counter, so no data is necessary.
Same function is implemented in Javascript with JQuery for a webfrontend and works
$.ajax({
url: '/api',
method: 'PUT'
});
EDIT:
Maybe it's a problem with the server. Currently I'm using an php file
<?php
echo(var_dump($_SERVER)); // ["REQUEST_METHOD"]=> string(3) "GET"
function get ($db) {
$state = $db->querySingle('SELECT state FROM states WHERE name="main"');
echo('{"state": ' . $state . ', "method": "get"}');
}
function put ($db) {
$state = $db->querySingle('SELECT state FROM states WHERE name="main"');
$db->exec('UPDATE states SET state=' . ($state+1)%2 . ' WHERE name="main"');
$state = $db->querySingle('SELECT state FROM states WHERE name="main"');
echo('{"state": ' . $state . ', "method": "put"}');
}
if ($db = new SQLite3('database.sqlite')) {
switch($_SERVER['REQUEST_METHOD']){
case 'GET':
get($db);
break;
case 'PUT':
put($db);
break;
}
$db->close();
} else {
}
?>
I tried my app with http://httpbin.org/put and it worked.
I found the problem. I have to append a trailing slash to the url otherwise the request is redirected and transformed to a GET request. I don't exactly understand the problem but I found a solution for me.
I have to change
URL url = new URL("http://server.com/api");
to
URL url = new URL("http://server.com/api/");
And now it works. Maybe someone can explain it to me. When I try to open http://server.com/api with curl I get a 303 redirect to http://server.com/api.
I am using HttpUrlConnection and using POST method to get some data from web server. Sometimes, I get the response and at times I get EOFexception
These are the solutions are I have already tried :
1) System.setProperty("http.keepAlive", "false");
2) if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
connection.setRequestProperty("Connection", "close");
}
Below is my code from AsyncTask class;
CODE :
#Override
protected JSONObject doInBackground(KeyValuePair... keyValuePairs) {
JSONObject jsonResponse = new JSONObject();
HttpURLConnection connection = null;
// check if is Internet is available before making a network call
if (isInternetAvailable()) {
try {
jsonResponse = new JSONObject();
URL url = new URL(urlStr);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setUseCaches(false);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("charset", "UTF-8");
if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
connection.setRequestProperty("Connection", "close");
}
// setting post params
StringBuilder builder = new StringBuilder();
for (int i = 0; i < keyValuePairs.length; i++) {
builder.append(URLEncoder.encode(keyValuePairs[i].getKey(), "UTF-8") + "=" + URLEncoder.encode(keyValuePairs[i].getValue(), "UTF-8") + "&");
GeneralUtils.print("key : " + keyValuePairs[i].getKey() + ", value : " + keyValuePairs[i].getValue());
}
String postData = builder.toString();
postData = postData.substring(0, postData.length() - 1);
GeneralUtils.print("postData " + postData);
byte[] postDataByteArr = postData.getBytes();
connection.setFixedLengthStreamingMode(postDataByteArr.length);
connection.setConnectTimeout(20000);
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.writeBytes(postData);
dataOutputStream.flush();
dataOutputStream.close();
GeneralUtils.print("respCode " + connection.getResponseCode());
// if connection was not successful
if (connection.getResponseCode() != 200) {
jsonResponse.put("status", "Failure");
jsonResponse.put("message", "Something went wrong. Please Try Again");
} else {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null) {
sb.append(line);
}
reader.close();
String response = sb.toString();
GeneralUtils.print("NetworkCall Server response " + response);
jsonResponse = new JSONObject(response);
}
} catch (JSONException e) {
GeneralUtils.print("NetworkCall.JSONEx 162 " + e);
} catch (MalformedURLException e) {
GeneralUtils.print("NetworkCall.MalformedURLEx " + e);
} catch (IOException e) {
try {
jsonResponse.put("status", "No Internet Connection");
jsonResponse.put("message", "Please check your Internet connection and try again");
} catch (JSONException e1) {
GeneralUtils.print("NetworkCall.JSONEx " + e);
}
} finally {
connection.disconnect();
}
} else {
// if Internet is not available
try {
jsonResponse.put("status", "No Internet Connection");
jsonResponse.put("message", "Please check your Internet connection and try again");
} catch (JSONException e) {
e.printStackTrace();
}
}
return jsonResponse;
}
Many many thanks in advance!
As of now I am following a workaround posted here
which essentially dictates trying to connect N number of times to bypass the EOF exception issue.
In my case, when I catch EOFException, I call the doInBackground again depending upon the reconnectCount;
CODE :
catch (IOException e) {
try {
if (reConnectCount <= 10) {
reConnectCount++;
jsonResponse = doInBackground(keyValuePairs);
} else {
jsonResponse.put("status", "No Internet Connection");
jsonResponse.put("message", "Please check your Internet connection and try again");
}
} catch (JSONException e1) {
GeneralUtils.print("NetworkCall.JSONEx " + e);
}
}
Where jsonResponse essentially holds server response in JSON form. So, whenever doInBackground is successfully executed (i.e. does not get Caught and returns jsonResponse), we overwrite the calling doInBackground's jsonResponse object.