Getting 406 Error in Ajax Response using Spring MVC - javascript

I am learning Ajax and trying to get it work on my project. Basically i am trying to implement google like suggestion on the project.
i have a UI that sends ajax request to the server asynchronously and gets relevant suggestion
function showHint(str) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
console.log(str);
var xmlhttp = new XMLHttpRequest();
console.log(xmlhttp.readyState);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET", "/hint?word=" + str, true);
xmlhttp.send();
}
}
<label>Name <input id="peak" type="text" name="peak_name" onkeyup="showHint(this.value)">
<p id="peak"></p>
<p>Suggestions: <span id="txtHint"></span></p>
The Spring MVC controller is
#RequestMapping(value = { "/hint" }, method = RequestMethod.GET,params={"word"})
public #ResponseBody ArrayList<String> hint(ModelMap model,#RequestParam String word) {
System.out.println("Inside Hint");
String[] hints = { "Ram", "Shyam" };
ArrayList<String> returnhint = new ArrayList<String>();
// lookup all hints from array if $q is different from ""
if (word != null) {
word = word.toLowerCase();
int length = returnhint.size();
for (int j = 0; j < length; j++) {
if (word.contains(hints[j])) {
returnhint.add(hints[j]);
}
}
}
return returnhint;
}
I am new to Ajax. So is there a specific way xmlhttp object's responseText have to be handled?
My question is since i have passed ArrayList in the response body, how do get ajax to get that response and update the UI accordingly?

To use #ResponseBody you need two things:
<mvc:annotation-driven /> in your context file
a library to handle JSon (like Faster Jackson) in your classpath
If you don't configure well the spring part you will have a 406 error because the header of the response is not correctly initialized and the response itself is not in the right format.

Going through the documentation, xmlhttprequest object has a set of properties to handle response
XMLHttpRequest.response Read only
Returns an ArrayBuffer, Blob, Document, JavaScript object, or a DOMString, depending on the value of XMLHttpRequest.responseType. that contains the response entity body.
So i basically returned a String instead of a ArrayList and concatenated all of the matched hints in the string using comma ',' separator
And in the javascript file. I simply made a list of the reponse with split(',') function.
function showHint(str) {
if (str.length == 0) {
document.getElementById("txtHint").innerHTML = "";
return;
} else {
console.log(str);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var list=xmlhttp.responseText.split(',');
console.log(list);
document.getElementById("txtHint").innerHTML = list;
}
};
xmlhttp.open("GET", "/hint?word=" + str, true);
xmlhttp.send();
}
}
<label>Name <input id="peak" type="text" name="peak_name" onkeyup="showHint(this.value)">
<p id="peak"></p>
<p>Suggestions: <span id="txtHint"></span></p>
Controller Method
#RequestMapping(value = { "/hint" }, method = RequestMethod.GET,params={"word"})
public #ResponseBody String hint(ModelMap model,#RequestParam String word) {
System.out.println("Inside Hint");
String[] hints = { "Ram", "Ra","R","Shyam" };
String returnedhints="";
// lookup all hints from array if $q is different from ""
if (word != null) {
System.out.println("i am here");
//word = word.toLowerCase();
int length = hints.length;
for (int j = 0; j < length; j++) {
System.out.println(word+"contains"+hints[j]+"="+word.contains(hints[j]));
if ((word.regionMatches(0, hints[j], 0, hints[j].length())) {
returnedhints= returnedhints+","+hints[j];
}
}
}
return returnedhints;
}
Hope this will be helpful to future ajax learner with spring mvc.

Related

How to get parametr in response from spring? (rest Javascript)

I have a problem with returning an error to html. So, I have web-app with "sql interpreter".
HTML
<button type="submit" onclick="executeSQL('interpreterSQL')">
<i class="fas fa-bolt"></i>
</button>
<textarea id="interpreterSQL" placeholder="❔❔❔"></textarea>
After entering a query into the interpreter, I run POST in javascript and shoot to spring:
POST in JavaScript
function executeSQL(interpreterSQL) {
var tmp = document.getElementById(interpreterSQL).value;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var response = xhttp.responseText;
console.log("ok"+response);
}
};
xhttp.open("POST", "/user/executeSQL", true);
xhttp.send(tmp);
}
After that I handle the query in my service and return message to POST in my Controller:
Controller (POST in Spring)
#PostMapping(path = { "/user/executeSQL" })
public ModelAndView executeSQL(#RequestBody String tmp) {
String[] split = tmp.replace("\n", "").replace("\t", "").split(";");
String feedback = databaseTableService.executeSQL(split);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("successMessage", feedback);
modelAndView.setViewName("/user/interpreterSQL");
return modelAndView;
}
Service which is used to execute native query
public String executeSQL(String[] split){
SessionFactory hibernateFactory = someService.getHibernateFactory();
Session session = hibernateFactory.openSession();
String message = null;
for (int i = 0; i < split.length; i++) {
try{
String query = split[i];
session.doWork(connection -> connection.prepareStatement(query).execute());
message = "Success";
}
catch(Exception e){
message = ((SQLGrammarException) e).getSQLException().getMessage();
}
}
session.close();
return message;
}
So finally we are in my controller which is ready to return value and we have message which is have information about sql exceptions. We are there:
And here is my question: How to get variable "feedback" in response?
I need to handle that value there i think:
but that "var response = xhttp.responseText" is returning all my HTML code. I need only parametr "feedback" from my controller.
Guys can someone help? :( I don't know how to send that parametr in return and handle it in javascript...
Maybe you can change your Controler method to return JSON response instead on ModelAndView
#PostMapping(path = { "/user/executeSQL" })
public ResponseEntity<Object> executeSQL(#RequestBody String tmp) {
String[] split = tmp.replace("\n", "").replace("\t", "").split(";");
Map<String,String> response = new HashMap<String, String>();
response.put("feedback", databaseTableService.executeSQL(split));
return new ResponseEntity<>( response , HttpStatus.OK);
}
Now you should be able to see the status
var response = xhttp.responseText;
console.log("ok"+response);

getJSON - How to print out the result, and how to retrieve input?

I implemented some java functions. Now I have to present the result to the user via html.
public Object post()
{
responseHeaders.put("Content-Type", "application/json");
try
{
final User user = UC0_Login.getLoggedInUser(this);
List<Measurement> mylist = MeasurementService.getMeasurementsbyPatient(user.getUsername().toString());
for(int i = 0; i < mylist.size(); i++) {
Measurement mesPatient = mylist.get(i);
DownloaderService.saveTxt(mesPatient);
// System.out.println("Test Name: " + mesPatient.getRequest().getPatient().getFirst_name().toString());
}
}
catch(HttpException x)
{
x.printStackTrace();
this.statusCode = x.getStatusCode();
return "{ \"success\": false }";
}
catch(Exception x)
{
x.printStackTrace();
this.statusCode = StatusCode.SERVER_ERROR_500;
return "{ \"success\": false }";
}
String property = "java.io.tmpdir";
String tempDir = System.getProperty(property);
String result = "Your measurements have been saved at" + tempDir;
return result;
}
There I implemented post(), in a Java class. I also created a HttpServer in the background. As shown in the code, I return a String. How can I print out that string in HTML? And how can I get input (for example an integer) from HTML into for example a get() function? Thank you!!!
If you are basically looking for AJAX request and response, here is a good source to learn how to.
https://blog.garstasio.com/you-dont-need-jquery/ajax/#posting
For example,
HTML
<p id="result"></p>
<form id="frm1" action="/action_page.php">
Your input: <input type="text" id="myInput"><br><br>
<input type="button" onclick="myFunction()" value="Submit">
</form>
JAVASCRIPT
var input = document.getElementById("myInput").value;
xhr = new XMLHttpRequest();
xhr.open('POST', 'Your URL Goes Here');
xhr.onload = function() {
if (xhr.status === 200) {
var response = xhr.responseText;
document.getElementById("result").innerHTML = response;
}
else if (xhr.status !== 200) {
alert('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send(encodeURI('input=' + input)); // Use your API param keys here

'undefined' error even after JSON.parse

<!DOCTYPE html>
<html>
<head>
<title>Imagery Gallery</title>
</head>
<body>
<h2>Location List</h2>
<!-- image gallery will be displayed in the results <div> -->
<div id="results"></div>
<!-- JavaScript codes -->
<script src="HTTPRequest.js"></script>
<script>
//Send request to the server to get the JSON dataset showing the list of locations
//The URL to request is "http://geopingyin.com/gis/Locations.php"
//The request function sendHttpRequest(sURL) is defined in the HTTPRequest.js file
sendHttpRequest("http://geopingyin.com/gis/Locations.php");
//When the JSON dataset (JSONData, a text string) is successfully returned to the browser,
//The function handleResponseData(JSONData) will be automatically called.
//Complete the following function to process the JSON dataset.
function handleResponseData(JSONData) {
var obj = JSON.parse(JSONData);
for (i in obj) {
i += obj[i] + "<br>";
document.getElementById("results").innerHTML = i.Locations;
}
}
//place your codes here for the imagery gallery
</script>
</body>
</html>
This code is giving me an 'undefined' answer whenever I run it. After lots of research it seems like most people have issues with 'undefined' because they are using strings and not objects. However in my code I used a JSON.parse in order to create an object off of the original string, and it still comes up as undefined. I wish to use JSON.parse in order to change my array into objects and then loop through and display each one, yet I can not seem to figure out how to go about this. Any help would be greatly appreciated!
Also here is my HTTPRequest.js code just in case
var xmlHttp = createHttpRequestObj(); //Http request object
//Create HTTP request object
function createHttpRequestObj() {
var xmlHttpObj;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
try {
xmlHttpObj = new XMLHttpRequest();
} catch (e) {
xmlHttpObj = false;
}
} else {
// code for IE6, IE5
try {
xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
xmlHttpObj = false;
}
}
if (!xmlHttpObj)
alert("Cannot create the Http request object");
else {
return xmlHttpObj;
}
}
//Send HTTP request with the URL
//Function handleServerResponse() will be used to interpret the response
function sendHttpRequest(sURL) {
if (xmlHttp.readyState == 0 || xmlHttp.readyState == 4) {
xmlHttp.open("GET", sURL, true);
xmlHttp.onreadystatechange = handleServerResponse;
xmlHttp.send();
} else {
setTimeout(function() {
sendHttpRequest(sURL);
}, 1000);
}
}
//Handel HTTP response
function handleServerResponse() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
xmlResponse = xmlHttp.responseText;
//Handle the xmlResponse
handleResponseData(xmlResponse);
}
}
}
THANK YOU!
undefined results when you try to access data that doesn't exist. This can result from trying to read an object key from what is actually a string; but can equally happen when reading a nonexistent key from a real object (which is one part of what was going wrong in your code.)
The issues are within your handleResponseData function; I've commented it below to describe what's going wrong:
function handleResponseData(JSONData) {
var obj = JSON.parse(JSONData); // so far so good
/* obj only contains one key, "Locations", so `obj` isn't
what you want to be iterating over; instead you want to iterate
within obj.Locations: */
for (i in obj) {
/* Two problems in this next line: first, it's trying to
concatenate objects onto a string (which will result in
the string "[object Object]"); second, it's trying to
concatenating them onto the iterator, which would
interfere with the loop: */
i += obj[i] + "<br>";
/* This line should not be inside the loop, and it shouldn't be
trying to read the Locations key from child objects, because
that key was on the parent: */
document.getElementById("results").innerHTML = i.Locations;
}
}
Below is a corrected version (I've assumed the .Name key from each object within the Locations array is what you want):
var xmlHttp = createHttpRequestObj();
function createHttpRequestObj() {
// Code for handling obsolete browsers omitted for brevity
return new XMLHttpRequest();
}
function sendHttpRequest(sURL) {
if (xmlHttp.readyState == 0 || xmlHttp.readyState == 4) {
xmlHttp.open("GET", sURL, true);
xmlHttp.onreadystatechange = handleServerResponse;
xmlHttp.send();
} else {
setTimeout(function() {
sendHttpRequest(sURL);
}, 1000);
}
}
function handleServerResponse() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
xmlResponse = xmlHttp.responseText;
handleResponseData(xmlResponse);
}
}
}
sendHttpRequest("https://geopingyin.com/gis/Locations.php");
function handleResponseData(JSONData) {
var obj = JSON.parse(JSONData);
var output = "";
for (i in obj.Locations) {
output += obj.Locations[i].Name + "<br>";
}
document.getElementById("results").innerHTML = output
}
<h2>Location List</h2>
<div id="results"></div>

How can I pass a parameter from javascript to RESTful web service using XMLHttpRequest

When i try to print the received parameter at the web service.
The parameter is empty.
If I view domain server log of glass fish server I can see the following
print:
Inside getJson()
countryKey =
So I understand the request arruved to the web service, but the parameter
that was sent from the javascript url is empty
// This is the code of the web service method
#GET
#Produces(MediaType.APPLICATION_JSON)
public String getJson(String countryKey) {
System.out.println("Inside getJson()");
System.out.println("countryKey = " + countryKey);
return "countryKey = " + countryKey;
}
// This is the javascript method
function populateDistrictList() {
var element = document.getElementById("selectCountry");
var selectedCountryKey = element.value;
var selectedCountry = element.options[element.selectedIndex].text;
var xmlHttp = new XMLHttpRequest();
var url = "http://localhost:8080/MissionWS/webresources/generic?selectedCountryKey="+selectedCountryKey;
xmlHttp.open('GET', url, true);
xmlHttp.responseType = 'json';
if (xmlHttp) {
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
alert(xmlHttp.responseText);
} else {
alert("Something is wrong !");
}
}
};
xmlHttp.send();
}
}
Please try adding the #QueryParam to your method signature as follows.
public String getJson(#QueryParam("selectedCountryKey") String countryKey)

Sending binary data to server

I create an array buffer containing some data:
var myArray = new ArrayBuffer(512);
var longInt8View = new Uint8Array(myArray);
for (var i = 0; i < longInt8View.length; i++) {
longInt8View[i] = i % 255;
}
And I send it so a server via POST:
if (window.XMLHttpRequest) {
var xmlhttp = new XMLHttpRequest();
} else {
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
action(xmlhttp.responseText);
}
};
xmlhttp.open("POST", 'http://somedomain.com:8080', true);
xmlhttp.send(myArray);
var action = function (response) {
console.log(response);
};
I now want to receive these binary data in go code, and do something with it. How can I do this?
package main
import (
"fmt"
"net/http"
)
func handleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "%s", r.Body)
}
func main() {
http.HandleFunc("/", handleRequest)
http.ListenAndServe(":8080", nil)
}
I can see a reference to a memory block inside the body, but how do I get this specificaly?
Don't send binary data over HTTP protocol. Convert them in Base64. Send them as a normal string. Decode them from Base64 to binary on the server side.
To convert a binary data to base64 you can use the function btoa

Categories

Resources