ajax gets empty responseText once piping intermediate data to python at backend - javascript

The background is, frontend passed an id back to backend and backend uses the id to extract information from database. The extracted data need further processing at backend and then gets sent back to frontend.
Here is the front end code:
html:
<!DOCTYPE html>
<html>
<head>
<title>Test!</title>
<meta charset="utf-8">
<script src="loadPage.js">
</script>
</head>
<body onload = "loadPage()">
<div id="stack"><p>test part</p>
</div>
</body>
</html>
js:
function __getParameters() {
var parm = {};
var url = window.location.href;
var pairs = url.slice(url.indexOf('?') + 1).split('&');
for (var i = 0; i < pairs.length; i++) {
pair = pairs[i].split('=');
parm[pair[0]] = pair[1];
}
return parm;
}
function __loadData(star) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// var data = JSON.parse(xmlhttp.responseText);
console.log(xmlhttp.responseText);
if (xmlhttp.responseText == "") {
document.getElementById("stack").innerHTML = "f*ck";
} else {
document.getElementById("stack").innerHTML = xmlhttp.responseText;
}
}
}
var url = "getXML.pl";
url = url + "?STAR=" + star;
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function loadPage() {
var parm = __getParameters();
// document.getElementById("stack").innerHTML = parm["STAR"];
if (parm == undefined) {
// wrong url error page
} else if (parm['STAR'] == undefined) {
// missing star error page
} else if (parm['user' == undefined]) {
// missing user id error page
} else {
var star = parm["STAR"];
var user = parm["user"];
__loadData(star);
}
}
The backend uses perl to extract data from database, and it will print the output to stdout. The output is a XML in string form. Then I must use an existed python script to process the extracted data.
However, the server seems not support python (But the server can run python if I directly run python scripts on it. The reason for my statement is that I wrote a python cgi and I got a 500 error, while the perl cgi is ok. I'm sure the python script is correct since it can run directly on the server. I have no access to error log and I cannot modify the config file of the server).
So I piped the output of the perl script to python, and run it using 'system()'. The python script will output a processed string to stdout.
Here is the backend scripts:
perl script:
#!/depot/perl-5.14.2/bin/perl
# extract posted data
local ($buffer, #pairs, $pair, $name, $value, %FORM);
$ENV{"REQUEST__METHOD"} =~ tr/a-z/A-Z/;
if ($ENV{"REQUEST_METHOD"} eq "POST") {
read(STDIN, $buffer, $ENV{"CONTENT_LENGTH"});
} else {
$buffer = $ENV{"QUERY_STRING"};
}
#pairs = split(/&/, $buffer);
foreach $pair (#pairs) {
($name, $value) = split(/=/, $buffer);
$value =~ tr/+/ /;
$value =~ s/%(..)/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
$star = $FORM{STAR};
print "Content-type:text/html\n\n";
my $cmd = "***/sq_star.pl --xml --star_id " . $star;
$cmd = $cmd . " | ***/python parseXML.py";
system($cmd);
the sq_star.pl (I just remove the path here and replace it with ***) near the end of perl script is just an existed script that will extract data from database. And parseXML.py is an existed script which does a lot to the input string.
The strange thing is, the responseText is always an empty string. I tried to run the perl script directly on the server, it can print expected results. And if I remove $cmd = $cmd . " | ***/python parseXML.py";, the responseText will be the data extracted from the database.
What I have tried for now:
1. I wrote a simple test python with just one line of print. Still empty response
2. I tried to store the output as $output =`$cmd`; and print $output; in the perl script, still empty.
3. I tried to store the original data in a txt and let the python read from the txt. Still empty
It seems that that data processed by python just cannot be sent back .....
-------------------update----------------
It seems to be the problem of the server. I guess the server is not set to support python so if I directly send requests to a python script on backend, there will be 500 error. But somehow my way, i.e., calling python in perl, gets around the error, but still the python just doesn't work... Just my guess

I found the problem. It is because the interpreter I specified cannot be found by the server. system(...) line actually doesn't run at all. The reason that I didn' t see any error is because system() hides the error for me. Actually the return value of system() is -1, which means something wrong. I should have checked the return value

Related

How to get live row count as Jasper prints reports

I've developed a web application using jsp that has a list of contents which are placed in an ArrayList. I've tried various methods to implement this, tried the AsynchronousFillHandle , AJAX , Scriptlet. But I just can't get it done properly.
What I'm trying to achieve here is, while the JasperExportManager is filling records row by row, I want to display the number of rows that have been printed (say Live status of number of records printed) in the webpage.
For Example
267 out of 645588 records printed
5692 out of 645588 records printed
34677 out of 645588 records printed
After two days of unsuccessful attempts, I decided to use a shortcut, I wrote a scriptlet file, which will print the count of records being printed to a txt file in the same directory,
Scriptlet code:
public void afterDetailEval() throws JRScriptletException{
count = (Integer) this.getVariableValue("count");
BufferedWriter br = null;
try {
br = new BufferedWriter(new FileWriter(new File("C:/jasperreports-5.6.0/test/viewTasks/WebContent/value.txt")));
br.write(new String(""+count));
br.close();
Thread.sleep(200);
}catch (Exception e) {
e.printStackTrace();
}
}
and then used another ajax request to read data from the text file and display it in the browser, which was again unsuccessful as the ajax request returned only the previously stored value (i.e. Although the changes take place in the .txt file, AJAX request returned only the value which was there before the program execution took place. I guess it is because, the changes happen in the local directory and doesn't get reflected in the server). The AJAX code is as follows,
Webpage code:
<script>
function startPrinting() {
xhttp1 = new XMLHttpRequest();
xhttp1.onreadystatechange = function() {
if (this.readyState >= 1) {
document.getElementById('total')style.display = "";
setTimeout(function() { getStat(); }, 6000); //calls the function to start updating status
}
};
xhttp1.open("POST", "statusServlet", true);
xhttp1.send();
} //This function is to start the printing processes
function getStat(){
myvar=setInterval(function() {reval()}, 3000);
function reval(){
if(xhttp1.readyState>2){
xhttp1.abort();
}
var rawFile = new XMLHttpRequest();
var prev = "";
rawFile.open("GET","value.txt" , true);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
allText = rawFile.responseText;
if(prev===allText){
document.getElementById("status").innerHTML = allText;
return;
}
prev = allText;
document.getElementById("status").innerHTML = allText;
}
}
}
rawFile.send();
}
}
</script>
While using this code, If the file .txt is kept active inside the eclipse IDE, the values get reflected in the webpage, I really don't know why or how, but when the text file is kept active (I know it's weird), somehow the AJAX request returns the values correctly. Is there anyway to get this code to work without having to keep the .txt file active? Is there any other way to achieve the live row status of Jasper export other than writing and reading from a file?
NOTE: I'm using JAVA EE IDE from Eclipse with Tomcat 7.0 as server
Thanks in advance!

JSON parsing string but not xmlhttprequest responseText

[SOLVED]
I have a terrible headache, because I am new to JS and AJAX/JSON and cannot seem to figure out why this is happening. I am getting a JSON formatted response that looks like this when output on my client web page:
[{"ticket_id":"2","ticket_name":"super_rugby_18_Aug_2017","ticket_desc":"Brumbies vs Sharks, 14:30","ticket_price":"420.00"}]
The problem is, that I cannot parse the responseText with JSON. But whenever I hardcode the parsed string to be [{"ticket_id":"2","ticket_name":"super_rugby_18_Aug_2017","ticket_desc":"Brumbies vs Sharks, 14:30","ticket_price":"420.00"}], the problem goes away.
But of course, I need the database request to be parsed and not the hardcoded string. Please help. Here is my code that is not working:
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var input = String(this.responseText);
var jsonObj = JSON.parse(input);
document.getElementById("history").innerHTML = jsonObj[0].ticket_id;
}
}
Hardcoded 'string' variable that can be parsed:
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var string = '[{"ticket_id":"2","ticket_name":"super_rugby_18_Aug_2017","ticket_desc":"Brumbies vs Sharks, 14:30","ticket_price":"420.00"}]';
var jsonObj = JSON.parse(string);
document.getElementById("history").innerHTML = jsonObj[0].ticket_id;
}
}
Here is the output of stringify:
"\r\n\r\n\r\n\r\n\r\n\r\n\r\n[{\"ticket_id\":\"1\",\"ticket_name\":\"IIC_match3\",\"ticket_desc\":\"\",\"ticket_price\":\"589.99\"},{\"ticket_id\":\"2\",\"ticket_name\":\"super_rugby_18_Aug_2017\",\"ticket_desc\":\"Brumbies vs Sharks, 14:30\",\"ticket_price\":\"420.00\"}]\r\n\r\n" The array is filled in this php loop:
php loop I use to send the JSON array
$rows = array();
while ($r = mysqli_fetch_assoc($result)){
$rows[] = $r;
}
$json = json_encode($rows);
echo $json;
SOLUTION:
Guess what the problem was? My web service is running in a Linux VM environment, and my calling web client was too. Now when I tried doing the httprequest from a WINDOWS machine to the VM, the JSON.parse works! What could be wrong with my Linux configuration?

I am trying to implement an AJAX call. What am I doing wrong?

This is my HTML text:
<input type="text" class="resizedsearch" name="searchdb">
<button id="submit" onclick="ajaxCall()">Search!</button>
This is Javascript:
ajaxCall()
{
var xmlhttp = new XMLHttpRequest();
var url = "http://localhost:8080/CSE%205335%20Project%20One/userInfo.php";
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
myFunction(xmlhttp.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send('searchdb');
function myFunction(response)
{
var obj = JSON.parse(response);
document.getElementById("democity").innerHTML =
obj.city;
document.getElementById("demodes").innerHTML =
obj.description;
document.getElementById("latlon").innerHTML =
obj.latitude + "," + obj.longitude;
}
}
And this is where I am trying to display the response that I am receiving from the PHP file:
<b><font size="24" face="Cambria"><p id="democity"></p></font></b>
<font size="6" face="Cambria"><p id="demodes"></p></font>
</br>
The output of the PHP file is stored in $outp and it is in the JSON format.
Any help appreciated. Thank you.
!!UPDATE!!
function ajaxCall()
{
var xmlhttp = new XMLHttpRequest();
var url = "http://localhost:8080/CSE%205335%20Project%20One/userInfo.php";
xmlhttp.onreadystatechange=function()
{
xmlhttp.open("GET", url, true);
xmlhttp.send('searchdb');
if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
myFunction(xmlhttp.responseText);
}
}
}
function myFunction(response)
{
var obj = JSON.parse(response);
document.getElementById("democity").innerHTML =
obj.city;
document.getElementById("demodes").innerHTML =
obj.description;
document.getElementById("latlon").innerHTML =
obj.latitude + "," + obj.longitude;
}
This is how the improvised code looks. Still not working.
Example by FactoryAidan is not going to work as it violates Same Origin Policy (unless you'll run the code in browser console on Google page). Try replacing http://www.google.com with your local address. I tested the code with a little modification and it works, or at least gives alert, so the function is called. Here's it is:
function ajaxCall(){
var xmlhttp = new XMLHttpRequest();
var url = "http://localhost:8080"; /* but make sure the url is accessible and of same origin */
xmlhttp.onload=function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
myFunction(xmlhttp.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send('searchdb');
}
function myFunction(response){
alert('I made it here');
}
Your code update after my first answer looks like it was done in haste and I think makes the question a little harder. The .open() and .send() methods ended up inside your .onreadystatechange function definition but they need to be outside. Your first one didn't have those placement issues. The code I wrote below has your exact building blocks but with no placement issues so you should be able to follow along with how it matches your example code. I also tested it and it sucessfully sends and receives data back and successfully calls the myFunction() callback function.
Nonetheless, I took your code and rewrote it a bit. If you get an alert('') message when you run it, that means that your xml request worked perfectly. If you don't see an alert('') message. It means your xml request is returning a http 404 error, which means your request URL is bad. Try changing your request URL to something you know won't give you a 404 error, like 'http://www.google.com'. If it works and you get the alert message, then the only problem is that your localhost:8080 url is a bad url.
Also, in your myFunction callback function, javascript treats line-breaks as the end of a line of code. So you must write assignments that use an '=' sign on the same line with no line-breaks. Due to this javascrit principle, you also don't need a semicolon ';' at the end of a single line like you would in PHP script.
Finally, a big cause of errors can be the JSON.parse() call. The data received MUST be a valid json string. So if the URL you call returns anything other than pure json... your myFunction() callback function will break on the JSON.parse() command.
Lastly, if there is an error in your myFunction() callback function, your browser inspector will not report it in a useful way and will instead throw an error that points to your xmlhttp.onreadystatechange=function(){} as being the culprit because that is where the browser thinks the error resides (being the calling function), even though the real error is in your myFunction() callback function. Using my edit of your ajaxCall(){...} code and with a valid url, you can be positive that the ajax call works and any errors you have are in your myFunction() callback function.
Lastly again, You have to be careful in your callback function because there are so many things that could break it. For example, document.getElementById() will cause an error if no html element exists on your web-page with the id you provided. Also, if the JSON you received back from the ajax call is missing any properties you mentioned like (city or latitude) it is likely that the innerHTML will be set to 'undefined'. But some browsers may treat the missing json properties as an error instead of just saying they are 'undefined' when you try to call them.
function ajaxCall(){
var xmlhttp = new XMLHttpRequest();
var url = "http://www.google.com";
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
myFunction(xmlhttp.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send('searchdb');
}
function myFunction(response){
alert('I made it here')
/*
var obj = JSON.parse(response);
document.getElementById("democity").innerHTML = obj.city
document.getElementById("demodes").innerHTML = obj.description
document.getElementById("latlon").innerHTML = obj.latitude + "," + obj.longitude
*/
}

ajax responsetext has extra data

I use ajax to check if there is a certain record in the database, using the variables 'zer' and 'modify' to search for the record containing those values (see the code below).
If the record is found in the database, I return "found" from the php ajax code to the javascript; otherwise I return "not found"
I also store the value of 'zer' and 'modify' into the SESSION before I return the "found" or "not found" from the php ajax code.
The response text looks like this when the record is found in the database:
array(2) {
["zer"]=>
string(2) "someVal"
["modify"]=>
string(1) "anotherVal"
}
found
I only want the "found" returned here and for some reason the responseText is returning the Session variables that I set up before the return.
Why is this, and how can I precisely control exactly what is returned from the Ajax call?
I tried using some buffer flushing php calls (see the code) to no effect. I've read a lot of Ajax posts but I cannot find one that explains how to have precise, exact control over what gets returned from my ajax, or whether storing my 'zer' and 'modify' values into the SESSION before I return the responseText is some kind of "no-no."
Here is the code (NOTE: the database lookup code works 100% and correctly finds the record if it is present -- the code below has been tested for both the 'found' and 'not found' situations and correctly locates the record if it is present).
EDIT: I use some output buffering PHP calls in an attempt to control any output buffering that may be happening, but this did not help. See these buffer calls below.
JAVASCRIPT
var zer = "someVal";
var modify = "anotherVal";
if(window.XMLHttpRequest)
{
xmlhttp = new XMLHttpRequest();
}
else
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
var theResponseText;
xmlhttp.onreadystatechange = function()
{
if(xmlhttp.readyState == 4 && xmlhttp.status == 200)
{
theResponseText = xmlhttp.responseText;
alert("responseText is >>>" + theResponseText + "<<< that.");
if( theResponseText == 'notfound')
{
return;
}
else if( theResponseText == 'found')
{
alert("We found the record!.")
}
}
}
ajaxText = "handler.php?zer=" + zer + "&modify=" + modify;
xmlhttp.open("GET", ajaxText, true);
xmlhttp.send();
PHP CODE in handler.php
$zer = $_GET['zer'];
$modify = $_GET['modify'];
$theDB = connectToDb();
$query = "SELECT * FROM " . Dbases::$MyDB_TABLE
. " WHERE BINARY " . dbConstants::$ZERS
. " IN ('" . $zer . "')"
. " AND BINARY " . dbConstants::$MODIFYS
. " IN ('" . $modify . "')";
$result = mysql_query($query);
if($result)
{
$numrows = mysql_num_rows($result);
if($numrows > 0)
{
$bFound = true;
}
}
closeDB($theDB);
// now erase the php output buffering, start a new output buffer,
// echo the result, then flush the php output buffer so that the
// Ajax response text has *exactly* what I 'echo' here and nothing else.
// NOTE: this did *not* help.
if(! $bFound)
{
ob_flush();
while (#ob_end_flush());
//ob_end_flush();
//ob_end_clean();
//ob_end_flush();
ob_start();
//echo "notfound";
print "notfound";
ob_end_flush();
//ob_end_clean();
// clear out the session vars
$_SESSION['zer'] = "";
$_SESSION['modify'] = "";
return;
}
else
{
ob_end_clean();
ob_start();
//echo "found";
print "found";
ob_end_flush();
//ob_end_clean();
$_SESSION['zer'] = $zer;
$_SESSION['modify'] = $modify;
return;
}
I solved this. One of the team members, at some point, stuck a var_dump way up in the source file and I didn't catch it until just now. I commented out the var_dump() and voila, the responseText is as expected, and I eliminated all the php buffer function calls as well.

How to load a text file in JavaScript?

I'm creating a simple WebGL project and need a way to load in models. I decided to use OBJ format so I need a way to load it in. The file is (going to be) stored on the server and my question is: how does one in JS load in a text file and scan it line by line, token by token (like with streams in C++)? I'm new to JS, hence my question. The easier way, the better.
UPDATE: I used your solution, broofa, but I'm not sure if I did it right. I load the data from a file in forEach loop you wrote but outside of it (i.e. after all your code) the object I've been filling data with is "undefined". What am I doing wrong? Here's the code:
var materialFilename;
function loadOBJModel(filename)
{
// ...
var req = new XMLHttpRequest();
req.open('GET', filename);
req.responseType = 'text';
req.onreadystatechange = function()
{
if (req.readyState == 4)
{
var lines = req.responseText.split(/\n/g);
lines.forEach(function(line)
{
readLine(line);
});
}
}
req.send();
alert(materialFilename);
// ...
}
function readLine(line)
{
// ...
else if (tokens[0] == "mtllib")
{
materialFilename = tokens[1];
}
// ...
}
You can use XMLHttpRequest to fetch the file, assuming it's coming from the same domain as your main web page. If not, and you have control over the server hosting your file, you can enable CORS without too much trouble. E.g.
To scan line-by-line, you can use split(). E.g. Something like this ...
var req = new XMLHttpRequest();
req.open('GET', '/your/url/goes/here');
req.onreadystatechange = function() {
if (req.readyState == 4) {
if (req.status == 200) {
var lines = req.responseText.split(/\n/g);
lines.forEach(function(line, i) {
// 'line' is a line of your file, 'i' is the line number (starting at 0)
});
} else {
// (something went wrong with the request)
}
}
}
req.send();
If you can't simply load the data with XHR or CORS, you could always use the JSON-P method by wrapping it with a JavaScript function and dynamically attaching the script tag to your page.
You would have a server-side script that would accept a callback parameter, and return something like callback1234(/* file data here */);.
Once you have the data, parsing should be trivial, but you will have to write your own parsing functions. Nothing exists for that out of the box.

Categories