Return JSON from one JSP to another? - json

Is it possible in one JSP to make a jQuery ajax callback to another JSP and have data returned?
I am trying to make the ajax call to Page2.jsp in the $(document).ready call in Page1.jsp
I am attempting to get JSON returned by "Page2.jsp"
I am running Tomcat locally to test.
I am seeing the JSON printed to the console, but not returned to the original calling method in Page1.jsp
Any ideas?
Page1.jsp
$(document).ready(function(){
$.ajax({
url : 'Page2.jsp',
dataType: 'json',
success : function(json)
{
var obj = jQuery.parseJSON(json);
}
});
});
Page2.jsp
<%#page contentType="application/json; charset=UTF-8"%>
<%#page import="org.json.simple.JSONObject"%>
<%
JSONObject json = new JSONObject();
json.put("amount","55.00");
json.put("tax","1.00");
String jString = JSONObject.toJSONString(json);
PrintWriter out = response.getWriter();
out.println(jString);
out.close();
%>

I tried the code in your question and the jQuery.parseJSON() code throw the following error: "SyntaxError: JSON.parse: unexpected character". On debugging I saw that the servlet code generated by tomcat includes out.write("\r\n"); I suspect that these character are causing the syntax error.
Nevertheless in the javascript I tried accessing the returned object using the dot notation without parsing it and I was able to so as if it were a JSON object. It appears that it is not necessary to parse the returned object.
The only modification I made to the JSP code was to remove the lines PrintWriter out = response.getWriter(); and out.close();

Related

Reading JSON data from Servlet to JSP

Am getting a json data from servlet to JSP. Am getting the response from servlet checked in browser console. Attached the screenshot. I have given below the servlet and JSP code. Am making a ajax call to servlet to retrieve the json data. But from servlet response is coming but in ajax call its not going inside success function. How can i read this data in JSP and i need to use this JSON in javascript to retrieve it.
Am new to JSP & Servlet. I have tried this much. Can anyone help here please to read it and retrieve in JSP?
Thanking in Advance
Servlet Code
response.setContentType("application/json");
response.setHeader("cache-control", "no-cache");
PrintWriter out = response.getWriter();
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);
out.println(json.toString());
out.flush();
JSP Code with AJAX Call
$.ajax({
url: '<%=request.getContextPath()%>/home',
type: 'POST',
data: {
'action': 'getBugReport',
'dateString':document.getElementById("daterangePicker").value,
'projectName': 'All'
},
success: function(responseText) {
},
error: function () {
}
Response from Servlet

What functionality of Chrome shows a parse error as a popup?

I have no clue where this is coming from: here is it, in Java I created a servlet that runs Javascript files in Nashorn and then writes the result in a response. My Javascript code returns an object like:
function root(){
return {
"hello": 1
};
}
while my servlet returns the object (it was just a test):
Object result = invocable.invokeFunction("root", req);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(resp.getOutputStream());
outputStreamWriter.write(result.toString());
outputStreamWriter.close();
the response raw body is:
[object Object]
and chrome will do the following:
That red popup cross even closes it on click.
Is this done by an extension that I forgot about? Or is it some kind of integration with that syntax? I've really no idea.
#gotch4
Result you're observing is expected. You're retuning string representation of JavaScript object (technically you're calling Object.protorype.toString which returns [object Object]).
I think what you really want is to invoke JSON.stringify before returning response to the browser.
Object JSON = e.eval("JSON");
Object result = invocable.invokeMethod(JSON, "stringify", invocable.invokeFunction("root", req));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(resp.getOutputStream());
outputStreamWriter.write(result.toString());
outputStreamWriter.close();
p.s. Code should work, but I didn't test it - writing from phone.

how to display error message returned in json object from a servlet class in javascript/dojo?

I have a client makes file upload request via dojo.io.iframe to pass a binary data to a web application running on websphere app server and the servlet class inside of the web app makes a rest web service call to an external system to pass the binary data. So there are three layers involved.
The problem I am having is trying to display returned json data which contains exact exception happened in the last layer after making rest web service call back to the client.
The client html page looks like this
<form id="myForm" method="post" enctype="multipart/form-data">
<div id="output"></div>
<input id="filename" type="file" name="filename" />
<input id="submitButton" type="submit" value="Submit"></input>
</form>
The client javascript looks like this I am having trouble in printing out RuntimeException caught in a servlet to a client.
require(["dojo/io/iframe","dojo/dom","dojo/on","dojo/dom-construct","dojo/domReaddy!"],function(iframe,dom,on,domConst) {
on(dom.byId("submitButton"),"click",function() {
iframe.send({
form: "myForm",
handleAs: "json",
url: "/rootContext/myServlet"
}).then(function(data) {
domConst.place("<p>" + data + "</p>","output");
}, function(err) {
domConst.place("<p>" + err + "</p>","output"); // hope to print out exception caught in third layer
});
});
});
Servlet looks like this.
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
....
ServletOutputStream sos = null;
....
try {
domSomething(payLoad);
} catch (RuntimeException e) [
sos = response.getOutputStream();
sos.print(e.getMessage());
}
}
private void doSomething(String payLoad) {
URL url = null;
HttpURLConnection conn = null;
OutputStream os = null;
resource = new URL("someWhere");
conn = (HttpURLConnection) resource.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
os = conn.getOutputStream();
os.write(payLoad.getBytes());
os.close();
if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
String retMsg = null;
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
while ((retMsg = br.readLine()) != null) {
sb.append(retMsg);
}
br.close();
throw new RuntimeException(sb.toString()); // throws JSON format data
}
The servlet class makes rest web service call to an external system and if uploaded file data transmission fails it returns exception in json to the servlet class and I was trying to get that error data back to a client. This servlet class works fine for file uploading and if a corrupted file is uploaded then exception is generated. I didn't include logging mechanism in here, but it is implemented so that there is a log file in the app server that registers data transmitted included returned exception.
I am new to Dojo and having trouble using iframe api to display json data passed by a servlet class. I'd appreciate your advice on this matter. Thank you!
first of all I'd appreciate others who have contributed ideas to my question. The problem I was having fixed. I had to do following steps.
In the servlet class, wrap json data by html/body/textarea tags
From client side javascript, set handleAs: "json"
function(data) will be invoked and data would be json object so call whatever property name via . then mapping value will be printed out
Came to right solution via many trials/errors. One of the mistake I made was I used wrong slash for closing textarea tag by mistake in the servlet class.

Uncaught SyntaxError: Unexpected token B on live but not local server

So i am making some ajax post and it seems to work fine on the localhost, but when I publish it to ec2 server on amazon, I get Uncaught SyntaxError: Unexpected token B. Which seems to point to JSON parsing failure. Exact same database, same browser, and same methods being called. Why would it work on local and not on the server.
$.ajax({
url: '#Url.Action("Action")',
type: "POST",
data: ko.toJSON(viewModel),
dataType: "json",
contentType: "application/json; charset:utf-8",
success: function (result) {
},
error: function (xhr, textStatus, errorThrown) {
var errorData = $.parseJSON(xhr.responseText);
var errorMessages = [];
for (var key in errorData)
{
errorMessages.push(errorData[key]);
}
toastr.error(errorMessages.join("<br />"), 'Uh oh');
}
});
Here is the basic layout on the server side:
[HttpPost]
public JsonResult Action(ViewModel model)
{
try
{
Response.StatusCode = (int)HttpStatusCode.OK;
return Json("Successfull");
}
catch (Exception ex)
{
logger.Log(LogLevel.Error, string.Format("{0} \n {1}", ex.Message, ex.StackTrace));
Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
errors.Add(ex.Message);
return Json(errors);
}
}
Within the try statement, I do a couple of queries to the database and post some calculations on Authorize.Net (https://api.authorize.net/soap/v1/Service.asmx)
If there are any error with Authorize.net web service calls then I return errors like this:
if (profile.resultCode == MessageTypeEnum.Error)
{
logger.Log(LogLevel.Error, string.Join(",", profile.messages.Select(x => x.text)));
Response.StatusCode = (int)HttpStatusCode.BadRequest;
List<string> errors = new List<string>();
profile.messages.ToList().ForEach(x => errors.Add(x.text));
db.SaveChanges();
return Json(errors);
}
This error that I am logging:
A public action method 'AddPromoCode' was not found on controller 'Flazingo.Controllers.PositionController'. at
System.Web.Mvc.Controller.HandleUnknownAction(String actionName) at
System.Web.Mvc.Controller.ExecuteCore() at
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) at
System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.b__5() at
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.b__0() at
System.Web.Mvc.MvcHandler.<>c__DisplayClasse.b__d() at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&
completedSynchronously)
You have another post at can't find action only on live server, works fine in local server, so I'm guessing that this post is specifically related to the javascript pieces, not the server-side pieces.
It sounds like something bad happens on the server, the server sends back some type of error, and the your error handler (in javascript) dies when trying to handle that response.
I get Uncaught SyntaxError: Unexpected token B. Which seems to point
to JSON parsing failure.
That sounds quite reasonable. Let's look at the code:
.ajax({
...
error: function (xhr, textStatus, errorThrown) {
var errorData = $.parseJSON(xhr.responseText);
var errorMessages = [];
...
},
...
});
I would highly recommend taking a look at what xhr.responseText is. My guess it that it does not contain valid JSON, so the parseJSON method throws the 'Unexpected token B' error.
To look at this value, you could put console.log(xhr.responseText); or you could use a tool like the javascript debugger in your web browser or fiddler to see what is there.
My guess is that the server is sending back a string with something like There was an error on the server instead of JSON like you are expecting. I see that you have error handling built in - my guess is that there is an error within your error handling, and there is nothing to catch it. I would recommend doing debugging on the server side to see if there is an error somewhere that you are not expecting.
Perhaps profile.messages is something that can only be enumerated once, and when you try to do it again it throws an error. Or maybe DB.SaveChanges is throwing an error for some reason. Either of these would result in the logged message that you see with the behavior you see on the client side.
You are attempting to return a 400 response (Bad Request) with your own custom response content.
I think that IIS by default doesn't allow you to do this, and as CodeThug mentioned, may be replacing your custom JSON content with a server message.
But it appears that you can override this behaviour:
http://develoq.net/2011/returning-a-body-content-with-400-http-status-code/
<system.webServer>
<httpErrors existingResponse="PassThrough"></httpErrors>
</system.webServer>
I have received similar mysterious errors in the past when using ASP.NET script bundling on knockout and bootstrap, especially when including the already-minified versions in a bundle.
If you are running in DEBUG mode on localhost, then ASP.NET will not be minifying the javascript libraries. However, once you deploy, you are presumably no longer in DEBUG mode and now minifying/bundling the scripts. Sometimes the bundling/minification of these scripts can result in syntax errors similar to the one you posted.
If so, you may be able to load knockout from a CDN to avoid the need for bundling.
It seems JSON sending as the response from the server is badly generated
ex: if a value in the database is hi "my" friends
JSON file will be generated as text:"hi "my" friends"
so value for property text is badly generated.
double check values in production/development server for such values.
best practice is replace quotes with escape character
ex: text:"hi \"my\" friends"

IE9 JSON Data "do you want to open or save this file"

Started testing my jQuery applications with IE9. Looks like I may be in for some trouble here.
I noticed that when I return JSON data back to the Javascript methods I always get this Prompt that says: "Do you want to open or save this file?" and provides me with 3 buttons: Open, Save and Cancel. Of course, my javascript is taking actions based on the values set in the JSON object but since IE9 doesn't pass it over to the script, I cannot execute the follow up action from there on.
Anyone else facing this issue? Here is a snapshot.
If anyone is using ASP.net MVC and trying to fix this issue - I used the following built in methods in the MVC framework. Simply update the content Type and encoding on the JsonResult.
public ActionResult Index(int id)
{
// Fetch some data
var someData = GetSomeData();
// Return and update content type and encoding
return Json(someData, "text/html", System.Text.Encoding.UTF8,
JsonRequestBehavior.AllowGet);
}
This fixed the issue for me!
(Answer originally posted for this question.)
If using MVC, one way of handling this is to implement a base controller in which you override (hide) the Json(object) method as follows:
public class ExtendedController : Controller
{
protected new JsonResult Json(object data)
{
if (!Request.AcceptTypes.Contains("application/json"))
return base.Json(data, "text/plain");
else
return base.Json(data);
}
}
Now, your controllers can all inherit ExtendedController and simply call return Json(model); ...
without modifying the response content type for those browsers which play nicely (not <=IE9 !)
without having to remember to use Json(data, "text/plain") in your various Ajax action methods
This works with json requests which would otherwise display the "Open or Save" message in IE8 & IE9 such as those made by jQuery File Upload
I also faced this problem yesterday with WebAPI which returned a list of URLs (of asynchronously uploaded files).
Just set content type to "text/html" instead of default "application/json; charset=UTF-8" of WebAPI services. I got response as a JSON string and then used $.parseJSON to convert it to JSON object.
public async Task<HttpResponseMessage> Upload()
{
// ...
var response = Request.CreateResponse(HttpStatusCode.OK, files);
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
return response;
}
// result is an iframe's body content that received response.
$.each($.parseJSON(result.html()), function (i, item)
{
console.log(item.Url);
});
In my case when contentType in response header is "application/json; charset=UTF-8", the IE 9 shows that Prompt. But changed to "text/html" then the prompt does not show, although all otter browsers are fine with the "application/json; charset=UTF-8".
Actually, you were right #EricLaw. After setting the content type in the Json result, it worked.
I had to add the following lines:
result.ContentEncoding = System.Text.Encoding.UTF8;
result.ContentType = "application/json; charset=UTF-8